anv/allocator: Use a signed 32-bit offset for the free list
authorJason Ekstrand <jason.ekstrand@intel.com>
Tue, 15 Sep 2015 22:00:43 +0000 (15:00 -0700)
committerJason Ekstrand <jason.ekstrand@intel.com>
Fri, 18 Sep 2015 00:44:20 +0000 (17:44 -0700)
This has the unfortunate side-effect of making it so that we can't have a
block pool bigger than 1GB.  However, that's unlikely to happen and, for
the sake of bi-directional block pools, we need to negative offsets.

src/vulkan/anv_allocator.c
src/vulkan/anv_private.h

index 1b116a3a49a681a06783a024740c6a0a989fb507..6c7c85d5e74636a496a12bd2b9b3e9fa8345c2cd 100644 (file)
@@ -151,7 +151,7 @@ round_to_power_of_two(uint32_t value)
 }
 
 static bool
-anv_free_list_pop(union anv_free_list *list, void **map, uint32_t *offset)
+anv_free_list_pop(union anv_free_list *list, void **map, int32_t *offset)
 {
    union anv_free_list current, new, old;
 
@@ -164,7 +164,7 @@ anv_free_list_pop(union anv_free_list *list, void **map, uint32_t *offset)
        */
       __sync_synchronize();
 
-      uint32_t *next_ptr = *map + current.offset;
+      int32_t *next_ptr = *map + current.offset;
       new.offset = VG_NOACCESS_READ(next_ptr);
       new.count = current.count + 1;
       old.u64 = __sync_val_compare_and_swap(&list->u64, current.u64, new.u64);
@@ -179,10 +179,10 @@ anv_free_list_pop(union anv_free_list *list, void **map, uint32_t *offset)
 }
 
 static void
-anv_free_list_push(union anv_free_list *list, void *map, uint32_t offset)
+anv_free_list_push(union anv_free_list *list, void *map, int32_t offset)
 {
    union anv_free_list current, old, new;
-   uint32_t *next_ptr = map + offset;
+   int32_t *next_ptr = map + offset;
 
    old = *list;
    do {
@@ -307,6 +307,12 @@ anv_block_pool_grow(struct anv_block_pool *pool, uint32_t old_size)
       size = old_size * 2;
    }
 
+   /* We can't have a block pool bigger than 1GB because we use signed
+    * 32-bit offsets in the free list and we don't want overflow.  We
+    * should never need a block pool bigger than 1GB anyway.
+    */
+   assert(size <= (1u << 31));
+
    cleanup = anv_vector_add(&pool->mmap_cleanups);
    if (!cleanup)
       goto fail;
@@ -356,11 +362,12 @@ fail:
 uint32_t
 anv_block_pool_alloc(struct anv_block_pool *pool)
 {
-   uint32_t offset;
+   int32_t offset;
    struct anv_block_state state, old, new;
 
    /* Try free list first. */
    if (anv_free_list_pop(&pool->free_list, &pool->map, &offset)) {
+      assert(offset >= 0);
       assert(pool->map);
       return offset;
    }
@@ -411,12 +418,14 @@ static uint32_t
 anv_fixed_size_state_pool_alloc(struct anv_fixed_size_state_pool *pool,
                                 struct anv_block_pool *block_pool)
 {
-   uint32_t offset;
+   int32_t offset;
    struct anv_block_state block, old, new;
 
    /* Try free list first. */
-   if (anv_free_list_pop(&pool->free_list, &block_pool->map, &offset))
+   if (anv_free_list_pop(&pool->free_list, &block_pool->map, &offset)) {
+      assert(offset >= 0);
       return offset;
+   }
 
    /* If free list was empty (or somebody raced us and took the items) we
     * allocate a new item from the end of the block */
index 5931e0af98d6c37ef36d108d685f7807a31c3ee8..ef7c7083bb0f60bd8d112800eadf27379489ed39 100644 (file)
@@ -229,7 +229,7 @@ struct anv_bo {
  */
 union anv_free_list {
    struct {
-      uint32_t offset;
+      int32_t offset;
 
       /* A simple count that is incremented every time the head changes. */
       uint32_t count;