Go to the source code of this file.
Data Structures | |
struct | pb_slab_buffer |
Buffer in a slab. More... | |
struct | pb_slab |
Slab -- a contiguous piece of memory. More... | |
struct | pb_slab_manager |
It adds/removes slabs as needed in order to meet the allocation/destruction of individual buffers. More... | |
struct | pb_slab_range_manager |
Wrapper around several slabs, therefore capable of handling buffers of multiple sizes. More... | |
Functions | |
static struct pb_slab_buffer * | pb_slab_buffer (struct pb_buffer *buf) |
static struct pb_slab_manager * | pb_slab_manager (struct pb_manager *mgr) |
static struct pb_slab_range_manager * | pb_slab_range_manager (struct pb_manager *mgr) |
static void | pb_slab_buffer_destroy (struct pb_buffer *_buf) |
Delete a buffer from the slab delayed list and put it on the slab FREE list. | |
static void * | pb_slab_buffer_map (struct pb_buffer *_buf, unsigned flags) |
static void | pb_slab_buffer_unmap (struct pb_buffer *_buf) |
static void | pb_slab_buffer_get_base_buffer (struct pb_buffer *_buf, struct pb_buffer **base_buf, unsigned *offset) |
static enum pipe_error | pb_slab_create (struct pb_slab_manager *mgr) |
Create a new slab. | |
static struct pb_buffer * | pb_slab_manager_create_buffer (struct pb_manager *_mgr, size_t size, const struct pb_desc *desc) |
static void | pb_slab_manager_flush (struct pb_manager *_mgr) |
static void | pb_slab_manager_destroy (struct pb_manager *_mgr) |
struct pb_manager * | pb_slab_manager_create (struct pb_manager *provider, size_t bufSize, size_t slabSize, const struct pb_desc *desc) |
Slab sub-allocator. | |
static struct pb_buffer * | pb_slab_range_manager_create_buffer (struct pb_manager *_mgr, size_t size, const struct pb_desc *desc) |
static void | pb_slab_range_manager_flush (struct pb_manager *_mgr) |
static void | pb_slab_range_manager_destroy (struct pb_manager *_mgr) |
struct pb_manager * | pb_slab_range_manager_create (struct pb_manager *provider, size_t minBufSize, size_t maxBufSize, size_t slabSize, const struct pb_desc *desc) |
Allow a range of buffer size, by aggregating multiple slabs sub-allocators with different bucket sizes. | |
Variables | |
static struct pb_vtbl | pb_slab_buffer_vtbl |
Definition in file pb_bufmgr_slab.c.
static struct pb_slab_buffer* pb_slab_buffer | ( | struct pb_buffer * | buf | ) | [static, read] |
Definition at line 168 of file pb_bufmgr_slab.c.
References assert.
00169 { 00170 assert(buf); 00171 return (struct pb_slab_buffer *)buf; 00172 }
static void pb_slab_buffer_destroy | ( | struct pb_buffer * | _buf | ) | [static] |
Delete a buffer from the slab delayed list and put it on the slab FREE list.
Definition at line 196 of file pb_bufmgr_slab.c.
References assert, pb_buffer::base, pb_slab_buffer::base, pb_slab::bo, pb_slab::buffers, FREE, pb_slab::freeBuffers, pb_slab::head, pb_slab_buffer::head, list, LIST_ADDTAIL, LIST_DEL, LIST_DELINIT, pb_slab_buffer::mapCount, pb_slab::mgr, pb_slab_manager::mutex, list_head::next, pb_slab::numBuffers, pb_slab::numFree, pb_reference(), pb_slab_buffer(), pipe_mutex_lock, pipe_mutex_unlock, pipe_buffer::refcount, pb_slab_buffer::slab, and pb_slab_manager::slabs.
00197 { 00198 struct pb_slab_buffer *buf = pb_slab_buffer(_buf); 00199 struct pb_slab *slab = buf->slab; 00200 struct pb_slab_manager *mgr = slab->mgr; 00201 struct list_head *list = &buf->head; 00202 00203 pipe_mutex_lock(mgr->mutex); 00204 00205 assert(buf->base.base.refcount == 0); 00206 00207 buf->mapCount = 0; 00208 00209 LIST_DEL(list); 00210 LIST_ADDTAIL(list, &slab->freeBuffers); 00211 slab->numFree++; 00212 00213 if (slab->head.next == &slab->head) 00214 LIST_ADDTAIL(&slab->head, &mgr->slabs); 00215 00216 /* If the slab becomes totally empty, free it */ 00217 if (slab->numFree == slab->numBuffers) { 00218 list = &slab->head; 00219 LIST_DELINIT(list); 00220 pb_reference(&slab->bo, NULL); 00221 FREE(slab->buffers); 00222 FREE(slab); 00223 } 00224 00225 pipe_mutex_unlock(mgr->mutex); 00226 }
static void pb_slab_buffer_get_base_buffer | ( | struct pb_buffer * | _buf, | |
struct pb_buffer ** | base_buf, | |||
unsigned * | offset | |||
) | [static] |
Definition at line 252 of file pb_bufmgr_slab.c.
References pb_slab::bo, pb_get_base_buffer(), pb_slab_buffer(), pb_slab_buffer::slab, and pb_slab_buffer::start.
00255 { 00256 struct pb_slab_buffer *buf = pb_slab_buffer(_buf); 00257 pb_get_base_buffer(buf->slab->bo, base_buf, offset); 00258 *offset += buf->start; 00259 }
static void* pb_slab_buffer_map | ( | struct pb_buffer * | _buf, | |
unsigned | flags | |||
) | [static] |
Definition at line 230 of file pb_bufmgr_slab.c.
References pb_slab_buffer::mapCount, pb_slab_buffer(), pb_slab_buffer::slab, pb_slab_buffer::start, and pb_slab::virtual.
00232 { 00233 struct pb_slab_buffer *buf = pb_slab_buffer(_buf); 00234 00235 ++buf->mapCount; 00236 return (void *) ((uint8_t *) buf->slab->virtual + buf->start); 00237 }
static void pb_slab_buffer_unmap | ( | struct pb_buffer * | _buf | ) | [static] |
Definition at line 241 of file pb_bufmgr_slab.c.
References pb_slab_buffer::event, pb_slab_buffer::mapCount, pb_slab_buffer(), and pipe_condvar_broadcast.
00242 { 00243 struct pb_slab_buffer *buf = pb_slab_buffer(_buf); 00244 00245 --buf->mapCount; 00246 if (buf->mapCount == 0) 00247 pipe_condvar_broadcast(buf->event); 00248 }
static enum pipe_error pb_slab_create | ( | struct pb_slab_manager * | mgr | ) | [static] |
Create a new slab.
Called when we ran out of free slabs.
Definition at line 277 of file pb_bufmgr_slab.c.
References pipe_buffer::alignment, pb_slab_buffer::base, pb_buffer::base, pb_slab::bo, pb_slab::buffers, pb_slab_manager::bufSize, CALLOC, CALLOC_STRUCT, pb_manager::create_buffer, pb_slab_manager::desc, pb_slab_buffer::event, FREE, pb_slab::freeBuffers, pb_slab_buffer::head, pb_slab::head, LIST_ADDTAIL, LIST_INITHEAD, pb_slab_buffer::mapCount, pb_slab::mgr, pb_slab::numBuffers, pb_slab::numFree, pb_map(), pb_reference(), pb_unmap(), PIPE_BUFFER_USAGE_CPU_READ, PIPE_BUFFER_USAGE_CPU_WRITE, pipe_condvar_init, PIPE_ERROR_OUT_OF_MEMORY, PIPE_OK, pb_slab_manager::provider, pipe_buffer::refcount, pipe_buffer::size, pb_slab_buffer::slab, pb_slab_manager::slabs, pb_slab_manager::slabSize, pb_slab_buffer::start, pipe_buffer::usage, pb_slab::virtual, and pb_buffer::vtbl.
00278 { 00279 struct pb_slab *slab; 00280 struct pb_slab_buffer *buf; 00281 unsigned numBuffers; 00282 unsigned i; 00283 enum pipe_error ret; 00284 00285 slab = CALLOC_STRUCT(pb_slab); 00286 if (!slab) 00287 return PIPE_ERROR_OUT_OF_MEMORY; 00288 00289 slab->bo = mgr->provider->create_buffer(mgr->provider, mgr->slabSize, &mgr->desc); 00290 if(!slab->bo) { 00291 ret = PIPE_ERROR_OUT_OF_MEMORY; 00292 goto out_err0; 00293 } 00294 00295 /* Note down the slab virtual address. All mappings are accessed directly 00296 * through this address so it is required that the buffer is pinned. */ 00297 slab->virtual = pb_map(slab->bo, 00298 PIPE_BUFFER_USAGE_CPU_READ | 00299 PIPE_BUFFER_USAGE_CPU_WRITE); 00300 if(!slab->virtual) { 00301 ret = PIPE_ERROR_OUT_OF_MEMORY; 00302 goto out_err1; 00303 } 00304 pb_unmap(slab->bo); 00305 00306 numBuffers = slab->bo->base.size / mgr->bufSize; 00307 00308 slab->buffers = CALLOC(numBuffers, sizeof(*slab->buffers)); 00309 if (!slab->buffers) { 00310 ret = PIPE_ERROR_OUT_OF_MEMORY; 00311 goto out_err1; 00312 } 00313 00314 LIST_INITHEAD(&slab->head); 00315 LIST_INITHEAD(&slab->freeBuffers); 00316 slab->numBuffers = numBuffers; 00317 slab->numFree = 0; 00318 slab->mgr = mgr; 00319 00320 buf = slab->buffers; 00321 for (i=0; i < numBuffers; ++i) { 00322 buf->base.base.refcount = 0; 00323 buf->base.base.size = mgr->bufSize; 00324 buf->base.base.alignment = 0; 00325 buf->base.base.usage = 0; 00326 buf->base.vtbl = &pb_slab_buffer_vtbl; 00327 buf->slab = slab; 00328 buf->start = i* mgr->bufSize; 00329 buf->mapCount = 0; 00330 pipe_condvar_init(buf->event); 00331 LIST_ADDTAIL(&buf->head, &slab->freeBuffers); 00332 slab->numFree++; 00333 buf++; 00334 } 00335 00336 /* Add this slab to the list of partial slabs */ 00337 LIST_ADDTAIL(&slab->head, &mgr->slabs); 00338 00339 return PIPE_OK; 00340 00341 out_err1: 00342 pb_reference(&slab->bo, NULL); 00343 out_err0: 00344 FREE(slab); 00345 return ret; 00346 }
static struct pb_slab_manager* pb_slab_manager | ( | struct pb_manager * | mgr | ) | [static, read] |
Definition at line 176 of file pb_bufmgr_slab.c.
References assert.
00177 { 00178 assert(mgr); 00179 return (struct pb_slab_manager *)mgr; 00180 }
struct pb_manager* pb_slab_manager_create | ( | struct pb_manager * | provider, | |
size_t | bufSize, | |||
size_t | slabSize, | |||
const struct pb_desc * | desc | |||
) | [read] |
Slab sub-allocator.
Definition at line 431 of file pb_bufmgr_slab.c.
References pb_slab_manager::base, pb_slab_manager::bufSize, CALLOC_STRUCT, pb_manager::create_buffer, pb_slab_manager::desc, pb_manager::destroy, pb_manager::flush, LIST_INITHEAD, pb_slab_manager::mutex, pb_slab_manager_create_buffer(), pb_slab_manager_destroy(), pb_slab_manager_flush(), pipe_mutex_init, pb_slab_manager::provider, pb_slab_manager::slabs, and pb_slab_manager::slabSize.
00435 { 00436 struct pb_slab_manager *mgr; 00437 00438 mgr = CALLOC_STRUCT(pb_slab_manager); 00439 if (!mgr) 00440 return NULL; 00441 00442 mgr->base.destroy = pb_slab_manager_destroy; 00443 mgr->base.create_buffer = pb_slab_manager_create_buffer; 00444 mgr->base.flush = pb_slab_manager_flush; 00445 00446 mgr->provider = provider; 00447 mgr->bufSize = bufSize; 00448 mgr->slabSize = slabSize; 00449 mgr->desc = *desc; 00450 00451 LIST_INITHEAD(&mgr->slabs); 00452 00453 pipe_mutex_init(mgr->mutex); 00454 00455 return &mgr->base; 00456 }
static struct pb_buffer* pb_slab_manager_create_buffer | ( | struct pb_manager * | _mgr, | |
size_t | size, | |||
const struct pb_desc * | desc | |||
) | [static, read] |
Definition at line 350 of file pb_bufmgr_slab.c.
References pipe_buffer::alignment, pb_desc::alignment, assert, pb_buffer::base, pb_slab_buffer::base, pb_slab_manager::bufSize, pb_slab_manager::desc, pb_slab::freeBuffers, list, LIST_DELINIT, LIST_ENTRY, pb_slab_manager::mutex, list_head::next, pb_slab::numFree, pb_check_alignment(), pb_check_usage(), pb_slab_create(), pb_slab_manager(), pipe_mutex_lock, pipe_mutex_unlock, pipe_buffer::refcount, pb_slab_manager::slabs, pipe_buffer::usage, and pb_desc::usage.
00353 { 00354 struct pb_slab_manager *mgr = pb_slab_manager(_mgr); 00355 static struct pb_slab_buffer *buf; 00356 struct pb_slab *slab; 00357 struct list_head *list; 00358 00359 /* check size */ 00360 assert(size <= mgr->bufSize); 00361 if(size > mgr->bufSize) 00362 return NULL; 00363 00364 /* check if we can provide the requested alignment */ 00365 assert(pb_check_alignment(desc->alignment, mgr->desc.alignment)); 00366 if(!pb_check_alignment(desc->alignment, mgr->desc.alignment)) 00367 return NULL; 00368 assert(pb_check_alignment(desc->alignment, mgr->bufSize)); 00369 if(!pb_check_alignment(desc->alignment, mgr->bufSize)) 00370 return NULL; 00371 00372 assert(pb_check_usage(desc->usage, mgr->desc.usage)); 00373 if(!pb_check_usage(desc->usage, mgr->desc.usage)) 00374 return NULL; 00375 00376 pipe_mutex_lock(mgr->mutex); 00377 00378 /* Create a new slab, if we run out of partial slabs */ 00379 if (mgr->slabs.next == &mgr->slabs) { 00380 (void) pb_slab_create(mgr); 00381 if (mgr->slabs.next == &mgr->slabs) { 00382 pipe_mutex_unlock(mgr->mutex); 00383 return NULL; 00384 } 00385 } 00386 00387 /* Allocate the buffer from a partial (or just created) slab */ 00388 list = mgr->slabs.next; 00389 slab = LIST_ENTRY(struct pb_slab, list, head); 00390 00391 /* If totally full remove from the partial slab list */ 00392 if (--slab->numFree == 0) 00393 LIST_DELINIT(list); 00394 00395 list = slab->freeBuffers.next; 00396 LIST_DELINIT(list); 00397 00398 pipe_mutex_unlock(mgr->mutex); 00399 buf = LIST_ENTRY(struct pb_slab_buffer, list, head); 00400 00401 ++buf->base.base.refcount; 00402 buf->base.base.alignment = desc->alignment; 00403 buf->base.base.usage = desc->usage; 00404 00405 return &buf->base; 00406 }
static void pb_slab_manager_destroy | ( | struct pb_manager * | _mgr | ) | [static] |
Definition at line 421 of file pb_bufmgr_slab.c.
References FREE, and pb_slab_manager().
00422 { 00423 struct pb_slab_manager *mgr = pb_slab_manager(_mgr); 00424 00425 /* TODO: cleanup all allocated buffers */ 00426 FREE(mgr); 00427 }
static void pb_slab_manager_flush | ( | struct pb_manager * | _mgr | ) | [static] |
Definition at line 410 of file pb_bufmgr_slab.c.
References assert, pb_manager::flush, pb_slab_manager(), and pb_slab_manager::provider.
00411 { 00412 struct pb_slab_manager *mgr = pb_slab_manager(_mgr); 00413 00414 assert(mgr->provider->flush); 00415 if(mgr->provider->flush) 00416 mgr->provider->flush(mgr->provider); 00417 }
static struct pb_slab_range_manager* pb_slab_range_manager | ( | struct pb_manager * | mgr | ) | [static, read] |
Definition at line 184 of file pb_bufmgr_slab.c.
References assert.
00185 { 00186 assert(mgr); 00187 return (struct pb_slab_range_manager *)mgr; 00188 }
struct pb_manager* pb_slab_range_manager_create | ( | struct pb_manager * | provider, | |
size_t | minBufSize, | |||
size_t | maxBufSize, | |||
size_t | slabSize, | |||
const struct pb_desc * | desc | |||
) | [read] |
Allow a range of buffer size, by aggregating multiple slabs sub-allocators with different bucket sizes.
Definition at line 508 of file pb_bufmgr_slab.c.
References pb_slab_range_manager::base, pb_slab_range_manager::buckets, CALLOC, CALLOC_STRUCT, pb_manager::create_buffer, pb_manager::destroy, pb_manager::flush, FREE, pb_slab_range_manager::maxBufSize, pb_slab_range_manager::minBufSize, pb_slab_range_manager::numBuckets, pb_slab_manager_create(), pb_slab_range_manager_create_buffer(), pb_slab_range_manager_destroy(), pb_slab_range_manager_flush(), and pb_slab_range_manager::provider.
00513 { 00514 struct pb_slab_range_manager *mgr; 00515 size_t bufSize; 00516 unsigned i; 00517 00518 if(!provider) 00519 return NULL; 00520 00521 mgr = CALLOC_STRUCT(pb_slab_range_manager); 00522 if (!mgr) 00523 goto out_err0; 00524 00525 mgr->base.destroy = pb_slab_range_manager_destroy; 00526 mgr->base.create_buffer = pb_slab_range_manager_create_buffer; 00527 mgr->base.flush = pb_slab_range_manager_flush; 00528 00529 mgr->provider = provider; 00530 mgr->minBufSize = minBufSize; 00531 mgr->maxBufSize = maxBufSize; 00532 00533 mgr->numBuckets = 1; 00534 bufSize = minBufSize; 00535 while(bufSize < maxBufSize) { 00536 bufSize *= 2; 00537 ++mgr->numBuckets; 00538 } 00539 00540 mgr->buckets = CALLOC(mgr->numBuckets, sizeof(*mgr->buckets)); 00541 if (!mgr->buckets) 00542 goto out_err1; 00543 00544 bufSize = minBufSize; 00545 for (i = 0; i < mgr->numBuckets; ++i) { 00546 mgr->buckets[i] = pb_slab_manager_create(provider, bufSize, slabSize, desc); 00547 if(!mgr->buckets[i]) 00548 goto out_err2; 00549 bufSize *= 2; 00550 } 00551 00552 return &mgr->base; 00553 00554 out_err2: 00555 for (i = 0; i < mgr->numBuckets; ++i) 00556 if(mgr->buckets[i]) 00557 mgr->buckets[i]->destroy(mgr->buckets[i]); 00558 FREE(mgr->buckets); 00559 out_err1: 00560 FREE(mgr); 00561 out_err0: 00562 return NULL; 00563 }
static struct pb_buffer* pb_slab_range_manager_create_buffer | ( | struct pb_manager * | _mgr, | |
size_t | size, | |||
const struct pb_desc * | desc | |||
) | [static, read] |
Definition at line 460 of file pb_bufmgr_slab.c.
References pb_slab_range_manager::buckets, pb_manager::create_buffer, pb_slab_range_manager::minBufSize, pb_slab_range_manager::numBuckets, pb_slab_range_manager(), and pb_slab_range_manager::provider.
00463 { 00464 struct pb_slab_range_manager *mgr = pb_slab_range_manager(_mgr); 00465 size_t bufSize; 00466 unsigned i; 00467 00468 bufSize = mgr->minBufSize; 00469 for (i = 0; i < mgr->numBuckets; ++i) { 00470 if(bufSize >= size) 00471 return mgr->buckets[i]->create_buffer(mgr->buckets[i], size, desc); 00472 bufSize *= 2; 00473 } 00474 00475 /* Fall back to allocate a buffer object directly from the provider. */ 00476 return mgr->provider->create_buffer(mgr->provider, size, desc); 00477 }
static void pb_slab_range_manager_destroy | ( | struct pb_manager * | _mgr | ) | [static] |
Definition at line 494 of file pb_bufmgr_slab.c.
References pb_slab_range_manager::buckets, pb_slab_range_manager::bucketSizes, pb_manager::destroy, FREE, pb_slab_range_manager::numBuckets, and pb_slab_range_manager().
00495 { 00496 struct pb_slab_range_manager *mgr = pb_slab_range_manager(_mgr); 00497 unsigned i; 00498 00499 for (i = 0; i < mgr->numBuckets; ++i) 00500 mgr->buckets[i]->destroy(mgr->buckets[i]); 00501 FREE(mgr->buckets); 00502 FREE(mgr->bucketSizes); 00503 FREE(mgr); 00504 }
static void pb_slab_range_manager_flush | ( | struct pb_manager * | _mgr | ) | [static] |
Definition at line 481 of file pb_bufmgr_slab.c.
References assert, pb_manager::flush, pb_slab_range_manager(), and pb_slab_range_manager::provider.
00482 { 00483 struct pb_slab_range_manager *mgr = pb_slab_range_manager(_mgr); 00484 00485 /* Individual slabs don't hold any temporary buffers so no need to call them */ 00486 00487 assert(mgr->provider->flush); 00488 if(mgr->provider->flush) 00489 mgr->provider->flush(mgr->provider); 00490 }
struct pb_vtbl pb_slab_buffer_vtbl [static] |
Initial value:
{ pb_slab_buffer_destroy, pb_slab_buffer_map, pb_slab_buffer_unmap, pb_slab_buffer_get_base_buffer }
Definition at line 263 of file pb_bufmgr_slab.c.