static void pb_cache_manager_destroy(struct pb_manager *_mgr) { struct pb_cache_manager *mgr = pb_cache_manager(_mgr); pb_cache_deinit(&mgr->cache); FREE(mgr); }
static void pb_cache_manager_flush(struct pb_manager *_mgr) { struct pb_cache_manager *mgr = pb_cache_manager(_mgr); pb_cache_release_all_buffers(&mgr->cache); assert(mgr->provider->flush); if(mgr->provider->flush) mgr->provider->flush(mgr->provider); }
static struct pb_buffer * pb_cache_manager_create_buffer(struct pb_manager *_mgr, pb_size size, const struct pb_desc *desc) { struct pb_cache_manager *mgr = pb_cache_manager(_mgr); struct pb_cache_buffer *buf; /* get a buffer from the cache */ buf = (struct pb_cache_buffer *) pb_cache_reclaim_buffer(&mgr->cache, size, desc->alignment, desc->usage, 0); if (buf) return &buf->base; /* create a new one */ buf = CALLOC_STRUCT(pb_cache_buffer); if (!buf) return NULL; buf->buffer = mgr->provider->create_buffer(mgr->provider, size, desc); /* Empty the cache and try again. */ if (!buf->buffer) { pb_cache_release_all_buffers(&mgr->cache); buf->buffer = mgr->provider->create_buffer(mgr->provider, size, desc); } if(!buf->buffer) { FREE(buf); return NULL; } assert(pipe_is_referenced(&buf->buffer->reference)); assert(pb_check_alignment(desc->alignment, buf->buffer->alignment)); assert(buf->buffer->size >= size); pipe_reference_init(&buf->base.reference, 1); buf->base.alignment = buf->buffer->alignment; buf->base.usage = buf->buffer->usage; buf->base.size = buf->buffer->size; buf->base.vtbl = &pb_cache_buffer_vtbl; buf->mgr = mgr; pb_cache_init_entry(&mgr->cache, &buf->cache_entry, &buf->base, 0); return &buf->base; }
static void pb_cache_manager_flush(struct pb_manager *_mgr) { struct pb_cache_manager *mgr = pb_cache_manager(_mgr); struct list_head *curr, *next; struct pb_cache_buffer *buf; pipe_mutex_lock(mgr->mutex); curr = mgr->delayed.next; next = curr->next; while(curr != &mgr->delayed) { buf = LIST_ENTRY(struct pb_cache_buffer, curr, head); _pb_cache_buffer_destroy(buf); curr = next; next = curr->next; } pipe_mutex_unlock(mgr->mutex); assert(mgr->provider->flush); if(mgr->provider->flush) mgr->provider->flush(mgr->provider); }
static struct pb_buffer * pb_cache_manager_create_buffer(struct pb_manager *_mgr, pb_size size, const struct pb_desc *desc) { 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; int64_t now; pipe_mutex_lock(mgr->mutex); buf = NULL; curr = mgr->delayed.next; next = curr->next; /* search in the expired buffers, freeing them in the process */ now = os_time_get(); while(curr != &mgr->delayed) { 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(os_time_timeout(curr_buf->start, curr_buf->end, now)) _pb_cache_buffer_destroy(curr_buf); else /* This buffer (and all hereafter) are still hot in cache */ break; curr = next; next = curr->next; } /* keep searching in the hot buffers */ if(!buf) { while(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; break; } /* no need to check the timeout here */ curr = next; next = curr->next; } } if(buf) { LIST_DEL(&buf->head); pipe_mutex_unlock(mgr->mutex); /* Increase refcount */ pipe_reference_init(&buf->base.base.reference, 1); return &buf->base; } pipe_mutex_unlock(mgr->mutex); buf = CALLOC_STRUCT(pb_cache_buffer); if(!buf) return NULL; buf->buffer = mgr->provider->create_buffer(mgr->provider, size, desc); if(!buf->buffer) { FREE(buf); return NULL; } assert(pipe_is_referenced(&buf->buffer->base.reference)); assert(pb_check_alignment(desc->alignment, buf->buffer->base.alignment)); assert(pb_check_usage(desc->usage, buf->buffer->base.usage)); assert(buf->buffer->base.size >= size); pipe_reference_init(&buf->base.base.reference, 1); buf->base.base.alignment = buf->buffer->base.alignment; buf->base.base.usage = buf->buffer->base.usage; buf->base.base.size = buf->buffer->base.size; buf->base.vtbl = &pb_cache_buffer_vtbl; buf->mgr = mgr; return &buf->base; }