00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00039 #include "pipe/p_compiler.h"
00040 #include "pipe/p_error.h"
00041 #include "pipe/p_debug.h"
00042 #include "pipe/p_thread.h"
00043 #include "pipe/p_defines.h"
00044 #include "util/u_memory.h"
00045 #include "util/u_double_list.h"
00046 #include "util/u_time.h"
00047
00048 #include "pb_buffer.h"
00049 #include "pb_bufmgr.h"
00050
00051
00052 struct pb_slab;
00053
00054
00060 struct pb_slab_buffer
00061 {
00062 struct pb_buffer base;
00063
00064 struct pb_slab *slab;
00065
00066 struct list_head head;
00067
00068 unsigned mapCount;
00069
00071 size_t start;
00072
00074
00075 pipe_condvar event;
00076 };
00077
00078
00082 struct pb_slab
00083 {
00084 struct list_head head;
00085 struct list_head freeBuffers;
00086 size_t numBuffers;
00087 size_t numFree;
00088
00089 struct pb_slab_buffer *buffers;
00090 struct pb_slab_manager *mgr;
00091
00093 struct pb_buffer *bo;
00094
00095 void *virtual;
00096 };
00097
00098
00103 struct pb_slab_manager
00104 {
00105 struct pb_manager base;
00106
00108 struct pb_manager *provider;
00109
00111 size_t bufSize;
00112
00114 size_t slabSize;
00115
00122 struct pb_desc desc;
00123
00130 struct list_head slabs;
00131
00132 pipe_mutex mutex;
00133 };
00134
00135
00147 struct pb_slab_range_manager
00148 {
00149 struct pb_manager base;
00150
00151 struct pb_manager *provider;
00152
00153 size_t minBufSize;
00154 size_t maxBufSize;
00155
00157 struct pb_desc desc;
00158
00159 unsigned numBuckets;
00160 size_t *bucketSizes;
00161
00163 struct pb_manager **buckets;
00164 };
00165
00166
00167 static INLINE struct pb_slab_buffer *
00168 pb_slab_buffer(struct pb_buffer *buf)
00169 {
00170 assert(buf);
00171 return (struct pb_slab_buffer *)buf;
00172 }
00173
00174
00175 static INLINE struct pb_slab_manager *
00176 pb_slab_manager(struct pb_manager *mgr)
00177 {
00178 assert(mgr);
00179 return (struct pb_slab_manager *)mgr;
00180 }
00181
00182
00183 static INLINE struct pb_slab_range_manager *
00184 pb_slab_range_manager(struct pb_manager *mgr)
00185 {
00186 assert(mgr);
00187 return (struct pb_slab_range_manager *)mgr;
00188 }
00189
00190
00195 static void
00196 pb_slab_buffer_destroy(struct pb_buffer *_buf)
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
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 }
00227
00228
00229 static void *
00230 pb_slab_buffer_map(struct pb_buffer *_buf,
00231 unsigned flags)
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 }
00238
00239
00240 static void
00241 pb_slab_buffer_unmap(struct pb_buffer *_buf)
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 }
00249
00250
00251 static void
00252 pb_slab_buffer_get_base_buffer(struct pb_buffer *_buf,
00253 struct pb_buffer **base_buf,
00254 unsigned *offset)
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 }
00260
00261
00262 static const struct pb_vtbl
00263 pb_slab_buffer_vtbl = {
00264 pb_slab_buffer_destroy,
00265 pb_slab_buffer_map,
00266 pb_slab_buffer_unmap,
00267 pb_slab_buffer_get_base_buffer
00268 };
00269
00270
00276 static enum pipe_error
00277 pb_slab_create(struct pb_slab_manager *mgr)
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
00296
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
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 }
00347
00348
00349 static struct pb_buffer *
00350 pb_slab_manager_create_buffer(struct pb_manager *_mgr,
00351 size_t size,
00352 const struct pb_desc *desc)
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
00360 assert(size <= mgr->bufSize);
00361 if(size > mgr->bufSize)
00362 return NULL;
00363
00364
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
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
00388 list = mgr->slabs.next;
00389 slab = LIST_ENTRY(struct pb_slab, list, head);
00390
00391
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 }
00407
00408
00409 static void
00410 pb_slab_manager_flush(struct pb_manager *_mgr)
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 }
00418
00419
00420 static void
00421 pb_slab_manager_destroy(struct pb_manager *_mgr)
00422 {
00423 struct pb_slab_manager *mgr = pb_slab_manager(_mgr);
00424
00425
00426 FREE(mgr);
00427 }
00428
00429
00430 struct pb_manager *
00431 pb_slab_manager_create(struct pb_manager *provider,
00432 size_t bufSize,
00433 size_t slabSize,
00434 const struct pb_desc *desc)
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 }
00457
00458
00459 static struct pb_buffer *
00460 pb_slab_range_manager_create_buffer(struct pb_manager *_mgr,
00461 size_t size,
00462 const struct pb_desc *desc)
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
00476 return mgr->provider->create_buffer(mgr->provider, size, desc);
00477 }
00478
00479
00480 static void
00481 pb_slab_range_manager_flush(struct pb_manager *_mgr)
00482 {
00483 struct pb_slab_range_manager *mgr = pb_slab_range_manager(_mgr);
00484
00485
00486
00487 assert(mgr->provider->flush);
00488 if(mgr->provider->flush)
00489 mgr->provider->flush(mgr->provider);
00490 }
00491
00492
00493 static void
00494 pb_slab_range_manager_destroy(struct pb_manager *_mgr)
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 }
00505
00506
00507 struct pb_manager *
00508 pb_slab_range_manager_create(struct pb_manager *provider,
00509 size_t minBufSize,
00510 size_t maxBufSize,
00511 size_t slabSize,
00512 const struct pb_desc *desc)
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 }