Go to the source code of this file.
Data Structures | |
struct | _DriSlabBuffer |
struct | _DriKernelBO |
struct | _DriSlab |
struct | _DriSlabSizeHeader |
struct | _DriFreeSlabManager |
struct | _DriSlabPool |
Defines | |
#define | DRI_SLABPOOL_ALLOC_RETRIES 100 |
Functions | |
static int | driTimeAfterEq (struct timeval *arg1, struct timeval *arg2) |
static void | driTimeAdd (struct timeval *arg, struct timeval *add) |
static void | driFreeKernelBO (struct _DriKernelBO *kbo) |
static void | driFreeTimeoutKBOsLocked (struct _DriFreeSlabManager *fMan, struct timeval *time) |
static void | driSetKernelBOFree (struct _DriFreeSlabManager *fMan, struct _DriKernelBO *kbo) |
static struct _DriKernelBO * | driAllocKernelBO (struct _DriSlabSizeHeader *header) |
static int | driAllocSlab (struct _DriSlabSizeHeader *header) |
static void | driSlabFreeBufferLocked (struct _DriSlabBuffer *buf) |
static void | driSlabCheckFreeLocked (struct _DriSlabSizeHeader *header, int wait) |
static struct _DriSlabBuffer * | driSlabAllocBuffer (struct _DriSlabSizeHeader *header) |
static void * | pool_create (struct _DriBufferPool *driPool, unsigned long size, uint64_t flags, unsigned hint, unsigned alignment) |
static int | pool_destroy (struct _DriBufferPool *driPool, void *private) |
static int | pool_waitIdle (struct _DriBufferPool *driPool, void *private, pipe_mutex *mutex, int lazy) |
static int | pool_map (struct _DriBufferPool *pool, void *private, unsigned flags, int hint, pipe_mutex *mutex, void **virtual) |
static int | pool_unmap (struct _DriBufferPool *pool, void *private) |
static unsigned long | pool_offset (struct _DriBufferPool *pool, void *private) |
static unsigned long | pool_poolOffset (struct _DriBufferPool *pool, void *private) |
static uint64_t | pool_flags (struct _DriBufferPool *pool, void *private) |
static unsigned long | pool_size (struct _DriBufferPool *pool, void *private) |
static int | pool_fence (struct _DriBufferPool *pool, void *private, struct _DriFenceObject *fence) |
static drmBO * | pool_kernel (struct _DriBufferPool *pool, void *private) |
static int | pool_validate (struct _DriBufferPool *pool, void *private, pipe_mutex *mutex) |
struct _DriFreeSlabManager * | driInitFreeSlabManager (uint32_t checkIntervalMsec, uint32_t slabTimeoutMsec) |
void | driFinishFreeSlabManager (struct _DriFreeSlabManager *fMan) |
static void | driInitSizeHeader (struct _DriSlabPool *pool, uint32_t size, struct _DriSlabSizeHeader *header) |
static void | driFinishSizeHeader (struct _DriSlabSizeHeader *header) |
static void | pool_takedown (struct _DriBufferPool *driPool) |
struct _DriBufferPool * | driSlabPoolInit (int fd, uint64_t flags, uint64_t validMask, uint32_t smallestSize, uint32_t numSizes, uint32_t desiredNumBuffers, uint32_t maxSlabSize, uint32_t pageAlignment, struct _DriFreeSlabManager *fMan) |
#define DRI_SLABPOOL_ALLOC_RETRIES 100 |
Definition at line 42 of file ws_dri_slabpool.c.
static struct _DriKernelBO* driAllocKernelBO | ( | struct _DriSlabSizeHeader * | header | ) | [static, read] |
Definition at line 222 of file ws_dri_slabpool.c.
References _DriKernelBO::bo, _DriSlabSizeHeader::bufSize, _DriFreeSlabManager::cached, _DriSlabPool::desiredNumBuffers, driFreeKernelBO(), _DriSlabPool::fd, _DriKernelBO::fd, _DriSlabPool::fMan, _DriKernelBO::head, list, _DriSlabPool::maxSlabSize, _DriFreeSlabManager::mutex, _DriKernelBO::pageAlignment, _DriSlabPool::pageAlignment, _DriSlabPool::pageSize, pipe_mutex_lock, pipe_mutex_unlock, _DriSlabPool::proposedFlags, _DriSlabSizeHeader::slabPool, _DriKernelBO::timeoutHead, _DriFreeSlabManager::unCached, and _DriKernelBO::virtual.
00224 { 00225 struct _DriSlabPool *slabPool = header->slabPool; 00226 struct _DriFreeSlabManager *fMan = slabPool->fMan; 00227 drmMMListHead *list, *next, *head; 00228 uint32_t size = header->bufSize * slabPool->desiredNumBuffers; 00229 struct _DriKernelBO *kbo; 00230 struct _DriKernelBO *kboTmp; 00231 int ret; 00232 00233 /* 00234 * FIXME: We should perhaps allow some variation in slabsize in order 00235 * to efficiently reuse slabs. 00236 */ 00237 00238 size = (size <= slabPool->maxSlabSize) ? size : slabPool->maxSlabSize; 00239 size = (size + slabPool->pageSize - 1) & ~(slabPool->pageSize - 1); 00240 pipe_mutex_lock(fMan->mutex); 00241 00242 kbo = NULL; 00243 00244 retry: 00245 head = (slabPool->proposedFlags & DRM_BO_FLAG_CACHED) ? 00246 &fMan->cached : &fMan->unCached; 00247 00248 for (list = head->next, next = list->next; 00249 list != head; 00250 list = next, next = list->next) { 00251 00252 kboTmp = DRMLISTENTRY(struct _DriKernelBO, list, head); 00253 00254 if ((kboTmp->bo.size == size) && 00255 (slabPool->pageAlignment == 0 || 00256 (kboTmp->pageAlignment % slabPool->pageAlignment) == 0)) { 00257 00258 if (!kbo) 00259 kbo = kboTmp; 00260 00261 if ((kbo->bo.proposedFlags ^ slabPool->proposedFlags) == 0) 00262 break; 00263 00264 } 00265 } 00266 00267 if (kbo) { 00268 DRMLISTDELINIT(&kbo->head); 00269 DRMLISTDELINIT(&kbo->timeoutHead); 00270 } 00271 00272 pipe_mutex_unlock(fMan->mutex); 00273 00274 if (kbo) { 00275 uint64_t new_mask = kbo->bo.proposedFlags ^ slabPool->proposedFlags; 00276 00277 ret = 0; 00278 if (new_mask) { 00279 ret = drmBOSetStatus(kbo->fd, &kbo->bo, slabPool->proposedFlags, 00280 new_mask, DRM_BO_HINT_DONT_FENCE, 0, 0); 00281 } 00282 if (ret == 0) 00283 return kbo; 00284 00285 driFreeKernelBO(kbo); 00286 kbo = NULL; 00287 goto retry; 00288 } 00289 00290 kbo = calloc(1, sizeof(struct _DriKernelBO)); 00291 if (!kbo) 00292 return NULL; 00293 00294 kbo->fd = slabPool->fd; 00295 DRMINITLISTHEAD(&kbo->head); 00296 DRMINITLISTHEAD(&kbo->timeoutHead); 00297 ret = drmBOCreate(kbo->fd, size, slabPool->pageAlignment, NULL, 00298 slabPool->proposedFlags, 00299 DRM_BO_HINT_DONT_FENCE, &kbo->bo); 00300 if (ret) 00301 goto out_err0; 00302 00303 ret = drmBOMap(kbo->fd, &kbo->bo, 00304 DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 00305 0, &kbo->virtual); 00306 00307 if (ret) 00308 goto out_err1; 00309 00310 ret = drmBOUnmap(kbo->fd, &kbo->bo); 00311 if (ret) 00312 goto out_err1; 00313 00314 return kbo; 00315 00316 out_err1: 00317 drmBOUnreference(kbo->fd, &kbo->bo); 00318 out_err0: 00319 free(kbo); 00320 return NULL; 00321 }
static int driAllocSlab | ( | struct _DriSlabSizeHeader * | header | ) | [static] |
Definition at line 325 of file ws_dri_slabpool.c.
References _DriKernelBO::bo, _DriSlab::buffers, _DriSlabSizeHeader::bufSize, driAllocKernelBO(), driSetKernelBOFree(), ENOMEM, _DriSlabBuffer::event, _DriSlabPool::fMan, _DriSlab::freeBuffers, _DriSlabBuffer::head, _DriSlab::head, _DriSlab::header, _DriSlabBuffer::isSlabBuffer, _DriSlab::kbo, _DriSlabBuffer::mapCount, _DriSlab::numBuffers, _DriSlab::numFree, _DriSlabBuffer::parent, pipe_condvar_init, _DriSlabSizeHeader::slabPool, _DriSlabSizeHeader::slabs, and _DriSlabBuffer::start.
00326 { 00327 struct _DriSlab *slab; 00328 struct _DriSlabBuffer *buf; 00329 uint32_t numBuffers; 00330 int ret; 00331 int i; 00332 00333 slab = calloc(1, sizeof(*slab)); 00334 if (!slab) 00335 return -ENOMEM; 00336 00337 slab->kbo = driAllocKernelBO(header); 00338 if (!slab->kbo) { 00339 ret = -ENOMEM; 00340 goto out_err0; 00341 } 00342 00343 numBuffers = slab->kbo->bo.size / header->bufSize; 00344 00345 slab->buffers = calloc(numBuffers, sizeof(*slab->buffers)); 00346 if (!slab->buffers) { 00347 ret = -ENOMEM; 00348 goto out_err1; 00349 } 00350 00351 DRMINITLISTHEAD(&slab->head); 00352 DRMINITLISTHEAD(&slab->freeBuffers); 00353 slab->numBuffers = numBuffers; 00354 slab->numFree = 0; 00355 slab->header = header; 00356 00357 buf = slab->buffers; 00358 for (i=0; i < numBuffers; ++i) { 00359 buf->parent = slab; 00360 buf->start = i* header->bufSize; 00361 buf->mapCount = 0; 00362 buf->isSlabBuffer = 1; 00363 pipe_condvar_init(buf->event); 00364 DRMLISTADDTAIL(&buf->head, &slab->freeBuffers); 00365 slab->numFree++; 00366 buf++; 00367 } 00368 00369 DRMLISTADDTAIL(&slab->head, &header->slabs); 00370 00371 return 0; 00372 00373 out_err1: 00374 driSetKernelBOFree(header->slabPool->fMan, slab->kbo); 00375 free(slab->buffers); 00376 out_err0: 00377 free(slab); 00378 return ret; 00379 }
void driFinishFreeSlabManager | ( | struct _DriFreeSlabManager * | fMan | ) |
Definition at line 823 of file ws_dri_slabpool.c.
References assert, _DriFreeSlabManager::cached, _DriFreeSlabManager::checkInterval, driFreeTimeoutKBOsLocked(), driTimeAdd(), _DriFreeSlabManager::mutex, _DriFreeSlabManager::nextCheck, pipe_mutex_lock, pipe_mutex_unlock, _DriFreeSlabManager::timeoutList, and _DriFreeSlabManager::unCached.
00824 { 00825 struct timeval time; 00826 00827 time = fMan->nextCheck; 00828 driTimeAdd(&time, &fMan->checkInterval); 00829 00830 pipe_mutex_lock(fMan->mutex); 00831 driFreeTimeoutKBOsLocked(fMan, &time); 00832 pipe_mutex_unlock(fMan->mutex); 00833 00834 assert(fMan->timeoutList.next == &fMan->timeoutList); 00835 assert(fMan->unCached.next == &fMan->unCached); 00836 assert(fMan->cached.next == &fMan->cached); 00837 00838 free(fMan); 00839 }
static void driFinishSizeHeader | ( | struct _DriSlabSizeHeader * | header | ) | [static] |
Definition at line 860 of file ws_dri_slabpool.c.
References _DriSlabSizeHeader::delayedBuffers, driFenceFinish(), driFenceUnReference(), driSlabFreeBufferLocked(), _DriSlabBuffer::fence, _DriSlabBuffer::fenceType, _DriSlabBuffer::head, list, _DriSlabSizeHeader::mutex, _DriSlabSizeHeader::numDelayed, pipe_mutex_lock, and pipe_mutex_unlock.
00861 { 00862 drmMMListHead *list, *next; 00863 struct _DriSlabBuffer *buf; 00864 00865 pipe_mutex_lock(header->mutex); 00866 for (list = header->delayedBuffers.next, next = list->next; 00867 list != &header->delayedBuffers; 00868 list = next, next = list->next) { 00869 00870 buf = DRMLISTENTRY(struct _DriSlabBuffer, list , head); 00871 if (buf->fence) { 00872 (void) driFenceFinish(buf->fence, buf->fenceType, 0); 00873 driFenceUnReference(&buf->fence); 00874 } 00875 header->numDelayed--; 00876 driSlabFreeBufferLocked(buf); 00877 } 00878 pipe_mutex_unlock(header->mutex); 00879 }
static void driFreeKernelBO | ( | struct _DriKernelBO * | kbo | ) | [static] |
Definition at line 148 of file ws_dri_slabpool.c.
References _DriKernelBO::bo, and _DriKernelBO::fd.
00149 { 00150 if (!kbo) 00151 return; 00152 00153 (void) drmBOUnreference(kbo->fd, &kbo->bo); 00154 free(kbo); 00155 }
static void driFreeTimeoutKBOsLocked | ( | struct _DriFreeSlabManager * | fMan, | |
struct timeval * | time | |||
) | [static] |
Definition at line 159 of file ws_dri_slabpool.c.
References _DriFreeSlabManager::checkInterval, driFreeKernelBO(), driTimeAdd(), driTimeAfterEq(), _DriKernelBO::head, list, _DriFreeSlabManager::nextCheck, _DriKernelBO::timeFreed, _DriKernelBO::timeoutHead, and _DriFreeSlabManager::timeoutList.
00161 { 00162 drmMMListHead *list, *next; 00163 struct _DriKernelBO *kbo; 00164 00165 if (!driTimeAfterEq(time, &fMan->nextCheck)) 00166 return; 00167 00168 for (list = fMan->timeoutList.next, next = list->next; 00169 list != &fMan->timeoutList; 00170 list = next, next = list->next) { 00171 00172 kbo = DRMLISTENTRY(struct _DriKernelBO, list, timeoutHead); 00173 00174 if (!driTimeAfterEq(time, &kbo->timeFreed)) 00175 break; 00176 00177 DRMLISTDELINIT(&kbo->timeoutHead); 00178 DRMLISTDELINIT(&kbo->head); 00179 driFreeKernelBO(kbo); 00180 } 00181 00182 fMan->nextCheck = *time; 00183 driTimeAdd(&fMan->nextCheck, &fMan->checkInterval); 00184 }
struct _DriFreeSlabManager* driInitFreeSlabManager | ( | uint32_t | checkIntervalMsec, | |
uint32_t | slabTimeoutMsec | |||
) | [read] |
Definition at line 794 of file ws_dri_slabpool.c.
References _DriFreeSlabManager::cached, _DriFreeSlabManager::checkInterval, driTimeAdd(), _DriFreeSlabManager::mutex, _DriFreeSlabManager::nextCheck, pipe_mutex_init, pipe_mutex_lock, pipe_mutex_unlock, _DriFreeSlabManager::slabTimeout, _DriFreeSlabManager::timeoutList, and _DriFreeSlabManager::unCached.
00795 { 00796 struct _DriFreeSlabManager *tmp; 00797 00798 tmp = calloc(1, sizeof(*tmp)); 00799 if (!tmp) 00800 return NULL; 00801 00802 pipe_mutex_init(tmp->mutex); 00803 pipe_mutex_lock(tmp->mutex); 00804 tmp->slabTimeout.tv_usec = slabTimeoutMsec*1000; 00805 tmp->slabTimeout.tv_sec = tmp->slabTimeout.tv_usec / 1000000; 00806 tmp->slabTimeout.tv_usec -= tmp->slabTimeout.tv_sec*1000000; 00807 00808 tmp->checkInterval.tv_usec = checkIntervalMsec*1000; 00809 tmp->checkInterval.tv_sec = tmp->checkInterval.tv_usec / 1000000; 00810 tmp->checkInterval.tv_usec -= tmp->checkInterval.tv_sec*1000000; 00811 00812 gettimeofday(&tmp->nextCheck, NULL); 00813 driTimeAdd(&tmp->nextCheck, &tmp->checkInterval); 00814 DRMINITLISTHEAD(&tmp->timeoutList); 00815 DRMINITLISTHEAD(&tmp->unCached); 00816 DRMINITLISTHEAD(&tmp->cached); 00817 pipe_mutex_unlock(tmp->mutex); 00818 00819 return tmp; 00820 }
static void driInitSizeHeader | ( | struct _DriSlabPool * | pool, | |
uint32_t | size, | |||
struct _DriSlabSizeHeader * | header | |||
) | [static] |
Definition at line 842 of file ws_dri_slabpool.c.
References _DriSlabSizeHeader::bufSize, _DriSlabSizeHeader::delayedBuffers, _DriSlabSizeHeader::freeSlabs, _DriSlabSizeHeader::mutex, _DriSlabSizeHeader::numDelayed, pipe_mutex_init, pipe_mutex_lock, pipe_mutex_unlock, _DriSlabSizeHeader::slabPool, and _DriSlabSizeHeader::slabs.
00844 { 00845 pipe_mutex_init(header->mutex); 00846 pipe_mutex_lock(header->mutex); 00847 00848 DRMINITLISTHEAD(&header->slabs); 00849 DRMINITLISTHEAD(&header->freeSlabs); 00850 DRMINITLISTHEAD(&header->delayedBuffers); 00851 00852 header->numDelayed = 0; 00853 header->slabPool = pool; 00854 header->bufSize = size; 00855 00856 pipe_mutex_unlock(header->mutex); 00857 }
static void driSetKernelBOFree | ( | struct _DriFreeSlabManager * | fMan, | |
struct _DriKernelBO * | kbo | |||
) | [static] |
Definition at line 194 of file ws_dri_slabpool.c.
References _DriKernelBO::bo, _DriFreeSlabManager::cached, driFreeTimeoutKBOsLocked(), driTimeAdd(), _DriKernelBO::head, _DriFreeSlabManager::mutex, pipe_mutex_lock, pipe_mutex_unlock, _DriFreeSlabManager::slabTimeout, _DriKernelBO::timeFreed, _DriKernelBO::timeoutHead, _DriFreeSlabManager::timeoutList, and _DriFreeSlabManager::unCached.
00196 { 00197 struct timeval time; 00198 00199 pipe_mutex_lock(fMan->mutex); 00200 gettimeofday(&time, NULL); 00201 driTimeAdd(&time, &fMan->slabTimeout); 00202 00203 kbo->timeFreed = time; 00204 00205 if (kbo->bo.flags & DRM_BO_FLAG_CACHED) 00206 DRMLISTADD(&kbo->head, &fMan->cached); 00207 else 00208 DRMLISTADD(&kbo->head, &fMan->unCached); 00209 00210 DRMLISTADDTAIL(&kbo->timeoutHead, &fMan->timeoutList); 00211 driFreeTimeoutKBOsLocked(fMan, &time); 00212 00213 pipe_mutex_unlock(fMan->mutex); 00214 }
static struct _DriSlabBuffer* driSlabAllocBuffer | ( | struct _DriSlabSizeHeader * | header | ) | [static, read] |
Definition at line 490 of file ws_dri_slabpool.c.
References DRI_SLABPOOL_ALLOC_RETRIES, driAllocSlab(), driSlabCheckFreeLocked(), _DriSlab::freeBuffers, _DriSlab::head, list, _DriSlabSizeHeader::mutex, _DriSlab::numFree, pipe_mutex_lock, pipe_mutex_unlock, and _DriSlabSizeHeader::slabs.
00491 { 00492 static struct _DriSlabBuffer *buf; 00493 struct _DriSlab *slab; 00494 drmMMListHead *list; 00495 int count = DRI_SLABPOOL_ALLOC_RETRIES; 00496 00497 pipe_mutex_lock(header->mutex); 00498 while(header->slabs.next == &header->slabs && count > 0) { 00499 driSlabCheckFreeLocked(header, 0); 00500 if (header->slabs.next != &header->slabs) 00501 break; 00502 00503 pipe_mutex_unlock(header->mutex); 00504 if (count != DRI_SLABPOOL_ALLOC_RETRIES) 00505 usleep(1); 00506 pipe_mutex_lock(header->mutex); 00507 (void) driAllocSlab(header); 00508 count--; 00509 } 00510 00511 list = header->slabs.next; 00512 if (list == &header->slabs) { 00513 pipe_mutex_unlock(header->mutex); 00514 return NULL; 00515 } 00516 slab = DRMLISTENTRY(struct _DriSlab, list, head); 00517 if (--slab->numFree == 0) 00518 DRMLISTDELINIT(list); 00519 00520 list = slab->freeBuffers.next; 00521 DRMLISTDELINIT(list); 00522 00523 pipe_mutex_unlock(header->mutex); 00524 buf = DRMLISTENTRY(struct _DriSlabBuffer, list, head); 00525 return buf; 00526 }
static void driSlabCheckFreeLocked | ( | struct _DriSlabSizeHeader * | header, | |
int | wait | |||
) | [static] |
Definition at line 427 of file ws_dri_slabpool.c.
References _DriSlabSizeHeader::delayedBuffers, driFenceFinish(), driFenceSignaled(), driFenceSignaledCached(), driFenceUnReference(), driSlabFreeBufferLocked(), _DriSlabBuffer::fence, _DriSlabBuffer::fenceType, _DriSlab::head, list, _DriSlabSizeHeader::numDelayed, and _DriSlabBuffer::parent.
00428 { 00429 drmMMListHead *list, *prev, *first; 00430 struct _DriSlabBuffer *buf; 00431 struct _DriSlab *slab; 00432 int firstWasSignaled = 1; 00433 int signaled; 00434 int i; 00435 int ret; 00436 00437 /* 00438 * Rerun the freeing test if the youngest tested buffer 00439 * was signaled, since there might be more idle buffers 00440 * in the delay list. 00441 */ 00442 00443 while (firstWasSignaled) { 00444 firstWasSignaled = 0; 00445 signaled = 0; 00446 first = header->delayedBuffers.next; 00447 00448 /* Only examine the oldest 1/3 of delayed buffers: 00449 */ 00450 if (header->numDelayed > 3) { 00451 for (i = 0; i < header->numDelayed; i += 3) { 00452 first = first->next; 00453 } 00454 } 00455 00456 for (list = first, prev = list->prev; 00457 list != &header->delayedBuffers; 00458 list = prev, prev = list->prev) { 00459 buf = DRMLISTENTRY(struct _DriSlabBuffer, list, head); 00460 slab = buf->parent; 00461 00462 if (!signaled) { 00463 if (wait) { 00464 ret = driFenceFinish(buf->fence, buf->fenceType, 0); 00465 if (ret) 00466 break; 00467 signaled = 1; 00468 wait = 0; 00469 } else { 00470 signaled = driFenceSignaled(buf->fence, buf->fenceType); 00471 } 00472 if (signaled) { 00473 if (list == first) 00474 firstWasSignaled = 1; 00475 driFenceUnReference(&buf->fence); 00476 header->numDelayed--; 00477 driSlabFreeBufferLocked(buf); 00478 } 00479 } else if (driFenceSignaledCached(buf->fence, buf->fenceType)) { 00480 driFenceUnReference(&buf->fence); 00481 header->numDelayed--; 00482 driSlabFreeBufferLocked(buf); 00483 } 00484 } 00485 } 00486 }
static void driSlabFreeBufferLocked | ( | struct _DriSlabBuffer * | buf | ) | [static] |
Definition at line 387 of file ws_dri_slabpool.c.
References _DriSlab::buffers, driSetKernelBOFree(), _DriSlabPool::fMan, _DriSlab::freeBuffers, _DriSlabSizeHeader::freeSlabs, _DriSlab::head, _DriSlabBuffer::head, _DriSlab::header, _DriSlab::kbo, list, _DriSlab::numBuffers, _DriSlab::numFree, _DriSlabBuffer::parent, _DriSlabSizeHeader::slabPool, and _DriSlabSizeHeader::slabs.
00388 { 00389 struct _DriSlab *slab = buf->parent; 00390 struct _DriSlabSizeHeader *header = slab->header; 00391 drmMMListHead *list = &buf->head; 00392 00393 DRMLISTDEL(list); 00394 DRMLISTADDTAIL(list, &slab->freeBuffers); 00395 slab->numFree++; 00396 00397 if (slab->head.next == &slab->head) 00398 DRMLISTADDTAIL(&slab->head, &header->slabs); 00399 00400 if (slab->numFree == slab->numBuffers) { 00401 list = &slab->head; 00402 DRMLISTDEL(list); 00403 DRMLISTADDTAIL(list, &header->freeSlabs); 00404 } 00405 00406 if (header->slabs.next == &header->slabs || 00407 slab->numFree != slab->numBuffers) { 00408 00409 drmMMListHead *next; 00410 struct _DriFreeSlabManager *fMan = header->slabPool->fMan; 00411 00412 for (list = header->freeSlabs.next, next = list->next; 00413 list != &header->freeSlabs; 00414 list = next, next = list->next) { 00415 00416 slab = DRMLISTENTRY(struct _DriSlab, list, head); 00417 00418 DRMLISTDELINIT(list); 00419 driSetKernelBOFree(fMan, slab->kbo); 00420 free(slab->buffers); 00421 free(slab); 00422 } 00423 } 00424 }
struct _DriBufferPool* driSlabPoolInit | ( | int | fd, | |
uint64_t | flags, | |||
uint64_t | validMask, | |||
uint32_t | smallestSize, | |||
uint32_t | numSizes, | |||
uint32_t | desiredNumBuffers, | |||
uint32_t | maxSlabSize, | |||
uint32_t | pageAlignment, | |||
struct _DriFreeSlabManager * | fMan | |||
) | [read] |
Definition at line 898 of file ws_dri_slabpool.c.
References _DriSlabPool::bucketSizes, _DriBufferPool::create, _DriBufferPool::data, _DriSlabPool::desiredNumBuffers, _DriBufferPool::destroy, driInitSizeHeader(), _DriSlabPool::fd, _DriBufferPool::fence, _DriBufferPool::flags, _DriSlabPool::fMan, _DriSlabPool::headers, _DriBufferPool::kernel, _DriBufferPool::map, _DriSlabPool::maxSlabSize, _DriSlabPool::numBuckets, _DriBufferPool::offset, _DriSlabPool::pageAlignment, _DriSlabPool::pageSize, pool_create(), pool_destroy(), pool_fence(), pool_flags(), pool_kernel(), pool_map(), pool_offset(), pool_poolOffset(), pool_size(), pool_takedown(), pool_unmap(), pool_validate(), pool_waitIdle(), _DriBufferPool::poolOffset, _DriSlabPool::proposedFlags, _DriBufferPool::size, _DriBufferPool::takeDown, _DriBufferPool::unmap, _DriBufferPool::validate, _DriSlabPool::validMask, and _DriBufferPool::waitIdle.
00906 { 00907 struct _DriBufferPool *driPool; 00908 struct _DriSlabPool *pool; 00909 uint32_t i; 00910 00911 driPool = calloc(1, sizeof(*driPool)); 00912 if (!driPool) 00913 return NULL; 00914 00915 pool = calloc(1, sizeof(*pool)); 00916 if (!pool) 00917 goto out_err0; 00918 00919 pool->bucketSizes = calloc(numSizes, sizeof(*pool->bucketSizes)); 00920 if (!pool->bucketSizes) 00921 goto out_err1; 00922 00923 pool->headers = calloc(numSizes, sizeof(*pool->headers)); 00924 if (!pool->headers) 00925 goto out_err2; 00926 00927 pool->fMan = fMan; 00928 pool->proposedFlags = flags; 00929 pool->validMask = validMask; 00930 pool->numBuckets = numSizes; 00931 pool->pageSize = getpagesize(); 00932 pool->fd = fd; 00933 pool->pageAlignment = pageAlignment; 00934 pool->maxSlabSize = maxSlabSize; 00935 pool->desiredNumBuffers = desiredNumBuffers; 00936 00937 for (i=0; i<pool->numBuckets; ++i) { 00938 pool->bucketSizes[i] = (smallestSize << i); 00939 driInitSizeHeader(pool, pool->bucketSizes[i], 00940 &pool->headers[i]); 00941 } 00942 00943 driPool->data = (void *) pool; 00944 driPool->map = &pool_map; 00945 driPool->unmap = &pool_unmap; 00946 driPool->destroy = &pool_destroy; 00947 driPool->offset = &pool_offset; 00948 driPool->poolOffset = &pool_poolOffset; 00949 driPool->flags = &pool_flags; 00950 driPool->size = &pool_size; 00951 driPool->create = &pool_create; 00952 driPool->fence = &pool_fence; 00953 driPool->kernel = &pool_kernel; 00954 driPool->validate = &pool_validate; 00955 driPool->waitIdle = &pool_waitIdle; 00956 driPool->takeDown = &pool_takedown; 00957 00958 return driPool; 00959 00960 out_err2: 00961 free(pool->bucketSizes); 00962 out_err1: 00963 free(pool); 00964 out_err0: 00965 free(driPool); 00966 00967 return NULL; 00968 }
static void driTimeAdd | ( | struct timeval * | arg, | |
struct timeval * | add | |||
) | [static] |
Definition at line 136 of file ws_dri_slabpool.c.
00137 { 00138 unsigned int sec; 00139 00140 arg->tv_sec += add->tv_sec; 00141 arg->tv_usec += add->tv_usec; 00142 sec = arg->tv_usec / 1000000; 00143 arg->tv_sec += sec; 00144 arg->tv_usec -= sec*1000000; 00145 }
static int driTimeAfterEq | ( | struct timeval * | arg1, | |
struct timeval * | arg2 | |||
) | [static] |
Definition at line 128 of file ws_dri_slabpool.c.
00129 { 00130 return ((arg1->tv_sec > arg2->tv_sec) || 00131 ((arg1->tv_sec == arg2->tv_sec) && 00132 (arg1->tv_usec > arg2->tv_usec))); 00133 }
static void* pool_create | ( | struct _DriBufferPool * | driPool, | |
unsigned long | size, | |||
uint64_t | flags, | |||
unsigned | hint, | |||
unsigned | alignment | |||
) | [static] |
Definition at line 529 of file ws_dri_slabpool.c.
References _DriBufferPool::data, driSlabAllocBuffer(), _DriSlabPool::fd, _DriSlabPool::headers, _DriSlabPool::numBuckets, and _DriSlabPool::pageSize.
00531 { 00532 struct _DriSlabPool *pool = (struct _DriSlabPool *) driPool->data; 00533 struct _DriSlabSizeHeader *header; 00534 struct _DriSlabBuffer *buf; 00535 void *dummy; 00536 int i; 00537 int ret; 00538 00539 /* 00540 * FIXME: Check for compatibility. 00541 */ 00542 00543 header = pool->headers; 00544 for (i=0; i<pool->numBuckets; ++i) { 00545 if (header->bufSize >= size) 00546 break; 00547 header++; 00548 } 00549 00550 if (i < pool->numBuckets) 00551 return driSlabAllocBuffer(header); 00552 00553 00554 /* 00555 * Fall back to allocate a buffer object directly from DRM. 00556 * and wrap it in a driBO structure. 00557 */ 00558 00559 00560 buf = calloc(1, sizeof(*buf)); 00561 00562 if (!buf) 00563 return NULL; 00564 00565 buf->bo = calloc(1, sizeof(*buf->bo)); 00566 if (!buf->bo) 00567 goto out_err0; 00568 00569 if (alignment) { 00570 if ((alignment < pool->pageSize) && (pool->pageSize % alignment)) 00571 goto out_err1; 00572 if ((alignment > pool->pageSize) && (alignment % pool->pageSize)) 00573 goto out_err1; 00574 } 00575 00576 ret = drmBOCreate(pool->fd, size, alignment / pool->pageSize, NULL, 00577 flags, hint, buf->bo); 00578 if (ret) 00579 goto out_err1; 00580 00581 ret = drmBOMap(pool->fd, buf->bo, DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 00582 0, &dummy); 00583 if (ret) 00584 goto out_err2; 00585 00586 ret = drmBOUnmap(pool->fd, buf->bo); 00587 if (ret) 00588 goto out_err2; 00589 00590 return buf; 00591 out_err2: 00592 drmBOUnreference(pool->fd, buf->bo); 00593 out_err1: 00594 free(buf->bo); 00595 out_err0: 00596 free(buf); 00597 return NULL; 00598 }
static int pool_destroy | ( | struct _DriBufferPool * | driPool, | |
void * | private | |||
) | [static] |
Definition at line 601 of file ws_dri_slabpool.c.
References _DriSlabBuffer::bo, _DriBufferPool::data, _DriSlabSizeHeader::delayedBuffers, driFenceSignaledCached(), driFenceUnReference(), driSlabFreeBufferLocked(), _DriSlabPool::fd, _DriSlabBuffer::fence, _DriSlabBuffer::fenceType, _DriSlabBuffer::head, _DriSlab::header, _DriSlabBuffer::isSlabBuffer, _DriSlabBuffer::mapCount, _DriSlabSizeHeader::mutex, _DriSlabSizeHeader::numDelayed, _DriSlabBuffer::parent, pipe_mutex_lock, pipe_mutex_unlock, and _DriSlabBuffer::unFenced.
00602 { 00603 struct _DriSlabBuffer *buf = 00604 (struct _DriSlabBuffer *) private; 00605 struct _DriSlab *slab; 00606 struct _DriSlabSizeHeader *header; 00607 00608 if (!buf->isSlabBuffer) { 00609 struct _DriSlabPool *pool = (struct _DriSlabPool *) driPool->data; 00610 int ret; 00611 00612 ret = drmBOUnreference(pool->fd, buf->bo); 00613 free(buf->bo); 00614 free(buf); 00615 return ret; 00616 } 00617 00618 slab = buf->parent; 00619 header = slab->header; 00620 00621 pipe_mutex_lock(header->mutex); 00622 buf->unFenced = 0; 00623 buf->mapCount = 0; 00624 00625 if (buf->fence && !driFenceSignaledCached(buf->fence, buf->fenceType)) { 00626 DRMLISTADDTAIL(&buf->head, &header->delayedBuffers); 00627 header->numDelayed++; 00628 } else { 00629 if (buf->fence) 00630 driFenceUnReference(&buf->fence); 00631 driSlabFreeBufferLocked(buf); 00632 } 00633 00634 pipe_mutex_unlock(header->mutex); 00635 return 0; 00636 }
static int pool_fence | ( | struct _DriBufferPool * | pool, | |
void * | private, | |||
struct _DriFenceObject * | fence | |||
) | [static] |
Definition at line 747 of file ws_dri_slabpool.c.
References _DriKernelBO::bo, _DriSlabBuffer::bo, driFenceReference(), driFenceUnReference(), _DriSlabBuffer::event, _DriSlabBuffer::fence, _DriSlabBuffer::fenceType, _DriSlabBuffer::isSlabBuffer, _DriSlab::kbo, _DriSlabBuffer::parent, pipe_condvar_broadcast, and _DriSlabBuffer::unFenced.
00749 { 00750 struct _DriSlabBuffer *buf = (struct _DriSlabBuffer *) private; 00751 drmBO *bo; 00752 00753 if (buf->fence) 00754 driFenceUnReference(&buf->fence); 00755 00756 buf->fence = driFenceReference(fence); 00757 bo = (buf->isSlabBuffer) ? 00758 &buf->parent->kbo->bo: 00759 buf->bo; 00760 buf->fenceType = bo->fenceFlags; 00761 00762 buf->unFenced = 0; 00763 pipe_condvar_broadcast(buf->event); 00764 00765 return 0; 00766 }
static uint64_t pool_flags | ( | struct _DriBufferPool * | pool, | |
void * | private | |||
) | [static] |
Definition at line 726 of file ws_dri_slabpool.c.
References _DriKernelBO::bo, _DriSlabBuffer::bo, _DriSlabBuffer::isSlabBuffer, _DriSlab::kbo, and _DriSlabBuffer::parent.
00727 { 00728 struct _DriSlabBuffer *buf = (struct _DriSlabBuffer *) private; 00729 00730 if (!buf->isSlabBuffer) 00731 return buf->bo->flags; 00732 00733 return buf->parent->kbo->bo.flags; 00734 }
static drmBO* pool_kernel | ( | struct _DriBufferPool * | pool, | |
void * | private | |||
) | [static] |
Definition at line 769 of file ws_dri_slabpool.c.
References _DriSlabBuffer::bo, _DriKernelBO::bo, _DriSlabBuffer::isSlabBuffer, _DriSlab::kbo, and _DriSlabBuffer::parent.
00770 { 00771 struct _DriSlabBuffer *buf = (struct _DriSlabBuffer *) private; 00772 00773 return (buf->isSlabBuffer) ? &buf->parent->kbo->bo : buf->bo; 00774 }
static int pool_map | ( | struct _DriBufferPool * | pool, | |
void * | private, | |||
unsigned | flags, | |||
int | hint, | |||
pipe_mutex * | mutex, | |||
void ** | virtual | |||
) | [static] |
Definition at line 657 of file ws_dri_slabpool.c.
References _DriSlabBuffer::bo, driFenceSignaled(), driFenceSignaledCached(), _DriSlabBuffer::fence, _DriSlabBuffer::fenceType, _DriSlabBuffer::isSlabBuffer, _DriSlab::kbo, _DriSlabBuffer::mapCount, _DriSlabBuffer::parent, pool_waitIdle(), _DriSlabBuffer::start, _DriSlabBuffer::unFenced, and _DriKernelBO::virtual.
00659 { 00660 struct _DriSlabBuffer *buf = (struct _DriSlabBuffer *) private; 00661 int busy; 00662 00663 if (buf->isSlabBuffer) 00664 busy = buf->unFenced || (buf->fence && !driFenceSignaledCached(buf->fence, buf->fenceType)); 00665 else 00666 busy = buf->fence && !driFenceSignaled(buf->fence, buf->fenceType); 00667 00668 00669 if (busy) { 00670 if (hint & DRM_BO_HINT_DONT_BLOCK) 00671 return -EBUSY; 00672 else { 00673 (void) pool_waitIdle(pool, private, mutex, 0); 00674 } 00675 } 00676 00677 ++buf->mapCount; 00678 *virtual = (buf->isSlabBuffer) ? 00679 (void *) ((uint8_t *) buf->parent->kbo->virtual + buf->start) : 00680 (void *) buf->bo->virtual; 00681 00682 return 0; 00683 }
static unsigned long pool_offset | ( | struct _DriBufferPool * | pool, | |
void * | private | |||
) | [static] |
Definition at line 698 of file ws_dri_slabpool.c.
References assert, _DriKernelBO::bo, _DriSlabBuffer::bo, _DriSlab::header, _DriSlabBuffer::isSlabBuffer, _DriSlab::kbo, _DriSlabBuffer::parent, _DriSlabPool::proposedFlags, _DriSlabSizeHeader::slabPool, and _DriSlabBuffer::start.
00699 { 00700 struct _DriSlabBuffer *buf = (struct _DriSlabBuffer *) private; 00701 struct _DriSlab *slab; 00702 struct _DriSlabSizeHeader *header; 00703 00704 if (!buf->isSlabBuffer) { 00705 assert(buf->bo->proposedFlags & DRM_BO_FLAG_NO_MOVE); 00706 return buf->bo->offset; 00707 } 00708 00709 slab = buf->parent; 00710 header = slab->header; 00711 00712 (void) header; 00713 assert(header->slabPool->proposedFlags & DRM_BO_FLAG_NO_MOVE); 00714 return slab->kbo->bo.offset + buf->start; 00715 }
static unsigned long pool_poolOffset | ( | struct _DriBufferPool * | pool, | |
void * | private | |||
) | [static] |
Definition at line 718 of file ws_dri_slabpool.c.
References _DriSlabBuffer::start.
00719 { 00720 struct _DriSlabBuffer *buf = (struct _DriSlabBuffer *) private; 00721 00722 return buf->start; 00723 }
static unsigned long pool_size | ( | struct _DriBufferPool * | pool, | |
void * | private | |||
) | [static] |
Definition at line 737 of file ws_dri_slabpool.c.
References _DriSlabBuffer::bo, _DriSlabSizeHeader::bufSize, _DriSlab::header, _DriSlabBuffer::isSlabBuffer, and _DriSlabBuffer::parent.
00738 { 00739 struct _DriSlabBuffer *buf = (struct _DriSlabBuffer *) private; 00740 if (!buf->isSlabBuffer) 00741 return buf->bo->size; 00742 00743 return buf->parent->header->bufSize; 00744 }
static void pool_takedown | ( | struct _DriBufferPool * | driPool | ) | [static] |
Definition at line 882 of file ws_dri_slabpool.c.
References _DriSlabPool::bucketSizes, _DriBufferPool::data, driFinishSizeHeader(), _DriSlabPool::headers, and _DriSlabPool::numBuckets.
00883 { 00884 struct _DriSlabPool *pool = driPool->data; 00885 int i; 00886 00887 for (i=0; i<pool->numBuckets; ++i) { 00888 driFinishSizeHeader(&pool->headers[i]); 00889 } 00890 00891 free(pool->headers); 00892 free(pool->bucketSizes); 00893 free(pool); 00894 free(driPool); 00895 }
static int pool_unmap | ( | struct _DriBufferPool * | pool, | |
void * | private | |||
) | [static] |
Definition at line 686 of file ws_dri_slabpool.c.
References _DriSlabBuffer::event, _DriSlabBuffer::isSlabBuffer, _DriSlabBuffer::mapCount, and pipe_condvar_broadcast.
00687 { 00688 struct _DriSlabBuffer *buf = (struct _DriSlabBuffer *) private; 00689 00690 --buf->mapCount; 00691 if (buf->mapCount == 0 && buf->isSlabBuffer) 00692 pipe_condvar_broadcast(buf->event); 00693 00694 return 0; 00695 }
static int pool_validate | ( | struct _DriBufferPool * | pool, | |
void * | private, | |||
pipe_mutex * | mutex | |||
) | [static] |
Definition at line 777 of file ws_dri_slabpool.c.
References _DriSlabBuffer::event, _DriSlabBuffer::isSlabBuffer, _DriSlabBuffer::mapCount, pipe_condvar_wait, and _DriSlabBuffer::unFenced.
00779 { 00780 struct _DriSlabBuffer *buf = (struct _DriSlabBuffer *) private; 00781 00782 if (!buf->isSlabBuffer) 00783 return 0; 00784 00785 while(buf->mapCount != 0) 00786 pipe_condvar_wait(buf->event, *mutex); 00787 00788 buf->unFenced = 1; 00789 return 0; 00790 }
static int pool_waitIdle | ( | struct _DriBufferPool * | driPool, | |
void * | private, | |||
pipe_mutex * | mutex, | |||
int | lazy | |||
) | [static] |
Definition at line 639 of file ws_dri_slabpool.c.
References driFenceFinish(), driFenceUnReference(), _DriSlabBuffer::event, _DriSlabBuffer::fence, _DriSlabBuffer::fenceType, pipe_condvar_wait, and _DriSlabBuffer::unFenced.
00641 { 00642 struct _DriSlabBuffer *buf = (struct _DriSlabBuffer *) private; 00643 00644 while(buf->unFenced) 00645 pipe_condvar_wait(buf->event, *mutex); 00646 00647 if (!buf->fence) 00648 return 0; 00649 00650 driFenceFinish(buf->fence, buf->fenceType, lazy); 00651 driFenceUnReference(&buf->fence); 00652 00653 return 0; 00654 }