gallium: Several fixes to buffer caching.
This commit is contained in:
@@ -192,6 +192,17 @@ pb_reference(struct pb_buffer **dst,
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Utility function to check whether a requested alignment is consistent with
|
||||
* the provided alignment or not.
|
||||
*/
|
||||
static INLINE int
|
||||
pb_check_alignment(size_t requested, size_t provided)
|
||||
{
|
||||
return requested <= provided && (provided % requested) == 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Malloc-based buffer to store data that can't be used by the graphics
|
||||
* hardware.
|
||||
|
||||
@@ -136,7 +136,7 @@ _pb_cache_buffer_list_check_free(struct pb_cache_manager *mgr)
|
||||
while(curr != &mgr->delayed) {
|
||||
buf = LIST_ENTRY(struct pb_cache_buffer, curr, head);
|
||||
|
||||
if(util_time_timeout(&buf->start, &buf->end, &now) != 0)
|
||||
if(!util_time_timeout(&buf->start, &buf->end, &now))
|
||||
break;
|
||||
|
||||
_pb_cache_buffer_destroy(buf);
|
||||
@@ -202,6 +202,24 @@ pb_cache_buffer_vtbl = {
|
||||
};
|
||||
|
||||
|
||||
static INLINE boolean
|
||||
pb_cache_is_buffer_compat(struct pb_cache_buffer *buf,
|
||||
size_t size,
|
||||
const struct pb_desc *desc)
|
||||
{
|
||||
/* TODO: be more lenient with size */
|
||||
if(buf->base.base.size != size)
|
||||
return FALSE;
|
||||
|
||||
if(!pb_check_alignment(desc->alignment, buf->base.base.alignment))
|
||||
return FALSE;
|
||||
|
||||
/* XXX: check usage too? */
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static struct pb_buffer *
|
||||
pb_cache_manager_create_buffer(struct pb_manager *_mgr,
|
||||
size_t size,
|
||||
@@ -209,30 +227,46 @@ pb_cache_manager_create_buffer(struct pb_manager *_mgr,
|
||||
{
|
||||
struct pb_cache_manager *mgr = pb_cache_manager(_mgr);
|
||||
struct pb_cache_buffer *buf;
|
||||
struct pb_cache_buffer *curr_buf;
|
||||
struct list_head *curr, *next;
|
||||
struct util_time now;
|
||||
|
||||
util_time_get(&now);
|
||||
_glthread_LOCK_MUTEX(mgr->mutex);
|
||||
|
||||
buf = NULL;
|
||||
curr = mgr->delayed.next;
|
||||
next = curr->next;
|
||||
|
||||
/* search in the expired buffers, freeing them in the process */
|
||||
util_time_get(&now);
|
||||
while(curr != &mgr->delayed) {
|
||||
buf = LIST_ENTRY(struct pb_cache_buffer, curr, head);
|
||||
|
||||
if(buf->base.base.size == size &&
|
||||
buf->base.base.alignment >= desc->alignment &&
|
||||
(buf->base.base.alignment % desc->alignment) == 0 &&
|
||||
/* buf->base.base.usage == usage */ 1) {
|
||||
++buf->base.base.refcount;
|
||||
return &buf->base;
|
||||
}
|
||||
|
||||
if(util_time_timeout(&buf->start, &buf->end, &now) != 0)
|
||||
_pb_cache_buffer_destroy(buf);
|
||||
|
||||
curr_buf = LIST_ENTRY(struct pb_cache_buffer, curr, head);
|
||||
if(!buf && pb_cache_is_buffer_compat(curr_buf, size, desc))
|
||||
buf = curr_buf;
|
||||
else if(util_time_timeout(&curr_buf->start, &curr_buf->end, &now))
|
||||
_pb_cache_buffer_destroy(curr_buf);
|
||||
curr = next;
|
||||
next = curr->next;
|
||||
}
|
||||
|
||||
/* keep searching in the hot buffers */
|
||||
while(!buf && curr != &mgr->delayed) {
|
||||
curr_buf = LIST_ENTRY(struct pb_cache_buffer, curr, head);
|
||||
if(pb_cache_is_buffer_compat(curr_buf, size, desc))
|
||||
buf = curr_buf;
|
||||
curr = next;
|
||||
next = curr->next;
|
||||
}
|
||||
|
||||
if(buf) {
|
||||
LIST_DEL(&buf->head);
|
||||
_glthread_UNLOCK_MUTEX(mgr->mutex);
|
||||
++buf->base.base.refcount;
|
||||
return &buf->base;
|
||||
}
|
||||
|
||||
_glthread_UNLOCK_MUTEX(mgr->mutex);
|
||||
|
||||
buf = CALLOC_STRUCT(pb_cache_buffer);
|
||||
if(!buf)
|
||||
return NULL;
|
||||
@@ -243,6 +277,11 @@ pb_cache_manager_create_buffer(struct pb_manager *_mgr,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
assert(buf->buffer->base.refcount >= 1);
|
||||
assert(pb_check_alignment(desc->alignment, buf->buffer->base.alignment));
|
||||
assert((buf->buffer->base.usage & desc->usage) == desc->usage);
|
||||
assert(buf->buffer->base.size >= size);
|
||||
|
||||
buf->base.base.refcount = 1;
|
||||
buf->base.base.alignment = buf->buffer->base.alignment;
|
||||
buf->base.base.usage = buf->buffer->base.usage;
|
||||
|
||||
@@ -304,13 +304,6 @@ out_err0:
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
check_alignment(size_t requested, size_t provided)
|
||||
{
|
||||
return requested <= provided && (provided % requested) == 0;
|
||||
}
|
||||
|
||||
|
||||
static struct pb_buffer *
|
||||
pb_slab_manager_create_buffer(struct pb_manager *_mgr,
|
||||
size_t size,
|
||||
@@ -328,11 +321,11 @@ pb_slab_manager_create_buffer(struct pb_manager *_mgr,
|
||||
return NULL;
|
||||
|
||||
/* check if we can provide the requested alignment */
|
||||
assert(check_alignment(desc->alignment, mgr->desc.alignment));
|
||||
if(!check_alignment(desc->alignment, mgr->desc.alignment))
|
||||
assert(pb_check_alignment(desc->alignment, mgr->desc.alignment));
|
||||
if(!pb_check_alignment(desc->alignment, mgr->desc.alignment))
|
||||
return NULL;
|
||||
assert(check_alignment(desc->alignment, mgr->bufSize));
|
||||
if(!check_alignment(desc->alignment, mgr->bufSize))
|
||||
assert(pb_check_alignment(desc->alignment, mgr->bufSize));
|
||||
if(!pb_check_alignment(desc->alignment, mgr->bufSize))
|
||||
return NULL;
|
||||
|
||||
/* XXX: check for compatible buffer usage too? */
|
||||
|
||||
Reference in New Issue
Block a user