From bcc5d0defb992232155969314618714c63d6ccad Mon Sep 17 00:00:00 2001 From: Jason Ekstrand Date: Wed, 26 Apr 2017 09:53:45 -0700 Subject: [PATCH] anv/allocator: Tweak the block pool growing algorithm The old algorithm worked fine assuming a constant block size. We're about to break that assumption so we need an algorithm that's a bit more robust against suddenly growing by a huge amount compared to the currently allocated quantity of memory. Reviewed-by: Juan A. Suarez Romero --- src/intel/vulkan/anv_allocator.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/src/intel/vulkan/anv_allocator.c b/src/intel/vulkan/anv_allocator.c index 63f0f9cabca..e90689d7f09 100644 --- a/src/intel/vulkan/anv_allocator.c +++ b/src/intel/vulkan/anv_allocator.c @@ -435,7 +435,6 @@ static uint32_t anv_block_pool_grow(struct anv_block_pool *pool, struct anv_block_state *state, uint32_t block_size) { - uint32_t size; VkResult result = VK_SUCCESS; pthread_mutex_lock(&pool->device->mutex); @@ -460,9 +459,19 @@ anv_block_pool_grow(struct anv_block_pool *pool, struct anv_block_state *state, uint32_t old_size = pool->bo.size; - if (old_size != 0 && - back_used * 2 <= pool->center_bo_offset && - front_used * 2 <= (old_size - pool->center_bo_offset)) { + /* The block pool is always initialized to a nonzero size and this function + * is always called after initialization. + */ + assert(old_size > 0); + + /* The back_used and front_used may actually be smaller than the actual + * requirement because they are based on the next pointers which are + * updated prior to calling this function. + */ + uint32_t back_required = MAX2(back_used, pool->center_bo_offset); + uint32_t front_required = MAX2(front_used, old_size - pool->center_bo_offset); + + if (back_used * 2 <= back_required && front_used * 2 <= front_required) { /* If we're in this case then this isn't the firsta allocation and we * already have enough space on both sides to hold double what we * have allocated. There's nothing for us to do. @@ -470,12 +479,11 @@ anv_block_pool_grow(struct anv_block_pool *pool, struct anv_block_state *state, goto done; } - if (old_size == 0) { - /* This is the first allocation */ - size = MAX2(32 * block_size, PAGE_SIZE); - } else { - size = old_size * 2; - } + uint32_t size = old_size * 2; + while (size < back_required + front_required) + size *= 2; + + assert(size > pool->bo.size); /* 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