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 <jasuarez@igalia.com>
This commit is contained in:
Jason Ekstrand 2017-04-26 09:53:45 -07:00
parent d3ed72e2c2
commit bcc5d0defb
1 changed files with 18 additions and 10 deletions

View File

@ -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