1 /* ------------------------------------------------------------------ 2 * Copyright (C) 1998-2009 PacketVideo 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 * express or implied. 14 * See the License for the specific language governing permissions 15 * and limitations under the License. 16 * ------------------------------------------------------------------- 17 */ 18 #include "oscl_mem_mempool.h" 19 20 21 /** 22 * OsclMemPoolFixedChunkAllocator section 23 **/ 24 25 OSCL_EXPORT_REF OsclMemPoolFixedChunkAllocator::OsclMemPoolFixedChunkAllocator(const uint32 numchunk, const uint32 chunksize, Oscl_DefAlloc* gen_alloc) : 26 iNumChunk(1), iChunkSize(0), iChunkSizeMemAligned(0), 27 iMemPoolAllocator(gen_alloc), iMemPool(NULL), 28 iCheckNextAvailableFreeChunk(false), iObserver(NULL), 29 iNextAvailableContextData(NULL), 30 iRefCount(1), 31 iEnableNullPtrReturn(false) 32 { 33 iNumChunk = numchunk; 34 iChunkSize = chunksize; 35 36 if (iNumChunk == 0) 37 { 38 iNumChunk = 1; 39 } 40 41 if (iChunkSize > 0) 42 { 43 createmempool(); 44 } 45 } 46 47 OSCL_EXPORT_REF void OsclMemPoolFixedChunkAllocator::enablenullpointerreturn() 48 { 49 iEnableNullPtrReturn = true; 50 } 51 52 OSCL_EXPORT_REF void OsclMemPoolFixedChunkAllocator::addRef() 53 { 54 // Just increment the ref count 55 ++iRefCount; 56 } 57 58 OSCL_EXPORT_REF void OsclMemPoolFixedChunkAllocator::removeRef() 59 { 60 // Decrement the ref count 61 --iRefCount; 62 63 // If ref count reaches 0 then destroy this object automatically 64 if (iRefCount <= 0) 65 { 66 OSCL_DELETE(this); 67 } 68 } 69 70 71 OSCL_EXPORT_REF OsclMemPoolFixedChunkAllocator::~OsclMemPoolFixedChunkAllocator() 72 { 73 // Decrement the ref count 74 --iRefCount; 75 76 // If ref count reaches 0 then destroy this object 77 if (iRefCount <= 0) 78 { 79 destroymempool(); 80 } 81 } 82 83 84 OSCL_EXPORT_REF OsclAny* OsclMemPoolFixedChunkAllocator::allocate(const uint32 n) 85 { 86 // Create the memory pool if it hasn't been created yet. 87 // Use the allocation size, n, as the chunk size for memory pool 88 if (iChunkSize == 0) 89 { 90 iChunkSize = n; 91 createmempool(); 92 } 93 else if (n > iChunkSize) 94 { 95 OSCL_LEAVE(OsclErrArgument); 96 // OSCL_UNUSED_RETURN(NULL); This statement was removed to avoid compiler warning for Unreachable Code 97 98 } 99 100 if (iFreeMemChunkList.empty()) 101 { 102 // No free chunk is available 103 if (iEnableNullPtrReturn) 104 { 105 return NULL; 106 } 107 else 108 { 109 OSCL_LEAVE(OsclErrNoResources); 110 } 111 } 112 113 // Return the next available chunk from the pool 114 OsclAny* freechunk = iFreeMemChunkList.back(); 115 // Remove the chunk from the free list 116 iFreeMemChunkList.pop_back(); 117 addRef(); 118 return freechunk; 119 } 120 121 122 OSCL_EXPORT_REF void OsclMemPoolFixedChunkAllocator::deallocate(OsclAny* p) 123 { 124 if (iMemPool == NULL) 125 { 126 // Memory pool hasn't been allocated yet so error 127 OSCL_LEAVE(OsclErrNotReady); 128 } 129 130 uint8* ptmp = (uint8*)p; 131 uint8* mptmp = (uint8*)iMemPool; 132 133 if ((ptmp < mptmp) || ptmp >= (mptmp + iNumChunk*iChunkSizeMemAligned)) 134 { 135 // Returned memory is not part of this memory pool 136 OSCL_LEAVE(OsclErrArgument); 137 } 138 139 if (((ptmp - mptmp) % iChunkSizeMemAligned) != 0) 140 { 141 // Returned memory is not aligned to the chunk. 142 OSCL_LEAVE(OsclErrArgument); 143 } 144 145 // Put the returned chunk in the free pool 146 iFreeMemChunkList.push_back(p); 147 148 // Notify the observer about free chunk available if waiting for such callback 149 if (iCheckNextAvailableFreeChunk) 150 { 151 iCheckNextAvailableFreeChunk = false; 152 if (iObserver) 153 { 154 iObserver->freechunkavailable(iNextAvailableContextData); 155 } 156 } 157 158 // Decrement the refcount since deallocating succeeded 159 removeRef(); 160 } 161 162 163 OSCL_EXPORT_REF void OsclMemPoolFixedChunkAllocator::notifyfreechunkavailable(OsclMemPoolFixedChunkAllocatorObserver& obs, OsclAny* aContextData) 164 { 165 iCheckNextAvailableFreeChunk = true; 166 iObserver = &obs; 167 iNextAvailableContextData = aContextData; 168 } 169 170 OSCL_EXPORT_REF void OsclMemPoolFixedChunkAllocator::CancelFreeChunkAvailableCallback() 171 { 172 iCheckNextAvailableFreeChunk = false; 173 iObserver = NULL; 174 iNextAvailableContextData = NULL; 175 } 176 177 OSCL_EXPORT_REF void OsclMemPoolFixedChunkAllocator::createmempool() 178 { 179 if (iChunkSize == 0 || iNumChunk == 0) 180 { 181 OSCL_LEAVE(OsclErrArgument); 182 } 183 184 // Create one block of memory for the memory pool 185 iChunkSizeMemAligned = oscl_mem_aligned_size(iChunkSize); 186 int32 leavecode = 0; 187 if (iMemPoolAllocator) 188 { 189 OSCL_TRY(leavecode, iMemPool = iMemPoolAllocator->ALLOCATE(iNumChunk * iChunkSizeMemAligned)); 190 } 191 else 192 { 193 iMemPool = OSCL_MALLOC(iNumChunk * iChunkSizeMemAligned); 194 } 195 196 if (leavecode || iMemPool == NULL) 197 { 198 OSCL_LEAVE(OsclErrNoMemory); 199 } 200 201 #if OSCL_MEM_FILL_WITH_PATTERN 202 oscl_memset(iMemPool, 0x55, iNumChunk*iChunkSizeMemAligned); 203 #endif 204 205 // Set up the free mem chunk list vector 206 iFreeMemChunkList.reserve(iNumChunk); 207 uint8* chunkptr = (uint8*)iMemPool; 208 209 for (uint32 i = 0; i < iNumChunk; ++i) 210 { 211 iFreeMemChunkList.push_back((OsclAny*)chunkptr); 212 chunkptr += iChunkSizeMemAligned; 213 } 214 } 215 216 217 OSCL_EXPORT_REF void OsclMemPoolFixedChunkAllocator::destroymempool() 218 { 219 // If ref count reaches 0 then destroy this object 220 if (iRefCount <= 0) 221 { 222 #if OSCL_MEM_CHECK_ALL_MEMPOOL_CHUNKS_ARE_RETURNED 223 // Assert if all of the chunks were not returned 224 OSCL_ASSERT(iFreeMemChunkList.size() == iNumChunk); 225 #endif 226 227 iFreeMemChunkList.clear(); 228 229 if (iMemPool) 230 { 231 if (iMemPoolAllocator) 232 { 233 iMemPoolAllocator->deallocate(iMemPool); 234 } 235 else 236 { 237 OSCL_FREE(iMemPool); 238 } 239 240 iMemPool = NULL; 241 } 242 } 243 } 244 245 246 247 /** 248 * OsclMemPoolResizableAllocator section 249 **/ 250 251 #define OSCLMEMPOOLRESIZABLEALLOCATOR_DEFAULT_NUMBLOCKPERBUFFER 10 252 #define OSCLMEMPOOLRESIZABLEALLOCATOR_PREFENCE_PATTERN 0x55 253 #define OSCLMEMPOOLRESIZABLEALLOCATOR_POSTFENCE_PATTERN 0xAA 254 #define OSCLMEMPOOLRESIZABLEALLOCATOR_MIN_BUFFERSIZE 8 255 256 OSCL_EXPORT_REF OsclMemPoolResizableAllocator::OsclMemPoolResizableAllocator(uint32 aMemPoolBufferSize, uint32 aMemPoolBufferNumLimit, uint32 aExpectedNumBlocksPerBuffer, Oscl_DefAlloc* gen_alloc) : 257 iMemPoolBufferSize(aMemPoolBufferSize), 258 iMemPoolBufferNumLimit(aMemPoolBufferNumLimit), 259 iExpectedNumBlocksPerBuffer(aExpectedNumBlocksPerBuffer), 260 iMemPoolBufferAllocator(gen_alloc), 261 iCheckNextAvailable(false), 262 iRequestedNextAvailableSize(0), 263 iNextAvailableContextData(NULL), 264 iObserver(NULL), 265 iCheckFreeMemoryAvailable(false), 266 iRequestedAvailableFreeMemSize(0), 267 iFreeMemContextData(NULL), 268 iFreeMemPoolObserver(NULL), 269 iRefCount(1), 270 iEnableNullPtrReturn(false) 271 { 272 OSCL_ASSERT(aMemPoolBufferSize > OSCLMEMPOOLRESIZABLEALLOCATOR_MIN_BUFFERSIZE); 273 274 iMaxNewMemPoolBufferSz = 0; 275 // Calculate and save the mem aligned size of buffer and block info header structures 276 iBufferInfoAlignedSize = oscl_mem_aligned_size(sizeof(MemPoolBufferInfo)); 277 iBlockInfoAlignedSize = oscl_mem_aligned_size(sizeof(MemPoolBlockInfo)); 278 279 // Pre-allocate memory for vector 280 if (iMemPoolBufferNumLimit > 0) 281 { 282 iMemPoolBufferList.reserve(iMemPoolBufferNumLimit); 283 } 284 else 285 { 286 iMemPoolBufferList.reserve(2); 287 } 288 289 // Determine the size of memory pool buffer and create one 290 uint32 buffersize = oscl_mem_aligned_size(iMemPoolBufferSize) + iBufferInfoAlignedSize; 291 if (iExpectedNumBlocksPerBuffer > 0) 292 { 293 buffersize += (iExpectedNumBlocksPerBuffer * iBlockInfoAlignedSize); 294 } 295 else 296 { 297 buffersize += (OSCLMEMPOOLRESIZABLEALLOCATOR_DEFAULT_NUMBLOCKPERBUFFER * iBlockInfoAlignedSize); 298 } 299 300 addnewmempoolbuffer(buffersize); 301 } 302 303 OSCL_EXPORT_REF void OsclMemPoolResizableAllocator::enablenullpointerreturn() 304 { 305 iEnableNullPtrReturn = true; 306 } 307 308 OSCL_EXPORT_REF OsclAny* OsclMemPoolResizableAllocator::allocate(const uint32 aNumBytes) 309 { 310 MemPoolBlockInfo* freeblock = NULL; 311 uint32 alignednumbytes = oscl_mem_aligned_size(aNumBytes); 312 313 if (aNumBytes == 0) 314 { 315 OSCL_LEAVE(OsclErrArgument); 316 // OSCL_UNUSED_RETURN(NULL); This statement was removed to avoid compiler warning for Unreachable Code 317 } 318 319 // Find a free block that would accomodate the requested size with a block info header 320 freeblock = findfreeblock(alignednumbytes + iBlockInfoAlignedSize); 321 if (freeblock == NULL) 322 { 323 //We could not find the new buffer, the only way we can allocate the chunk is by allocating newmempool buffer 324 //Validate is size is less than the regrow size. 325 if (iMemPoolBufferNumLimit > 0 && iMaxNewMemPoolBufferSz > 0 && iMaxNewMemPoolBufferSz < alignednumbytes) 326 { 327 //cannot create the new buffer 328 if (iEnableNullPtrReturn) 329 { 330 return NULL; 331 } 332 else 333 { 334 // Leave with resource limitation 335 OSCL_LEAVE(OsclErrNoResources); 336 } 337 338 } 339 // Check if the requested size is bigger than the specified buffer size 340 if (alignednumbytes > iMemPoolBufferSize) 341 { 342 // Would need to create a new buffer to accomodate this request 343 344 // Check if another buffer can be created 345 if (iMemPoolBufferNumLimit > 0 && iMemPoolBufferList.size() >= iMemPoolBufferNumLimit) 346 { 347 // Check if there is a memory pool buffer that has no outstanding buffers 348 // If present then remove it so a new one can be added 349 bool emptybufferfound = false; 350 for (uint32 j = 0; j < iMemPoolBufferList.size(); ++j) 351 { 352 if (iMemPoolBufferList[j]->iNumOutstanding == 0) 353 { 354 // Free the memory 355 if (iMemPoolBufferAllocator) 356 { 357 iMemPoolBufferAllocator->deallocate((OsclAny*)iMemPoolBufferList[j]); 358 } 359 else 360 { 361 OSCL_FREE((OsclAny*)iMemPoolBufferList[j]); 362 } 363 364 // Remove the mempool buffer from the list 365 iMemPoolBufferList.erase(iMemPoolBufferList.begin() + j); 366 emptybufferfound = true; 367 break; 368 } 369 } 370 371 // Need to leave and return if empty buffer not found 372 if (!emptybufferfound) 373 { 374 if (iEnableNullPtrReturn) 375 { 376 return NULL; 377 } 378 else 379 { 380 // Leave with resource limitation 381 OSCL_LEAVE(OsclErrNoResources); 382 } 383 } 384 385 // Continue on to create a new buffer 386 OSCL_ASSERT(iMemPoolBufferList.size() < iMemPoolBufferNumLimit); 387 } 388 389 // Determine the size of memory pool buffer and create one 390 uint32 buffersize = alignednumbytes + iBufferInfoAlignedSize; 391 if (iExpectedNumBlocksPerBuffer > 0) 392 { 393 buffersize += (iExpectedNumBlocksPerBuffer * iBlockInfoAlignedSize); 394 } 395 else 396 { 397 buffersize += (OSCLMEMPOOLRESIZABLEALLOCATOR_DEFAULT_NUMBLOCKPERBUFFER * iBlockInfoAlignedSize); 398 } 399 400 MemPoolBufferInfo* newbuffer = addnewmempoolbuffer(buffersize); 401 OSCL_ASSERT(newbuffer != NULL); 402 OSCL_ASSERT(newbuffer->iNextFreeBlock != NULL); 403 freeblock = (MemPoolBlockInfo*)(newbuffer->iNextFreeBlock); 404 OSCL_ASSERT(freeblock != NULL); 405 OSCL_ASSERT(freeblock->iBlockSize >= alignednumbytes); 406 } 407 else 408 { 409 // Check if another buffer can be created 410 if (iMemPoolBufferNumLimit > 0 && iMemPoolBufferList.size() >= iMemPoolBufferNumLimit) 411 { 412 if (iEnableNullPtrReturn) 413 { 414 return NULL; 415 } 416 else 417 { 418 // Leave with resource limitation 419 OSCL_LEAVE(OsclErrNoResources); 420 } 421 } 422 423 // Determine the size of memory pool buffer and create one 424 uint32 buffersize = oscl_mem_aligned_size(iMemPoolBufferSize) + iBufferInfoAlignedSize; 425 if (iExpectedNumBlocksPerBuffer > 0) 426 { 427 buffersize += (iExpectedNumBlocksPerBuffer * iBlockInfoAlignedSize); 428 } 429 else 430 { 431 buffersize += (OSCLMEMPOOLRESIZABLEALLOCATOR_DEFAULT_NUMBLOCKPERBUFFER * iBlockInfoAlignedSize); 432 } 433 434 MemPoolBufferInfo* newbuffer = addnewmempoolbuffer(buffersize); 435 OSCL_ASSERT(newbuffer != NULL); 436 OSCL_ASSERT(newbuffer->iNextFreeBlock != NULL); 437 freeblock = (MemPoolBlockInfo*)(newbuffer->iNextFreeBlock); 438 OSCL_ASSERT(freeblock != NULL); 439 OSCL_ASSERT(freeblock->iBlockSize >= alignednumbytes); 440 } 441 442 } 443 444 // Use the free block and return the buffer pointer 445 OsclAny* bufptr = allocateblock(*freeblock, alignednumbytes); 446 if (bufptr) 447 { 448 addRef(); 449 ++(freeblock->iParentBuffer->iNumOutstanding); 450 } 451 return bufptr; 452 } 453 454 455 OSCL_EXPORT_REF void OsclMemPoolResizableAllocator::deallocate(OsclAny* aPtr) 456 { 457 // Check that the returned pointer is from the memory pool 458 if (validateblock(aPtr) == false) 459 { 460 OSCL_LEAVE(OsclErrArgument); 461 } 462 463 // Retrieve the block info header and validate the info 464 uint8* byteptr = (uint8*)aPtr; 465 MemPoolBlockInfo* retblock = (MemPoolBlockInfo*)(byteptr - iBlockInfoAlignedSize); 466 OSCL_ASSERT(retblock != NULL); 467 OSCL_ASSERT(retblock->iBlockPreFence == OSCLMEMPOOLRESIZABLEALLOCATOR_PREFENCE_PATTERN); 468 OSCL_ASSERT(retblock->iBlockPostFence == OSCLMEMPOOLRESIZABLEALLOCATOR_POSTFENCE_PATTERN); 469 470 // Return the block to the memory pool buffer 471 deallocateblock(*retblock); 472 --(retblock->iParentBuffer->iNumOutstanding); 473 474 // Check if user needs to be notified when block becomes available 475 if (iCheckNextAvailable) 476 { 477 // Check if user is waiting for certain size 478 if (iRequestedNextAvailableSize == 0) 479 { 480 // No so just make the callback 481 iCheckNextAvailable = false; 482 if (iObserver) 483 { 484 iObserver->freeblockavailable(iNextAvailableContextData); 485 } 486 } 487 else 488 { 489 // Check if the requested size is available now 490 if (findfreeblock(iRequestedNextAvailableSize + iBlockInfoAlignedSize) != NULL) 491 { 492 iCheckNextAvailable = false; 493 if (iObserver) 494 { 495 iObserver->freeblockavailable(iNextAvailableContextData); 496 } 497 } 498 else if (iRequestedNextAvailableSize > iMemPoolBufferSize) 499 { 500 // The requested size is bigger than the set buffer size 501 502 // Check if there is space to grow the buffer, 503 if (iMemPoolBufferNumLimit == 0 || iMemPoolBufferList.size() < iMemPoolBufferNumLimit) 504 { 505 // Available 506 iCheckNextAvailable = false; 507 if (iObserver) 508 { 509 iObserver->freeblockavailable(iNextAvailableContextData); 510 } 511 } 512 else 513 { 514 // Not available so see if there is a buffer with 515 // no outstanding buffers which can be destroyed 516 // in the next allocate() call. 517 bool emptybufferfound = false; 518 for (uint32 j = 0; j < iMemPoolBufferList.size(); ++j) 519 { 520 if (iMemPoolBufferList[j]->iNumOutstanding == 0) 521 { 522 emptybufferfound = true; 523 break; 524 } 525 } 526 527 if (emptybufferfound) 528 { 529 iCheckNextAvailable = false; 530 if (iObserver) 531 { 532 iObserver->freeblockavailable(iNextAvailableContextData); 533 } 534 } 535 } 536 } 537 } 538 } 539 if (iCheckFreeMemoryAvailable) 540 { 541 if (iRequestedAvailableFreeMemSize == 0) 542 { 543 // No so just make the callback 544 iCheckFreeMemoryAvailable = false; 545 if (iFreeMemPoolObserver) 546 { 547 iFreeMemPoolObserver->freememoryavailable(iFreeMemContextData); 548 } 549 } 550 else 551 { 552 // Check if the requested size is available now 553 if (getAvailableSize() >= iRequestedAvailableFreeMemSize) 554 { 555 iCheckFreeMemoryAvailable = false; 556 if (iFreeMemPoolObserver) 557 { 558 iFreeMemPoolObserver->freememoryavailable(iFreeMemContextData); 559 } 560 } 561 } 562 } 563 564 // Decrement the refcount since deallocating succeeded 565 removeRef(); 566 } 567 568 569 OSCL_EXPORT_REF bool OsclMemPoolResizableAllocator::trim(OsclAny* aPtr, uint32 aBytesToFree) 570 { 571 // Amount to free has to be aligned 572 uint32 alignedbytestofree = oscl_mem_aligned_size(aBytesToFree); 573 if (alignedbytestofree > aBytesToFree) 574 { 575 // Not aligned so decrease amount to free by one alignment size 576 alignedbytestofree -= 8; 577 } 578 OSCL_ASSERT(alignedbytestofree <= aBytesToFree); 579 580 // Check that the returned pointer is from the memory pool 581 if (validateblock(aPtr) == false) 582 { 583 OSCL_LEAVE(OsclErrArgument); 584 // OSCL_UNUSED_RETURN(false); This statement was removed to avoid compiler warning for Unreachable Code 585 } 586 587 // Retrieve the block info header and validate the info 588 uint8* byteptr = (uint8*)aPtr; 589 MemPoolBlockInfo* resizeblock = (MemPoolBlockInfo*)(byteptr - iBlockInfoAlignedSize); 590 OSCL_ASSERT(resizeblock != NULL); 591 OSCL_ASSERT(resizeblock->iBlockPreFence == OSCLMEMPOOLRESIZABLEALLOCATOR_PREFENCE_PATTERN); 592 OSCL_ASSERT(resizeblock->iBlockPostFence == OSCLMEMPOOLRESIZABLEALLOCATOR_POSTFENCE_PATTERN); 593 594 if ((resizeblock->iBlockSize - iBlockInfoAlignedSize) < alignedbytestofree) 595 { 596 // The bytes to free in the resize is bigger than the original buffer size 597 OSCL_LEAVE(OsclErrArgument); 598 // OSCL_UNUSED_RETURN(false); This statement was removed to avoid compiler warning for Unreachable Code 599 } 600 601 if (alignedbytestofree < (iBlockInfoAlignedSize + OSCLMEMPOOLRESIZABLEALLOCATOR_MIN_BUFFERSIZE)) 602 { 603 // The resizing cannot be done since the amount to free doesn't have 604 // enough space to put in a block info header plus the minimum buffer for the new free block 605 // So don't do anything and return 606 return false; 607 } 608 609 // Create and fill in a block info header for the memory being freed back to memory pool 610 MemPoolBlockInfo* freeblock = (MemPoolBlockInfo*)((uint8*)resizeblock + resizeblock->iBlockSize - alignedbytestofree); 611 freeblock->iBlockPreFence = OSCLMEMPOOLRESIZABLEALLOCATOR_PREFENCE_PATTERN; 612 freeblock->iNextFreeBlock = NULL; 613 freeblock->iPrevFreeBlock = NULL; 614 freeblock->iBlockSize = alignedbytestofree; 615 freeblock->iBlockBuffer = (uint8*)freeblock + iBlockInfoAlignedSize; 616 freeblock->iParentBuffer = resizeblock->iParentBuffer; 617 freeblock->iBlockPostFence = OSCLMEMPOOLRESIZABLEALLOCATOR_POSTFENCE_PATTERN; 618 619 // Return the free block to the memory pool buffer 620 deallocateblock(*freeblock); 621 622 // Adjust the block info for the block being resized 623 resizeblock->iBlockSize -= alignedbytestofree; 624 return true; 625 } 626 627 628 OSCL_EXPORT_REF void OsclMemPoolResizableAllocator::notifyfreeblockavailable(OsclMemPoolResizableAllocatorObserver& aObserver, uint32 aRequestedSize, OsclAny* aContextData) 629 { 630 // Save the parameters for the next deallocate() call 631 iCheckNextAvailable = true; 632 iObserver = &aObserver; 633 iRequestedNextAvailableSize = oscl_mem_aligned_size(aRequestedSize); 634 iNextAvailableContextData = aContextData; 635 } 636 637 OSCL_EXPORT_REF void OsclMemPoolResizableAllocator::CancelFreeChunkAvailableCallback() 638 { 639 iCheckNextAvailable = false; 640 iObserver = NULL; 641 iRequestedNextAvailableSize = 0; 642 iNextAvailableContextData = NULL; 643 } 644 645 OSCL_EXPORT_REF void OsclMemPoolResizableAllocator::notifyfreememoryavailable(OsclMemPoolResizableAllocatorMemoryObserver& aObserver, uint32 aRequestedSize, OsclAny* aContextData) 646 { 647 // Save the parameters for the next deallocate() call 648 iCheckFreeMemoryAvailable = true; 649 iFreeMemPoolObserver = &aObserver; 650 iRequestedAvailableFreeMemSize = oscl_mem_aligned_size(aRequestedSize); 651 iFreeMemContextData = aContextData; 652 } 653 654 OSCL_EXPORT_REF void OsclMemPoolResizableAllocator::CancelFreeMemoryAvailableCallback() 655 { 656 iCheckFreeMemoryAvailable = false; 657 iFreeMemPoolObserver = NULL; 658 iRequestedAvailableFreeMemSize = 0; 659 iFreeMemContextData = NULL; 660 } 661 662 OSCL_EXPORT_REF void OsclMemPoolResizableAllocator::addRef() 663 { 664 // Just increment the ref count 665 ++iRefCount; 666 } 667 668 669 OSCL_EXPORT_REF void OsclMemPoolResizableAllocator::removeRef() 670 { 671 // Decrement the ref count 672 --iRefCount; 673 674 // If ref count reaches 0 then destroy this object automatically 675 if (iRefCount <= 0) 676 { 677 OSCL_DELETE(this); 678 } 679 } 680 681 682 OSCL_EXPORT_REF OsclMemPoolResizableAllocator::~OsclMemPoolResizableAllocator() 683 { 684 destroyallmempoolbuffers(); 685 } 686 687 688 OsclMemPoolResizableAllocator::MemPoolBufferInfo* OsclMemPoolResizableAllocator::addnewmempoolbuffer(uint32 aBufferAlignedSize) 689 { 690 OSCL_ASSERT(aBufferAlignedSize > 0); 691 OSCL_ASSERT(aBufferAlignedSize == oscl_mem_aligned_size(aBufferAlignedSize)); 692 693 // Allocate memory for one buffer 694 uint8* newbuffer = NULL; 695 if (iMemPoolBufferAllocator) 696 { 697 // Use the outside allocator 698 newbuffer = (uint8*)iMemPoolBufferAllocator->ALLOCATE(aBufferAlignedSize); 699 } 700 else 701 { 702 // Allocate directly from heap 703 newbuffer = (uint8*)OSCL_MALLOC(aBufferAlignedSize); 704 } 705 706 if (newbuffer == NULL) 707 { 708 OSCL_LEAVE(OsclErrNoMemory); 709 // OSCL_UNUSED_RETURN(NULL); This statement was removed to avoid compiler warning for Unreachable Code 710 } 711 712 #if OSCL_MEM_FILL_WITH_PATTERN 713 oscl_memset(newbuffer, 0x55, aBufferAlignedSize); 714 #endif 715 716 // Fill in the buffer info header 717 MemPoolBufferInfo* newbufferinfo = (MemPoolBufferInfo*)newbuffer; 718 newbufferinfo->iBufferPreFence = OSCLMEMPOOLRESIZABLEALLOCATOR_PREFENCE_PATTERN; 719 newbufferinfo->iStartAddr = (OsclAny*)(newbuffer + iBufferInfoAlignedSize); 720 newbufferinfo->iEndAddr = (OsclAny*)(newbuffer + aBufferAlignedSize - 1); 721 newbufferinfo->iBufferSize = aBufferAlignedSize; 722 newbufferinfo->iNumOutstanding = 0; 723 newbufferinfo->iNextFreeBlock = (MemPoolBlockInfo*)(newbufferinfo->iStartAddr); 724 newbufferinfo->iAllocatedSz = 0; 725 newbufferinfo->iBufferPostFence = OSCLMEMPOOLRESIZABLEALLOCATOR_POSTFENCE_PATTERN; 726 727 // Put in one free block in the new buffer 728 MemPoolBlockInfo* freeblockinfo = (MemPoolBlockInfo*)(newbufferinfo->iStartAddr); 729 freeblockinfo->iBlockPreFence = OSCLMEMPOOLRESIZABLEALLOCATOR_PREFENCE_PATTERN; 730 freeblockinfo->iNextFreeBlock = NULL; 731 freeblockinfo->iPrevFreeBlock = NULL; 732 freeblockinfo->iBlockSize = aBufferAlignedSize - iBufferInfoAlignedSize; 733 freeblockinfo->iBlockBuffer = (uint8*)freeblockinfo + iBlockInfoAlignedSize; 734 freeblockinfo->iParentBuffer = newbufferinfo; 735 freeblockinfo->iBlockPostFence = OSCLMEMPOOLRESIZABLEALLOCATOR_POSTFENCE_PATTERN; 736 737 // Add the new buffer to the list 738 iMemPoolBufferList.push_front(newbufferinfo); 739 740 return newbufferinfo; 741 } 742 743 744 void OsclMemPoolResizableAllocator::destroyallmempoolbuffers() 745 { 746 while (iMemPoolBufferList.empty() == false) 747 { 748 MemPoolBufferInfo* bufferinfo = iMemPoolBufferList[0]; 749 // Check the buffer 750 OSCL_ASSERT(bufferinfo != NULL); 751 OSCL_ASSERT(bufferinfo->iBufferPreFence == OSCLMEMPOOLRESIZABLEALLOCATOR_PREFENCE_PATTERN); 752 OSCL_ASSERT(bufferinfo->iBufferPostFence == OSCLMEMPOOLRESIZABLEALLOCATOR_POSTFENCE_PATTERN); 753 OSCL_ASSERT(bufferinfo->iNumOutstanding == 0); 754 755 // Free the memory 756 if (iMemPoolBufferAllocator) 757 { 758 iMemPoolBufferAllocator->deallocate((OsclAny*)bufferinfo); 759 } 760 else 761 { 762 OSCL_FREE((OsclAny*)bufferinfo); 763 } 764 765 iMemPoolBufferList.erase(iMemPoolBufferList.begin()); 766 } 767 } 768 769 770 OsclMemPoolResizableAllocator::MemPoolBlockInfo* OsclMemPoolResizableAllocator::findfreeblock(uint32 aBlockAlignedSize) 771 { 772 OSCL_ASSERT(aBlockAlignedSize > 0); 773 OSCL_ASSERT(aBlockAlignedSize == oscl_mem_aligned_size(aBlockAlignedSize)); 774 775 // Go through each mempool buffer and return the first free block that 776 // is bigger than the specified size 777 778 if (aBlockAlignedSize == 0) 779 { 780 // Request should be non-zero 781 OSCL_LEAVE(OsclErrArgument); 782 // OSCL_UNUSED_RETURN(NULL); This statement was removed to avoid compiler warning for Unreachable Code 783 } 784 785 for (uint32 i = 0; i < iMemPoolBufferList.size(); ++i) 786 { 787 MemPoolBufferInfo* bufferinfo = iMemPoolBufferList[i]; 788 MemPoolBlockInfo* blockinfo = bufferinfo->iNextFreeBlock; 789 while (blockinfo != NULL) 790 { 791 if ((blockinfo->iBlockSize/* - iBlockInfoAlignedSize*/) >= aBlockAlignedSize) 792 { 793 // This free block fits the request 794 return blockinfo; 795 } 796 797 // Go to the next free block 798 blockinfo = blockinfo->iNextFreeBlock; 799 } 800 } 801 802 return NULL; 803 } 804 805 806 OsclAny* OsclMemPoolResizableAllocator::allocateblock(MemPoolBlockInfo& aBlockPtr, uint32 aNumAlignedBytes) 807 { 808 OSCL_ASSERT(aNumAlignedBytes > 0); 809 OSCL_ASSERT(aNumAlignedBytes == oscl_mem_aligned_size(aNumAlignedBytes)); 810 811 if (aNumAlignedBytes == 0) 812 { 813 OSCL_LEAVE(OsclErrArgument); 814 // OSCL_UNUSED_RETURN(NULL); This statement was removed to avoid compiler warning for Unreachable Code 815 } 816 817 // Remove the free block from the double linked list 818 if (aBlockPtr.iPrevFreeBlock == NULL && aBlockPtr.iNextFreeBlock != NULL) 819 { 820 // Removing from the beginning of the free list 821 aBlockPtr.iNextFreeBlock->iPrevFreeBlock = NULL; 822 aBlockPtr.iParentBuffer->iNextFreeBlock = aBlockPtr.iNextFreeBlock; 823 } 824 else if (aBlockPtr.iPrevFreeBlock != NULL && aBlockPtr.iNextFreeBlock == NULL) 825 { 826 // Removing from the end of the free list 827 aBlockPtr.iPrevFreeBlock->iNextFreeBlock = NULL; 828 } 829 else if (aBlockPtr.iPrevFreeBlock == NULL && aBlockPtr.iNextFreeBlock == NULL) 830 { 831 // Free list becomes empty so update the parent buffer's link 832 aBlockPtr.iParentBuffer->iNextFreeBlock = NULL; 833 } 834 else 835 { 836 // Removing from middle of the free list 837 aBlockPtr.iPrevFreeBlock->iNextFreeBlock = aBlockPtr.iNextFreeBlock; 838 aBlockPtr.iNextFreeBlock->iPrevFreeBlock = aBlockPtr.iPrevFreeBlock; 839 } 840 841 aBlockPtr.iNextFreeBlock = NULL; 842 aBlockPtr.iPrevFreeBlock = NULL; 843 844 aBlockPtr.iParentBuffer->iAllocatedSz += aBlockPtr.iBlockSize; 845 846 // Resize the block if too large 847 uint32 extraspace = aBlockPtr.iBlockSize - iBlockInfoAlignedSize - aNumAlignedBytes; 848 if (extraspace > (iBlockInfoAlignedSize + OSCLMEMPOOLRESIZABLEALLOCATOR_MIN_BUFFERSIZE)) 849 { 850 trim(aBlockPtr.iBlockBuffer, extraspace); 851 } 852 853 #if OSCL_MEM_FILL_WITH_PATTERN 854 oscl_memset(aBlockPtr.iBlockBuffer, 0x55, (aBlockPtr.iBlockSize - iBlockInfoAlignedSize)); 855 #endif 856 return aBlockPtr.iBlockBuffer; 857 } 858 859 860 void OsclMemPoolResizableAllocator::deallocateblock(MemPoolBlockInfo& aBlockPtr) 861 { 862 OSCL_ASSERT(aBlockPtr.iParentBuffer); 863 864 MemPoolBufferInfo* bufferinfo = aBlockPtr.iParentBuffer; 865 MemPoolBlockInfo* rightblockinfo = bufferinfo->iNextFreeBlock; 866 MemPoolBlockInfo* leftblockinfo = NULL; 867 868 // Go through the free block list and find the free block which would 869 // become the right neighbor of the block being freed 870 while (rightblockinfo != NULL) 871 { 872 if (&aBlockPtr < rightblockinfo) 873 { 874 break; 875 } 876 leftblockinfo = rightblockinfo; 877 rightblockinfo = rightblockinfo->iNextFreeBlock; 878 } 879 880 // Check where the newly freed block is in the list 881 if (leftblockinfo == NULL && rightblockinfo == NULL) 882 { 883 // The free block list is empty. 884 // Trivial case so add to list and return to list without merge 885 bufferinfo->iNextFreeBlock = &aBlockPtr; 886 aBlockPtr.iNextFreeBlock = NULL; 887 aBlockPtr.iPrevFreeBlock = NULL; 888 aBlockPtr.iParentBuffer->iAllocatedSz -= aBlockPtr.iBlockSize; 889 return; 890 } 891 else if (leftblockinfo != NULL && rightblockinfo == NULL) 892 { 893 // Adding to the end of the list 894 OSCL_ASSERT(leftblockinfo->iNextFreeBlock == NULL); 895 896 // Check that the newly freed block doesn't overlap with an existing free block 897 if (((uint8*)leftblockinfo + leftblockinfo->iBlockSize) > (uint8*)&aBlockPtr) 898 { 899 OSCL_LEAVE(OsclErrArgument); 900 } 901 902 leftblockinfo->iNextFreeBlock = &aBlockPtr; 903 aBlockPtr.iPrevFreeBlock = leftblockinfo; 904 aBlockPtr.iNextFreeBlock = NULL; 905 } 906 else if (leftblockinfo == NULL && rightblockinfo != NULL) 907 { 908 // Adding to the beginning of the list 909 OSCL_ASSERT(rightblockinfo->iPrevFreeBlock == NULL); 910 911 // Check that the newly freed block doesn't overlap with an existing free block 912 if (((uint8*)&aBlockPtr + aBlockPtr.iBlockSize) > (uint8*)rightblockinfo) 913 { 914 OSCL_LEAVE(OsclErrArgument); 915 } 916 917 bufferinfo->iNextFreeBlock = &aBlockPtr; 918 rightblockinfo->iPrevFreeBlock = &aBlockPtr; 919 aBlockPtr.iPrevFreeBlock = NULL; 920 aBlockPtr.iNextFreeBlock = rightblockinfo; 921 } 922 else 923 { 924 // Adding to the middle of the list 925 OSCL_ASSERT(leftblockinfo->iNextFreeBlock == rightblockinfo); 926 OSCL_ASSERT(rightblockinfo->iPrevFreeBlock == leftblockinfo); 927 928 // Check that the newly freed block doesn't overlap with the existing free blocks 929 if (((uint8*)&aBlockPtr + aBlockPtr.iBlockSize) > (uint8*)rightblockinfo || 930 ((uint8*)leftblockinfo + leftblockinfo->iBlockSize) > (uint8*)&aBlockPtr) 931 { 932 OSCL_LEAVE(OsclErrArgument); 933 } 934 935 leftblockinfo->iNextFreeBlock = &aBlockPtr; 936 rightblockinfo->iPrevFreeBlock = &aBlockPtr; 937 aBlockPtr.iPrevFreeBlock = leftblockinfo; 938 aBlockPtr.iNextFreeBlock = rightblockinfo; 939 } 940 aBlockPtr.iParentBuffer->iAllocatedSz -= aBlockPtr.iBlockSize; 941 942 // Merge the newly freed block with neighbors if contiguous 943 // Check which neighbors are contiguous in memory space 944 bool rightadj = false; 945 bool leftadj = false; 946 if (aBlockPtr.iPrevFreeBlock) 947 { 948 MemPoolBlockInfo* leftnb = aBlockPtr.iPrevFreeBlock; 949 if (((uint8*)leftnb + leftnb->iBlockSize) == (uint8*)&aBlockPtr) 950 { 951 leftadj = true; 952 } 953 } 954 if (aBlockPtr.iNextFreeBlock) 955 { 956 MemPoolBlockInfo* rightnb = aBlockPtr.iNextFreeBlock; 957 if (((uint8*)&aBlockPtr + aBlockPtr.iBlockSize) == (uint8*)rightnb) 958 { 959 rightadj = true; 960 } 961 } 962 963 // Do the merge based on the check 964 if (leftadj == false && rightadj == true) 965 { 966 // Merge the right neighbor with the newly freed block 967 // Update newly freed block's size and remove the right neighbor from the list 968 MemPoolBlockInfo* midblock = &aBlockPtr; 969 MemPoolBlockInfo* rightblock = aBlockPtr.iNextFreeBlock; 970 // Size update 971 midblock->iBlockSize += rightblock->iBlockSize; 972 // Right neighbor removal 973 if (rightblock->iNextFreeBlock) 974 { 975 rightblock->iNextFreeBlock->iPrevFreeBlock = midblock; 976 } 977 midblock->iNextFreeBlock = rightblock->iNextFreeBlock; 978 } 979 else if (leftadj == true && rightadj == false) 980 { 981 // Merge the newly freed block with the left neighbor 982 // Update the left neighbor's block size to include the newly freed block and 983 // remove the newly freed block from the list 984 MemPoolBlockInfo* midblock = &aBlockPtr; 985 MemPoolBlockInfo* leftblock = aBlockPtr.iPrevFreeBlock; 986 // Size update 987 leftblock->iBlockSize += midblock->iBlockSize; 988 // Newly freed block removal 989 if (midblock->iNextFreeBlock) 990 { 991 midblock->iNextFreeBlock->iPrevFreeBlock = leftblock; 992 } 993 leftblock->iNextFreeBlock = midblock->iNextFreeBlock; 994 } 995 else if (leftadj == true && rightadj == true) 996 { 997 // Merge the newly freed block and right neighbor with the left neighbor 998 // and remove the newly freed block and right neighbor from the list 999 MemPoolBlockInfo* midblock = &aBlockPtr; 1000 MemPoolBlockInfo* leftblock = aBlockPtr.iPrevFreeBlock; 1001 MemPoolBlockInfo* rightblock = aBlockPtr.iNextFreeBlock; 1002 // Size update 1003 leftblock->iBlockSize += (midblock->iBlockSize + rightblock->iBlockSize); 1004 // Newly freed and right neighbor block removal 1005 if (rightblock->iNextFreeBlock) 1006 { 1007 rightblock->iNextFreeBlock->iPrevFreeBlock = leftblock; 1008 } 1009 leftblock->iNextFreeBlock = rightblock->iNextFreeBlock; 1010 } 1011 } 1012 1013 1014 bool OsclMemPoolResizableAllocator::validateblock(OsclAny* aBlockBufPtr) 1015 { 1016 uint32 i = 0; 1017 1018 if (aBlockBufPtr == NULL) 1019 { 1020 // Invalid pointer 1021 return false; 1022 } 1023 1024 // Check if the pointer falls within one of the memory pool buffer's memory address 1025 for (i = 0; i < iMemPoolBufferList.size(); ++i) 1026 { 1027 MemPoolBufferInfo* bufferinfo = iMemPoolBufferList[i]; 1028 if (aBlockBufPtr > bufferinfo->iStartAddr && aBlockBufPtr < bufferinfo->iEndAddr) 1029 { 1030 break; 1031 } 1032 } 1033 if (i >= iMemPoolBufferList.size()) 1034 { 1035 // Parent buffer is not part of this memory pool instance 1036 return false; 1037 } 1038 1039 // Retrieve the block info header 1040 MemPoolBlockInfo* chkblock = (MemPoolBlockInfo*)((uint8*)aBlockBufPtr - iBlockInfoAlignedSize); 1041 1042 if (chkblock->iBlockPreFence != OSCLMEMPOOLRESIZABLEALLOCATOR_PREFENCE_PATTERN || 1043 chkblock->iBlockPostFence != OSCLMEMPOOLRESIZABLEALLOCATOR_POSTFENCE_PATTERN) 1044 { 1045 // Memory fence checking failed 1046 return false; 1047 } 1048 1049 // Check the parent buffer is one in the list 1050 MemPoolBufferInfo* parentbuffer = chkblock->iParentBuffer; 1051 if (parentbuffer == NULL) 1052 { 1053 return false; 1054 } 1055 for (i = 0; i < iMemPoolBufferList.size(); ++i) 1056 { 1057 if (parentbuffer == iMemPoolBufferList[i]) 1058 { 1059 break; 1060 } 1061 } 1062 if (i >= iMemPoolBufferList.size()) 1063 { 1064 // Parent buffer is not part of this memory pool instance 1065 return false; 1066 } 1067 1068 if (aBlockBufPtr < parentbuffer->iStartAddr || aBlockBufPtr > parentbuffer->iEndAddr) 1069 { 1070 // The address of the buffer is not part of the parent buffer 1071 return false; 1072 } 1073 1074 if ((OsclAny*)((uint8*)chkblock + chkblock->iBlockSize - 1) > (parentbuffer->iEndAddr)) 1075 { 1076 // The block size is too big 1077 return false; 1078 } 1079 1080 return true; 1081 } 1082 1083 1084 OSCL_EXPORT_REF uint32 OsclMemPoolResizableAllocator::getBufferSize() const 1085 { 1086 if (iMemPoolBufferNumLimit == 0) 1087 OSCL_LEAVE(OsclErrNotSupported); 1088 1089 uint32 bufferSize = 0; 1090 for (uint32 i = 0; i < iMemPoolBufferList.size(); ++i) 1091 { 1092 MemPoolBufferInfo* bufferinfo = iMemPoolBufferList[i]; 1093 bufferSize += getMemPoolBufferSize(bufferinfo); 1094 } 1095 1096 return bufferSize; 1097 } 1098 1099 OSCL_EXPORT_REF uint32 OsclMemPoolResizableAllocator::getAllocatedSize() const 1100 { 1101 //const uint32 expectedNumBlocksPerBuffer = iExpectedNumBlocksPerBuffer > 0 ? iExpectedNumBlocksPerBuffer : OSCLMEMPOOLRESIZABLEALLOCATOR_DEFAULT_NUMBLOCKPERBUFFER; 1102 uint32 allocatedSz = 0; 1103 for (uint32 i = 0; i < iMemPoolBufferList.size(); ++i) 1104 { 1105 MemPoolBufferInfo* bufferinfo = iMemPoolBufferList[i]; 1106 allocatedSz += getMemPoolBufferAllocatedSize(bufferinfo); 1107 } 1108 return allocatedSz; 1109 } 1110 1111 OSCL_EXPORT_REF uint32 OsclMemPoolResizableAllocator::getAvailableSize() const 1112 { 1113 if (iMemPoolBufferNumLimit == 0) 1114 OSCL_LEAVE(OsclErrNotSupported); 1115 1116 uint32 availableSize = 0; 1117 for (uint32 i = 0; i < iMemPoolBufferList.size(); ++i) 1118 { 1119 MemPoolBufferInfo* bufferinfo = iMemPoolBufferList[i]; 1120 uint32 memPoolBufferAvailableSz = 0; 1121 memPoolBufferAvailableSz = (getMemPoolBufferSize(bufferinfo) - getMemPoolBufferAllocatedSize(bufferinfo)); 1122 availableSize += memPoolBufferAvailableSz; 1123 } 1124 1125 return availableSize; 1126 } 1127 1128 OSCL_EXPORT_REF uint32 OsclMemPoolResizableAllocator::getLargestContiguousFreeBlockSize() const 1129 { 1130 uint32 blockSz = 0; 1131 1132 if (iMemPoolBufferNumLimit > 0) 1133 { 1134 for (uint32 i = 0; i < iMemPoolBufferList.size(); ++i) 1135 { 1136 MemPoolBufferInfo* bufferinfo = iMemPoolBufferList[i]; 1137 if (bufferinfo) 1138 { 1139 MemPoolBlockInfo* blockinfo = bufferinfo->iNextFreeBlock; 1140 while (blockinfo != NULL) 1141 { 1142 if (blockinfo->iBlockSize > blockSz) blockSz = blockinfo->iBlockSize; 1143 blockinfo = blockinfo->iNextFreeBlock; 1144 } 1145 } 1146 } 1147 } 1148 else 1149 OSCL_LEAVE(OsclErrNotSupported); 1150 1151 if (blockSz > iBlockInfoAlignedSize) blockSz -= iBlockInfoAlignedSize; 1152 else blockSz = 0; 1153 1154 return blockSz; 1155 } 1156 1157 OSCL_EXPORT_REF bool OsclMemPoolResizableAllocator::setMaxSzForNewMemPoolBuffer(uint32 aMaxNewMemPoolBufferSz) 1158 { 1159 bool retval = true; 1160 if (iMemPoolBufferNumLimit > 0) 1161 iMaxNewMemPoolBufferSz = aMaxNewMemPoolBufferSz; 1162 else 1163 retval = false; 1164 return retval; 1165 } 1166 1167 uint32 OsclMemPoolResizableAllocator::getMemPoolBufferSize(MemPoolBufferInfo* aBufferInfo) const 1168 { 1169 uint32 memPoolBufferSz = 0; 1170 1171 if (aBufferInfo) 1172 memPoolBufferSz = aBufferInfo->iBufferSize; 1173 1174 return memPoolBufferSz; 1175 } 1176 1177 uint32 OsclMemPoolResizableAllocator::getMemPoolBufferAllocatedSize(MemPoolBufferInfo* aBufferInfo) const 1178 { 1179 return aBufferInfo->iAllocatedSz; 1180 /* 1181 uint32 allocatedSz = 0; 1182 const uint32 expectedNumBlocksPerBuffer = iExpectedNumBlocksPerBuffer > 0 ? iExpectedNumBlocksPerBuffer : OSCLMEMPOOLRESIZABLEALLOCATOR_DEFAULT_NUMBLOCKPERBUFFER; 1183 1184 if (aBufferInfo) 1185 { 1186 if (aBufferInfo->iNumOutstanding > expectedNumBlocksPerBuffer) 1187 { 1188 allocatedSz = (aBufferInfo->iAllocatedSz - (expectedNumBlocksPerBuffer * iBlockInfoAlignedSize)); 1189 } 1190 else 1191 { 1192 allocatedSz = (aBufferInfo->iAllocatedSz - (aBufferInfo->iNumOutstanding * iBlockInfoAlignedSize)); 1193 } 1194 } 1195 return allocatedSz; 1196 */ 1197 } 1198 1199 uint32 OsclMemPoolResizableAllocator::memoryPoolBufferMgmtOverhead() const 1200 { 1201 uint32 overheadBytes = iBufferInfoAlignedSize; 1202 if (iExpectedNumBlocksPerBuffer > 0) 1203 { 1204 overheadBytes += (iExpectedNumBlocksPerBuffer * iBlockInfoAlignedSize); 1205 } 1206 else 1207 { 1208 overheadBytes += (OSCLMEMPOOLRESIZABLEALLOCATOR_DEFAULT_NUMBLOCKPERBUFFER * iBlockInfoAlignedSize); 1209 } 1210 return overheadBytes; 1211 } 1212