From: "Zbigniew Kempczyński" <zbigniew.kempczynski@intel.com>
To: igt-dev@lists.freedesktop.org
Subject: [igt-dev] [PATCH i-g-t v2 3/5] lib/intel_allocator_reloc: Introduce stateful allocations in reloc
Date: Mon, 5 Dec 2022 21:27:06 +0100 [thread overview]
Message-ID: <20221205202708.76217-4-zbigniew.kempczynski@intel.com> (raw)
In-Reply-To: <20221205202708.76217-1-zbigniew.kempczynski@intel.com>
Till now reloc allocator was stateless - that means if we would
call alloc() twice for same handle + size, we would get consecutive
offsets (according to size and alignment). This is problematic
in library code, where we get handle and we would like to get offset
which must be same like in the caller. It wasn't possible thus library
instead of alloc() has to get offset from the caller instead. For
single object it is not big problem but passing more makes prototype
much longer and usage is inconvinient.
Introducing stateful allocations tracking in reloc solves this issue
- alloc() can be called many times in dependent code and same offset
will be returned until free().
Tracking was added to alloc()/free() only - reserve()/unreserve()
are not handled by reloc allocator at the moment at all.
Signed-off-by: Zbigniew Kempczyński <zbigniew.kempczynski@intel.com>
---
lib/intel_allocator_reloc.c | 115 ++++++++++++++++++++++++++-----
tests/i915/api_intel_allocator.c | 21 ++++--
2 files changed, 111 insertions(+), 25 deletions(-)
diff --git a/lib/intel_allocator_reloc.c b/lib/intel_allocator_reloc.c
index ee3ad43f4a..60cbb88511 100644
--- a/lib/intel_allocator_reloc.c
+++ b/lib/intel_allocator_reloc.c
@@ -9,11 +9,13 @@
#include "igt_x86.h"
#include "igt_rand.h"
#include "intel_allocator.h"
+#include "igt_map.h"
struct intel_allocator *
intel_allocator_reloc_create(int fd, uint64_t start, uint64_t end);
struct intel_allocator_reloc {
+ struct igt_map *objects;
uint32_t prng;
uint64_t start;
uint64_t end;
@@ -23,9 +25,41 @@ struct intel_allocator_reloc {
uint64_t allocated_objects;
};
+struct intel_allocator_record {
+ uint32_t handle;
+ uint64_t offset;
+ uint64_t size;
+};
+
/* Keep the low 256k clear, for negative deltas */
#define BIAS (256 << 10)
+/* 2^31 + 2^29 - 2^25 + 2^22 - 2^19 - 2^16 + 1 */
+#define GOLDEN_RATIO_PRIME_32 0x9e370001UL
+
+/* 2^63 + 2^61 - 2^57 + 2^54 - 2^51 - 2^18 + 1 */
+#define GOLDEN_RATIO_PRIME_64 0x9e37fffffffc0001ULL
+
+static inline uint32_t hash_handles(const void *val)
+{
+ uint32_t hash = *(uint32_t *) val;
+
+ hash = hash * GOLDEN_RATIO_PRIME_32;
+ return hash;
+}
+
+static int equal_handles(const void *a, const void *b)
+{
+ uint32_t *key1 = (uint32_t *) a, *key2 = (uint32_t *) b;
+
+ return *key1 == *key2;
+}
+
+static void map_entry_free_func(struct igt_map_entry *entry)
+{
+ free(entry->data);
+}
+
static void intel_allocator_reloc_get_address_range(struct intel_allocator *ial,
uint64_t *startp,
uint64_t *endp)
@@ -44,25 +78,39 @@ static uint64_t intel_allocator_reloc_alloc(struct intel_allocator *ial,
uint64_t alignment,
enum allocator_strategy strategy)
{
+ struct intel_allocator_record *rec;
struct intel_allocator_reloc *ialr = ial->priv;
uint64_t offset, aligned_offset;
- (void) handle;
(void) strategy;
- aligned_offset = ALIGN(ialr->offset, alignment);
+ rec = igt_map_search(ialr->objects, &handle);
+ if (rec) {
+ offset = rec->offset;
+ igt_assert(rec->size == size);
+ } else {
+ aligned_offset = ALIGN(ialr->offset, alignment);
- /* Check we won't exceed end */
- if (aligned_offset + size > ialr->end)
- aligned_offset = ALIGN(ialr->start, alignment);
+ /* Check we won't exceed end */
+ if (aligned_offset + size > ialr->end)
+ aligned_offset = ALIGN(ialr->start, alignment);
- /* Check that the object fits in the address range */
- if (aligned_offset + size > ialr->end)
- return ALLOC_INVALID_ADDRESS;
+ /* Check that the object fits in the address range */
+ if (aligned_offset + size > ialr->end)
+ return ALLOC_INVALID_ADDRESS;
- offset = aligned_offset;
- ialr->offset = offset + size;
- ialr->allocated_objects++;
+ offset = aligned_offset;
+
+ rec = malloc(sizeof(*rec));
+ rec->handle = handle;
+ rec->offset = offset;
+ rec->size = size;
+
+ igt_map_insert(ialr->objects, &rec->handle, rec);
+
+ ialr->offset = offset + size;
+ ialr->allocated_objects++;
+ }
return offset;
}
@@ -70,30 +118,60 @@ static uint64_t intel_allocator_reloc_alloc(struct intel_allocator *ial,
static bool intel_allocator_reloc_free(struct intel_allocator *ial,
uint32_t handle)
{
+ struct intel_allocator_record *rec = NULL;
struct intel_allocator_reloc *ialr = ial->priv;
+ struct igt_map_entry *entry;
- (void) handle;
+ entry = igt_map_search_entry(ialr->objects, &handle);
+ if (entry) {
+ igt_map_remove_entry(ialr->objects, entry);
+ if (entry->data) {
+ rec = (struct intel_allocator_record *) entry->data;
+ ialr->allocated_objects--;
+ free(rec);
- ialr->allocated_objects--;
+ return true;
+ }
+ }
return false;
}
+static inline bool __same(const struct intel_allocator_record *rec,
+ uint32_t handle, uint64_t size, uint64_t offset)
+{
+ return rec->handle == handle && rec->size == size &&
+ DECANONICAL(rec->offset) == DECANONICAL(offset);
+}
+
static bool intel_allocator_reloc_is_allocated(struct intel_allocator *ial,
uint32_t handle, uint64_t size,
uint64_t offset)
{
- (void) ial;
- (void) handle;
- (void) size;
- (void) offset;
+ struct intel_allocator_record *rec;
+ struct intel_allocator_reloc *ialr;
+ bool same = false;
- return false;
+ igt_assert(ial);
+ ialr = (struct intel_allocator_reloc *) ial->priv;
+ igt_assert(ialr);
+ igt_assert(handle);
+
+ rec = igt_map_search(ialr->objects, &handle);
+ if (rec && __same(rec, handle, size, offset))
+ same = true;
+
+ return same;
}
static void intel_allocator_reloc_destroy(struct intel_allocator *ial)
{
+ struct intel_allocator_reloc *ialr;
+
igt_assert(ial);
+ ialr = (struct intel_allocator_reloc *) ial->priv;
+
+ igt_map_destroy(ialr->objects, map_entry_free_func);
free(ial->priv);
free(ial);
@@ -174,6 +252,7 @@ intel_allocator_reloc_create(int fd, uint64_t start, uint64_t end)
ialr = ial->priv = calloc(1, sizeof(*ialr));
igt_assert(ial->priv);
+ ialr->objects = igt_map_create(hash_handles, equal_handles);
ialr->prng = (uint32_t) to_user_pointer(ial);
start = max_t(uint64_t, start, BIAS);
diff --git a/tests/i915/api_intel_allocator.c b/tests/i915/api_intel_allocator.c
index b55587e549..87abd90084 100644
--- a/tests/i915/api_intel_allocator.c
+++ b/tests/i915/api_intel_allocator.c
@@ -195,6 +195,7 @@ static void basic_alloc(int fd, int cnt, uint8_t type)
igt_assert_eq(intel_allocator_close(ahnd), true);
}
+#define NUM_OBJS 128
static void reuse(int fd, uint8_t type)
{
struct test_obj obj[128], tmp;
@@ -204,15 +205,15 @@ static void reuse(int fd, uint8_t type)
ahnd = intel_allocator_open(fd, 0, type);
- for (i = 0; i < 128; i++) {
+ for (i = 0; i < NUM_OBJS; i++) {
obj[i].handle = gem_handle_gen();
obj[i].size = OBJ_SIZE;
obj[i].offset = intel_allocator_alloc(ahnd, obj[i].handle,
obj[i].size, align);
}
- /* check simple reuse */
- for (i = 0; i < 128; i++) {
+ /* check reuse */
+ for (i = 0; i < NUM_OBJS; i++) {
prev_offset = obj[i].offset;
obj[i].offset = intel_allocator_alloc(ahnd, obj[i].handle,
obj[i].size, 0);
@@ -225,7 +226,13 @@ static void reuse(int fd, uint8_t type)
/* alloc different buffer to fill freed hole */
tmp.handle = gem_handle_gen();
tmp.offset = intel_allocator_alloc(ahnd, tmp.handle, OBJ_SIZE, align);
- igt_assert(prev_offset == tmp.offset);
+
+ /* Simple will return previously returned offset if fits */
+ if (type == INTEL_ALLOCATOR_SIMPLE)
+ igt_assert(prev_offset == tmp.offset);
+ /* Reloc is moving forward for new allocations */
+ else if (type == INTEL_ALLOCATOR_RELOC)
+ igt_assert(prev_offset != tmp.offset);
obj[i].offset = intel_allocator_alloc(ahnd, obj[i].handle,
obj[i].size, 0);
@@ -785,10 +792,10 @@ igt_main
igt_dynamic("print")
basic_alloc(fd, 1UL << 2, a->type);
- if (a->type == INTEL_ALLOCATOR_SIMPLE) {
- igt_dynamic("reuse")
- reuse(fd, a->type);
+ igt_dynamic("reuse")
+ reuse(fd, a->type);
+ if (a->type == INTEL_ALLOCATOR_SIMPLE) {
igt_dynamic("reserve")
reserve(fd, a->type);
}
--
2.34.1
next prev parent reply other threads:[~2022-12-05 20:27 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-12-05 20:27 [igt-dev] [PATCH i-g-t v2 0/5] Remove random allocator and improve reloc one Zbigniew Kempczyński
2022-12-05 20:27 ` [igt-dev] [PATCH i-g-t v2 1/5] lib/intel_allocator: Remove RANDOM allocator Zbigniew Kempczyński
2022-12-06 15:56 ` Kamil Konieczny
2022-12-05 20:27 ` [igt-dev] [PATCH i-g-t v2 2/5] tests/api_intel_allocator: Remove duplicated reuse and reserve subtests Zbigniew Kempczyński
2022-12-06 15:58 ` Kamil Konieczny
2022-12-05 20:27 ` Zbigniew Kempczyński [this message]
2022-12-06 21:39 ` [igt-dev] [PATCH i-g-t v2 3/5] lib/intel_allocator_reloc: Introduce stateful allocations in reloc Kamil Konieczny
2022-12-05 20:27 ` [igt-dev] [PATCH i-g-t v2 4/5] tests/gem_ctx_shared: Remove necessity of passing offset to function call Zbigniew Kempczyński
2022-12-06 16:31 ` Kamil Konieczny
2022-12-05 20:27 ` [igt-dev] [PATCH i-g-t v2 5/5] tests/gem_exec_parallel: Avoid acquiring offset for overlapping handle Zbigniew Kempczyński
2022-12-06 17:06 ` Kamil Konieczny
2022-12-07 11:28 ` Zbigniew Kempczyński
2022-12-05 21:06 ` [igt-dev] ✓ Fi.CI.BAT: success for Remove random allocator and improve reloc one (rev2) Patchwork
2022-12-05 22:24 ` [igt-dev] ✓ Fi.CI.IGT: " Patchwork
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20221205202708.76217-4-zbigniew.kempczynski@intel.com \
--to=zbigniew.kempczynski@intel.com \
--cc=igt-dev@lists.freedesktop.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox