[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