Changeset 26452 in vbox for trunk/src/VBox/Runtime/common/alloc
- Timestamp:
- Feb 11, 2010 6:41:06 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/alloc/memcache.cpp
r26428 r26452 53 53 /** Pointer to a cache page. */ 54 54 typedef struct RTMEMCACHEPAGE *PRTMEMCACHEPAGE; 55 56 57 58 /** 59 * A free object. 60 * 61 * @remarks This only works if the objects don't have a constructor or 62 * destructor and are big enough. 63 */ 64 typedef struct RTMEMCACHEFREEOBJ 65 { 66 /** Pointer to the next free object */ 67 struct RTMEMCACHEFREEOBJ * volatile pNext; 68 } RTMEMCACHEFREEOBJ; 69 /** Pointer to a free object. */ 70 typedef RTMEMCACHEFREEOBJ *PRTMEMCACHEFREEOBJ; 55 71 56 72 … … 107 123 /** The maximum number of objects. */ 108 124 uint32_t cMax; 125 /** Whether to the use the free list or not. */ 126 bool fUseFreeList; 109 127 /** Head of the page list. */ 110 128 PRTMEMCACHEPAGE pPageHead; … … 124 142 /** This may point to a page with free entries. */ 125 143 PRTMEMCACHEPAGE volatile pPageHint; 144 /** Stack of free items. 145 * These are marked as used in the allocation bitmaps. 146 * 147 * @todo This doesn't scale well when several threads are beating on the 148 * cache. Also, it totally doesn't work when we've got a 149 * constructor/destructor around or the objects are too small. */ 150 PRTMEMCACHEFREEOBJ volatile pFreeTop; 126 151 } RTMEMCACHEINT; 127 152 … … 129 154 130 155 RTDECL(int) RTMemCacheCreate(PRTMEMCACHE phMemCache, size_t cbObject, size_t cbAlignment, uint32_t cMaxObjects, 131 PFNMEMCACHECTOR pfnCtor, PFNMEMCACHEDTOR pfnDtor, void *pvUser) 156 PFNMEMCACHECTOR pfnCtor, PFNMEMCACHEDTOR pfnDtor, void *pvUser, uint32_t fFlags) 157 132 158 { 133 159 AssertPtr(phMemCache); 134 160 AssertPtrNull(pfnCtor); 135 161 AssertPtrNull(pfnDtor); 162 AssertReturn(!pfnDtor || pfnCtor, VERR_INVALID_PARAMETER); 136 163 AssertReturn(cbObject > 0, VERR_INVALID_PARAMETER); 137 164 AssertReturn(cbObject <= PAGE_SIZE / 8, VERR_INVALID_PARAMETER); 165 AssertReturn(!fFlags, VERR_INVALID_PARAMETER); 138 166 139 167 if (cbAlignment == 0) … … 173 201 pThis->cBits = RT_ALIGN(pThis->cPerPage, 64); 174 202 pThis->cMax = cMaxObjects; 175 pThis->cTotal = 0; 176 pThis->cFree = 0; 203 pThis->fUseFreeList = cbObject >= sizeof(RTMEMCACHEFREEOBJ) 204 && !pfnCtor 205 && !pfnDtor; 177 206 pThis->pPageHead = NULL; 178 pThis->pPageHint = NULL;179 207 pThis->pfnCtor = pfnCtor; 180 208 pThis->pfnDtor = pfnDtor; 181 209 pThis->pvUser = pvUser; 210 pThis->cTotal = 0; 211 pThis->cFree = 0; 212 pThis->pPageHint = NULL; 213 pThis->pFreeTop = NULL; 182 214 183 215 *phMemCache = pThis; … … 193 225 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); 194 226 AssertReturn(pThis->u32Magic == RTMEMCACHE_MAGIC, VERR_INVALID_HANDLE); 195 AssertMsg((uint32_t)pThis->cFree == pThis->cTotal, ("cFree=%u cTotal=%u\n", pThis->cFree, pThis->cTotal)); 227 #ifdef RT_STRICT 228 uint32_t cFree = pThis->cFree; 229 for (PRTMEMCACHEFREEOBJ pFree = pThis->pFreeTop; pFree; pFree = pFree->pNext) 230 cFree++; 231 AssertMsg(cFree == pThis->cTotal, ("cFree=%u cTotal=%u\n", cFree, pThis->cTotal)); 232 #endif 196 233 197 234 /* … … 268 305 pb = (uint8_t *)((uintptr_t)pb & ~(uintptr_t)7); 269 306 pPage->pbmAlloc = pb; 270 Assert((uintptr_t)pPage->pbmCtor + pThis->cBits / 8 < (uintptr_t)pPage->pbmCtor);307 Assert((uintptr_t)pPage->pbmCtor + pThis->cBits / 8 <= (uintptr_t)pPage->pbmAlloc); 271 308 272 309 /* Mark the bitmap padding and any unused objects as allocated. */ … … 322 359 AssertPtrReturn(pThis, VERR_INVALID_PARAMETER); 323 360 AssertReturn(pThis->u32Magic == RTMEMCACHE_MAGIC, VERR_INVALID_PARAMETER); 361 362 /* 363 * Try grab a free object from the stack. 364 */ 365 PRTMEMCACHEFREEOBJ pObj = (PRTMEMCACHEFREEOBJ)ASMAtomicUoReadPtr((void * volatile *)&pThis->pFreeTop); 366 if (pObj) 367 { 368 PRTMEMCACHEFREEOBJ pNext; 369 do 370 { 371 pNext = (PRTMEMCACHEFREEOBJ)ASMAtomicUoReadPtr((void * volatile *)&pObj->pNext); 372 if (ASMAtomicCmpXchgPtr((void * volatile *)&pThis->pFreeTop, pNext, pObj)) 373 { 374 *ppvObj = pObj; 375 return VINF_SUCCESS; 376 } 377 pObj = (PRTMEMCACHEFREEOBJ)ASMAtomicUoReadPtr((void * volatile *)&pThis->pFreeTop); 378 } while (pObj); 379 } 324 380 325 381 /* … … 438 494 Assert(RT_ALIGN_P(pvObj, pThis->cbAlignment) == pvObj); 439 495 440 /* Note: Do *NOT* attempt to poison the object if we have a constructor 441 or/and destructor! */ 442 443 /* 444 * Find the cache page. The page structure is at the start of the page. 445 */ 446 PRTMEMCACHEPAGE pPage = (PRTMEMCACHEPAGE)(((uintptr_t)pvObj) & ~(uintptr_t)PAGE_OFFSET_MASK); 447 Assert(pPage->pCache == pThis); 448 Assert(ASMAtomicUoReadS32(&pPage->cFree) < (int32_t)pThis->cPerPage); 449 450 /* 451 * Clear the bitmap bit and update the two object counter. Order matters! 452 */ 453 uintptr_t offObj = (uintptr_t)pvObj - (uintptr_t)pPage->pbObjects; 454 uintptr_t iObj = offObj / pThis->cbObject; 455 Assert(iObj * pThis->cbObject == offObj); 456 Assert(iObj < pThis->cPerPage); 457 AssertReturnVoid(ASMAtomicBitTestAndClear(pPage->pbmAlloc, iObj)); 458 459 ASMAtomicIncS32(&pPage->cFree); 460 ASMAtomicIncS32(&pThis->cFree); 461 } 462 496 if (pThis->fUseFreeList) 497 { 498 # ifdef RT_STRICT 499 /* This is the same as the other branch, except it's not actually freed. */ 500 PRTMEMCACHEPAGE pPage = (PRTMEMCACHEPAGE)(((uintptr_t)pvObj) & ~(uintptr_t)PAGE_OFFSET_MASK); 501 Assert(pPage->pCache == pThis); 502 Assert(ASMAtomicUoReadS32(&pPage->cFree) < (int32_t)pThis->cPerPage); 503 uintptr_t offObj = (uintptr_t)pvObj - (uintptr_t)pPage->pbObjects; 504 uintptr_t iObj = offObj / pThis->cbObject; 505 Assert(iObj * pThis->cbObject == offObj); 506 Assert(iObj < pThis->cPerPage); 507 AssertReturnVoid(ASMBitTest(pPage->pbmAlloc, iObj)); 508 # endif 509 510 /* 511 * Push it onto the free stack. 512 */ 513 PRTMEMCACHEFREEOBJ pObj = (PRTMEMCACHEFREEOBJ)pvObj; 514 PRTMEMCACHEFREEOBJ pNext; 515 do 516 { 517 pNext = (PRTMEMCACHEFREEOBJ)ASMAtomicUoReadPtr((void * volatile *)&pThis->pFreeTop); 518 pObj->pNext = pNext; 519 } while (!ASMAtomicCmpXchgPtr((void * volatile *)&pThis->pFreeTop, pObj, pNext)); 520 } 521 else 522 { 523 /* Note: Do *NOT* attempt to poison the object if we have a constructor 524 or/and destructor! */ 525 526 /* 527 * Find the cache page. The page structure is at the start of the page. 528 */ 529 PRTMEMCACHEPAGE pPage = (PRTMEMCACHEPAGE)(((uintptr_t)pvObj) & ~(uintptr_t)PAGE_OFFSET_MASK); 530 Assert(pPage->pCache == pThis); 531 Assert(ASMAtomicUoReadS32(&pPage->cFree) < (int32_t)pThis->cPerPage); 532 533 /* 534 * Clear the bitmap bit and update the two object counter. Order matters! 535 */ 536 uintptr_t offObj = (uintptr_t)pvObj - (uintptr_t)pPage->pbObjects; 537 uintptr_t iObj = offObj / pThis->cbObject; 538 Assert(iObj * pThis->cbObject == offObj); 539 Assert(iObj < pThis->cPerPage); 540 AssertReturnVoid(ASMAtomicBitTestAndClear(pPage->pbmAlloc, iObj)); 541 542 ASMAtomicIncS32(&pPage->cFree); 543 ASMAtomicIncS32(&pThis->cFree); 544 } 545 } 546
Note:
See TracChangeset
for help on using the changeset viewer.