summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJason Ekstrand <[email protected]>2015-05-25 15:29:10 -0700
committerJason Ekstrand <[email protected]>2015-05-27 11:48:28 -0700
commit59328bac108ff6786b939bc56cfb124da87202bc (patch)
treec35936759aa6d0de7547d4a8665548214166a788 /src
parenta1d30f867dc4cfc8c779ce0b3f53c6e6d9360e24 (diff)
vk/allocator: Add a free list that acts on pointers instead of offsets
Diffstat (limited to 'src')
-rw-r--r--src/vulkan/allocator.c46
1 files changed, 46 insertions, 0 deletions
diff --git a/src/vulkan/allocator.c b/src/vulkan/allocator.c
index 17d44423342..3fc6e8e39be 100644
--- a/src/vulkan/allocator.c
+++ b/src/vulkan/allocator.c
@@ -198,6 +198,52 @@ anv_free_list_push(union anv_free_list *list, void *map, uint32_t offset)
} while (old.u64 != current.u64);
}
+/* All pointers in the ptr_free_list are assumed to be page-aligned. This
+ * means that the bottom 12 bits should all be zero.
+ */
+#define PFL_COUNT(x) ((uintptr_t)(x) & 0xfff)
+#define PFL_PTR(x) ((void *)((uintptr_t)(x) & ~0xfff))
+#define PFL_PACK(ptr, count) ({ \
+ assert(((uintptr_t)(ptr) & 0xfff) == 0); \
+ (void *)((uintptr_t)(ptr) | (uintptr_t)((count) & 0xfff)); \
+})
+
+static bool
+anv_ptr_free_list_pop(void **list, void **elem)
+{
+ void *current = *list;
+ while (PFL_PTR(current) != NULL) {
+ void **next_ptr = PFL_PTR(current);
+ void *new_ptr = VG_NOACCESS_READ(next_ptr);
+ unsigned new_count = PFL_COUNT(current) + 1;
+ void *new = PFL_PACK(new_ptr, new_count);
+ void *old = __sync_val_compare_and_swap(list, current, new);
+ if (old == current) {
+ *elem = PFL_PTR(current);
+ return true;
+ }
+ current = old;
+ }
+
+ return false;
+}
+
+static void
+anv_ptr_free_list_push(void **list, void *elem)
+{
+ void *old, *current;
+ void **next_ptr = elem;
+
+ old = *list;
+ do {
+ current = old;
+ VG_NOACCESS_WRITE(next_ptr, PFL_PTR(current));
+ unsigned new_count = PFL_COUNT(current) + 1;
+ void *new = PFL_PACK(elem, new_count);
+ old = __sync_val_compare_and_swap(list, current, new);
+ } while (old != current);
+}
+
static int
anv_block_pool_grow(struct anv_block_pool *pool);