[igt-dev] [PATCH i-g-t v34 37/38] lib/intel_allocator: Add alloc function which allows passing strategy argument
Zbigniew Kempczyński
zbigniew.kempczynski at intel.com
Tue Apr 13 13:54:40 UTC 2021
To use spinners with no-reloc we need to alloc offsets for them
from already opened allocator. As we don't know what strategy
is chosen for open (likely HIGH_TO_LOW for SIMPLE allocator) we
want to overwrite it for spinners (there's expectation they
will reside on low addresses).
Extend allocator API adding intel_allocator_alloc_with_strategy()
to support spinners rewriting.
v2: add change in api_intel_allocator test to compile properly
whole series.
Signed-off-by: Zbigniew Kempczyński <zbigniew.kempczynski at intel.com>
Cc: Jason Ekstrand <jason at jlekstrand.net>
Acked-by: Daniel Vetter <daniel.vetter at ffwll.ch>
Acked-by: Petri Latvala <petri.latvala at intel.com>
---
lib/intel_allocator.c | 47 +++++++++++++++++++++++++++-----
lib/intel_allocator.h | 10 +++++--
lib/intel_allocator_msgchannel.h | 1 +
lib/intel_allocator_random.c | 4 ++-
lib/intel_allocator_reloc.c | 4 ++-
lib/intel_allocator_simple.c | 39 ++++++++++++++------------
tests/i915/api_intel_allocator.c | 11 +++++++-
7 files changed, 86 insertions(+), 30 deletions(-)
diff --git a/lib/intel_allocator.c b/lib/intel_allocator.c
index 0b33b8b24..8a2e607c3 100644
--- a/lib/intel_allocator.c
+++ b/lib/intel_allocator.c
@@ -579,15 +579,17 @@ static int handle_request(struct alloc_req *req, struct alloc_resp *resp)
resp->alloc.offset = ial->alloc(ial,
req->alloc.handle,
req->alloc.size,
- req->alloc.alignment);
+ req->alloc.alignment,
+ req->alloc.strategy);
alloc_info("<alloc> [tid: %ld] ahnd: %" PRIx64
", ctx: %u, vm: %u, handle: %u"
", size: 0x%" PRIx64 ", offset: 0x%" PRIx64
- ", alignment: 0x%" PRIx64 "\n",
+ ", alignment: 0x%" PRIx64 ", strategy: %u\n",
(long) req->tid, req->allocator_handle,
al->ctx, al->vm,
req->alloc.handle, req->alloc.size,
- resp->alloc.offset, req->alloc.alignment);
+ resp->alloc.offset, req->alloc.alignment,
+ req->alloc.strategy);
break;
case REQ_FREE:
@@ -1040,13 +1042,15 @@ void intel_allocator_get_address_range(uint64_t allocator_handle,
* range returns ALLOC_INVALID_ADDRESS.
*/
uint64_t __intel_allocator_alloc(uint64_t allocator_handle, uint32_t handle,
- uint64_t size, uint64_t alignment)
+ uint64_t size, uint64_t alignment,
+ enum allocator_strategy strategy)
{
struct alloc_req req = { .request_type = REQ_ALLOC,
.allocator_handle = allocator_handle,
.alloc.handle = handle,
.alloc.size = size,
- .alloc.alignment = alignment };
+ .alloc.alignment = alignment,
+ .alloc.strategy = strategy };
struct alloc_resp resp;
igt_assert(handle_request(&req, &resp) == 0);
@@ -1063,7 +1067,8 @@ uint64_t __intel_allocator_alloc(uint64_t allocator_handle, uint32_t handle,
* @alignment: determines object alignment
*
* Same as __intel_allocator_alloc() but asserts if allocator can't return
- * valid address.
+ * valid address. Uses default allocation strategy chosen during opening
+ * the allocator.
*/
uint64_t intel_allocator_alloc(uint64_t allocator_handle, uint32_t handle,
uint64_t size, uint64_t alignment)
@@ -1071,12 +1076,40 @@ uint64_t intel_allocator_alloc(uint64_t allocator_handle, uint32_t handle,
uint64_t offset;
offset = __intel_allocator_alloc(allocator_handle, handle,
- size, alignment);
+ size, alignment,
+ ALLOC_STRATEGY_NONE);
igt_assert(offset != ALLOC_INVALID_ADDRESS);
return offset;
}
+/**
+ * intel_allocator_alloc_with_strategy:
+ * @allocator_handle: handle to an allocator
+ * @handle: handle to an object
+ * @size: size of an object
+ * @alignment: determines object alignment
+ * @strategy: strategy of allocation
+ *
+ * Same as __intel_allocator_alloc() but asserts if allocator can't return
+ * valid address. Use @strategy instead of default chosen during opening
+ * the allocator.
+ */
+uint64_t intel_allocator_alloc_with_strategy(uint64_t allocator_handle,
+ uint32_t handle,
+ uint64_t size, uint64_t alignment,
+ enum allocator_strategy strategy)
+{
+ uint64_t offset;
+
+ offset = __intel_allocator_alloc(allocator_handle, handle,
+ size, alignment, strategy);
+ igt_assert(offset != ALLOC_INVALID_ADDRESS);
+
+ return offset;
+}
+
+
/**
* intel_allocator_free:
* @allocator_handle: handle to an allocator
diff --git a/lib/intel_allocator.h b/lib/intel_allocator.h
index 9b7bd0908..c14f57b4d 100644
--- a/lib/intel_allocator.h
+++ b/lib/intel_allocator.h
@@ -141,7 +141,8 @@ struct intel_allocator {
void (*get_address_range)(struct intel_allocator *ial,
uint64_t *startp, uint64_t *endp);
uint64_t (*alloc)(struct intel_allocator *ial, uint32_t handle,
- uint64_t size, uint64_t alignment);
+ uint64_t size, uint64_t alignment,
+ enum allocator_strategy strategy);
bool (*is_allocated)(struct intel_allocator *ial, uint32_t handle,
uint64_t size, uint64_t alignment);
bool (*reserve)(struct intel_allocator *ial,
@@ -181,9 +182,14 @@ bool intel_allocator_close(uint64_t allocator_handle);
void intel_allocator_get_address_range(uint64_t allocator_handle,
uint64_t *startp, uint64_t *endp);
uint64_t __intel_allocator_alloc(uint64_t allocator_handle, uint32_t handle,
- uint64_t size, uint64_t alignment);
+ uint64_t size, uint64_t alignment,
+ enum allocator_strategy strategy);
uint64_t intel_allocator_alloc(uint64_t allocator_handle, uint32_t handle,
uint64_t size, uint64_t alignment);
+uint64_t intel_allocator_alloc_with_strategy(uint64_t allocator_handle,
+ uint32_t handle,
+ uint64_t size, uint64_t alignment,
+ enum allocator_strategy strategy);
bool intel_allocator_free(uint64_t allocator_handle, uint32_t handle);
bool intel_allocator_is_allocated(uint64_t allocator_handle, uint32_t handle,
uint64_t size, uint64_t offset);
diff --git a/lib/intel_allocator_msgchannel.h b/lib/intel_allocator_msgchannel.h
index ac6edfb9e..c7a738a08 100644
--- a/lib/intel_allocator_msgchannel.h
+++ b/lib/intel_allocator_msgchannel.h
@@ -65,6 +65,7 @@ struct alloc_req {
uint32_t handle;
uint64_t size;
uint64_t alignment;
+ uint8_t strategy;
} alloc;
struct {
diff --git a/lib/intel_allocator_random.c b/lib/intel_allocator_random.c
index d804e3318..3d9a78f17 100644
--- a/lib/intel_allocator_random.c
+++ b/lib/intel_allocator_random.c
@@ -45,12 +45,14 @@ static void intel_allocator_random_get_address_range(struct intel_allocator *ial
static uint64_t intel_allocator_random_alloc(struct intel_allocator *ial,
uint32_t handle, uint64_t size,
- uint64_t alignment)
+ uint64_t alignment,
+ enum allocator_strategy strategy)
{
struct intel_allocator_random *ialr = ial->priv;
uint64_t offset;
(void) handle;
+ (void) strategy;
/* randomize the address, we try to avoid relocations */
do {
diff --git a/lib/intel_allocator_reloc.c b/lib/intel_allocator_reloc.c
index abf9c30cd..e8af787b0 100644
--- a/lib/intel_allocator_reloc.c
+++ b/lib/intel_allocator_reloc.c
@@ -46,12 +46,14 @@ static void intel_allocator_reloc_get_address_range(struct intel_allocator *ial,
static uint64_t intel_allocator_reloc_alloc(struct intel_allocator *ial,
uint32_t handle, uint64_t size,
- uint64_t alignment)
+ uint64_t alignment,
+ enum allocator_strategy strategy)
{
struct intel_allocator_reloc *ialr = ial->priv;
uint64_t offset, aligned_offset;
(void) handle;
+ (void) strategy;
alignment = max(alignment, 4096);
aligned_offset = ALIGN(ialr->offset, alignment);
diff --git a/lib/intel_allocator_simple.c b/lib/intel_allocator_simple.c
index a419955af..963d8d257 100644
--- a/lib/intel_allocator_simple.c
+++ b/lib/intel_allocator_simple.c
@@ -25,12 +25,7 @@ intel_allocator_simple_create_full(int fd, uint64_t start, uint64_t end,
struct simple_vma_heap {
struct igt_list_head holes;
-
- /* If true, simple_vma_heap_alloc will prefer high addresses
- *
- * Default is true.
- */
- bool alloc_high;
+ enum allocator_strategy strategy;
};
struct simple_vma_hole {
@@ -220,14 +215,11 @@ static void simple_vma_heap_init(struct simple_vma_heap *heap,
IGT_INIT_LIST_HEAD(&heap->holes);
simple_vma_heap_free(heap, start, size);
- switch (strategy) {
- case ALLOC_STRATEGY_LOW_TO_HIGH:
- heap->alloc_high = false;
- break;
- case ALLOC_STRATEGY_HIGH_TO_LOW:
- default:
- heap->alloc_high = true;
- }
+ /* Use LOW_TO_HIGH or HIGH_TO_LOW strategy only */
+ if (strategy == ALLOC_STRATEGY_LOW_TO_HIGH)
+ heap->strategy = strategy;
+ else
+ heap->strategy = ALLOC_STRATEGY_HIGH_TO_LOW;
}
static void simple_vma_heap_finish(struct simple_vma_heap *heap)
@@ -294,7 +286,8 @@ static void simple_vma_hole_alloc(struct simple_vma_hole *hole,
static bool simple_vma_heap_alloc(struct simple_vma_heap *heap,
uint64_t *offset, uint64_t size,
- uint64_t alignment)
+ uint64_t alignment,
+ enum allocator_strategy strategy)
{
struct simple_vma_hole *hole, *tmp;
uint64_t misalign;
@@ -305,7 +298,16 @@ static bool simple_vma_heap_alloc(struct simple_vma_heap *heap,
simple_vma_heap_validate(heap);
- if (heap->alloc_high) {
+ /* Ensure we support only NONE/LOW_TO_HIGH/HIGH_TO_LOW strategies */
+ igt_assert(strategy == ALLOC_STRATEGY_NONE ||
+ strategy == ALLOC_STRATEGY_LOW_TO_HIGH ||
+ strategy == ALLOC_STRATEGY_HIGH_TO_LOW);
+
+ /* Use default strategy chosen on open */
+ if (strategy == ALLOC_STRATEGY_NONE)
+ strategy = heap->strategy;
+
+ if (strategy == ALLOC_STRATEGY_HIGH_TO_LOW) {
simple_vma_foreach_hole_safe(hole, heap, tmp) {
if (size > hole->size)
continue;
@@ -412,7 +414,8 @@ static bool simple_vma_heap_alloc_addr(struct intel_allocator_simple *ials,
static uint64_t intel_allocator_simple_alloc(struct intel_allocator *ial,
uint32_t handle, uint64_t size,
- uint64_t alignment)
+ uint64_t alignment,
+ enum allocator_strategy strategy)
{
struct intel_allocator_record *rec;
struct intel_allocator_simple *ials;
@@ -430,7 +433,7 @@ static uint64_t intel_allocator_simple_alloc(struct intel_allocator *ial,
igt_assert(rec->size == size);
} else {
if (!simple_vma_heap_alloc(&ials->heap, &offset,
- size, alignment))
+ size, alignment, strategy))
return ALLOC_INVALID_ADDRESS;
rec = malloc(sizeof(*rec));
diff --git a/tests/i915/api_intel_allocator.c b/tests/i915/api_intel_allocator.c
index 7ff92a174..182d9ba79 100644
--- a/tests/i915/api_intel_allocator.c
+++ b/tests/i915/api_intel_allocator.c
@@ -50,10 +50,19 @@ static void alloc_simple(int fd)
intel_allocator_get_address_range(ahnd, &start, &end);
offset0 = intel_allocator_alloc(ahnd, 1, end - start, 0);
- offset1 = __intel_allocator_alloc(ahnd, 2, 4096, 0);
+ offset1 = __intel_allocator_alloc(ahnd, 2, 4096, 0, ALLOC_STRATEGY_NONE);
igt_assert(offset1 == ALLOC_INVALID_ADDRESS);
intel_allocator_free(ahnd, 1);
+ offset0 = intel_allocator_alloc_with_strategy(ahnd, 1, 4096, 0,
+ ALLOC_STRATEGY_HIGH_TO_LOW);
+ offset1 = intel_allocator_alloc_with_strategy(ahnd, 2, 4096, 0,
+ ALLOC_STRATEGY_LOW_TO_HIGH);
+ igt_assert(offset0 > offset1);
+
+ intel_allocator_free(ahnd, 1);
+ intel_allocator_free(ahnd, 2);
+
igt_assert_eq(intel_allocator_close(ahnd), true);
}
--
2.26.0
More information about the igt-dev
mailing list