blob: d22f81767050a97cb56a683ca81a7eb3231275fe [file]
// SPDX-License-Identifier: MIT
/*
* Copyright © 2021 Intel Corporation
*/
#include <sys/ioctl.h>
#include <stdlib.h>
#include "igt.h"
#include "igt_x86.h"
#include "igt_rand.h"
#include "intel_allocator.h"
struct intel_allocator *
intel_allocator_random_create(int fd, uint64_t start, uint64_t end);
struct intel_allocator_random {
uint32_t prng;
uint64_t start;
uint64_t end;
/* statistics */
uint64_t allocated_objects;
};
/* Keep the low 256k clear, for negative deltas */
#define BIAS (256 << 10)
#define RETRIES 8
static void intel_allocator_random_get_address_range(struct intel_allocator *ial,
uint64_t *startp,
uint64_t *endp)
{
struct intel_allocator_random *ialr = ial->priv;
if (startp)
*startp = ialr->start;
if (endp)
*endp = ialr->end;
}
static uint64_t intel_allocator_random_alloc(struct intel_allocator *ial,
uint32_t handle, uint64_t size,
uint64_t alignment,
enum allocator_strategy strategy)
{
struct intel_allocator_random *ialr = ial->priv;
uint64_t offset;
int cnt = RETRIES;
(void) handle;
(void) strategy;
/* randomize the address, we try to avoid relocations */
do {
offset = hars_petruska_f54_1_random64(&ialr->prng);
/* maximize the chances of fitting in the last iteration */
if (cnt == 1)
offset = 0;
offset %= ialr->end - ialr->start;
offset += ialr->start;
offset = ALIGN(offset, alignment);
} while (offset + size > ialr->end && --cnt);
if (!cnt)
return ALLOC_INVALID_ADDRESS;
ialr->allocated_objects++;
return offset;
}
static bool intel_allocator_random_free(struct intel_allocator *ial,
uint32_t handle)
{
struct intel_allocator_random *ialr = ial->priv;
(void) handle;
ialr->allocated_objects--;
return false;
}
static bool intel_allocator_random_is_allocated(struct intel_allocator *ial,
uint32_t handle, uint64_t size,
uint64_t offset)
{
(void) ial;
(void) handle;
(void) size;
(void) offset;
return false;
}
static void intel_allocator_random_destroy(struct intel_allocator *ial)
{
igt_assert(ial);
free(ial->priv);
free(ial);
}
static bool intel_allocator_random_reserve(struct intel_allocator *ial,
uint32_t handle,
uint64_t start, uint64_t end)
{
(void) ial;
(void) handle;
(void) start;
(void) end;
return false;
}
static bool intel_allocator_random_unreserve(struct intel_allocator *ial,
uint32_t handle,
uint64_t start, uint64_t end)
{
(void) ial;
(void) handle;
(void) start;
(void) end;
return false;
}
static bool intel_allocator_random_is_reserved(struct intel_allocator *ial,
uint64_t start, uint64_t end)
{
(void) ial;
(void) start;
(void) end;
return false;
}
static void intel_allocator_random_print(struct intel_allocator *ial, bool full)
{
struct intel_allocator_random *ialr = ial->priv;
(void) full;
igt_info("<ial: %p, fd: %d> allocated objects: %" PRIx64 "\n",
ial, ial->fd, ialr->allocated_objects);
}
static bool intel_allocator_random_is_empty(struct intel_allocator *ial)
{
struct intel_allocator_random *ialr = ial->priv;
return !ialr->allocated_objects;
}
struct intel_allocator *
intel_allocator_random_create(int fd, uint64_t start, uint64_t end)
{
struct intel_allocator *ial;
struct intel_allocator_random *ialr;
igt_debug("Using random allocator\n");
ial = calloc(1, sizeof(*ial));
igt_assert(ial);
ial->fd = fd;
ial->get_address_range = intel_allocator_random_get_address_range;
ial->alloc = intel_allocator_random_alloc;
ial->free = intel_allocator_random_free;
ial->is_allocated = intel_allocator_random_is_allocated;
ial->reserve = intel_allocator_random_reserve;
ial->unreserve = intel_allocator_random_unreserve;
ial->is_reserved = intel_allocator_random_is_reserved;
ial->destroy = intel_allocator_random_destroy;
ial->print = intel_allocator_random_print;
ial->is_empty = intel_allocator_random_is_empty;
ialr = ial->priv = calloc(1, sizeof(*ialr));
igt_assert(ial->priv);
ialr->prng = (uint32_t) to_user_pointer(ial);
start = max_t(uint64_t, start, BIAS);
igt_assert(start < end);
ialr->start = start;
ialr->end = end;
ialr->allocated_objects = 0;
return ial;
}