• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
OsclMemPoolFixedChunkAllocator(const uint32 numchunk,const uint32 chunksize,Oscl_DefAlloc * gen_alloc)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 
enablenullpointerreturn()47 OSCL_EXPORT_REF void OsclMemPoolFixedChunkAllocator::enablenullpointerreturn()
48 {
49     iEnableNullPtrReturn = true;
50 }
51 
addRef()52 OSCL_EXPORT_REF void OsclMemPoolFixedChunkAllocator::addRef()
53 {
54     // Just increment the ref count
55     ++iRefCount;
56 }
57 
removeRef()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 
~OsclMemPoolFixedChunkAllocator()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 
allocate(const uint32 n)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 
deallocate(OsclAny * p)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 
notifyfreechunkavailable(OsclMemPoolFixedChunkAllocatorObserver & obs,OsclAny * aContextData)163 OSCL_EXPORT_REF void OsclMemPoolFixedChunkAllocator::notifyfreechunkavailable(OsclMemPoolFixedChunkAllocatorObserver& obs, OsclAny* aContextData)
164 {
165     iCheckNextAvailableFreeChunk = true;
166     iObserver = &obs;
167     iNextAvailableContextData = aContextData;
168 }
169 
CancelFreeChunkAvailableCallback()170 OSCL_EXPORT_REF void OsclMemPoolFixedChunkAllocator::CancelFreeChunkAvailableCallback()
171 {
172     iCheckNextAvailableFreeChunk = false;
173     iObserver = NULL;
174     iNextAvailableContextData = NULL;
175 }
176 
createmempool()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 
destroymempool()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 
OsclMemPoolResizableAllocator(uint32 aMemPoolBufferSize,uint32 aMemPoolBufferNumLimit,uint32 aExpectedNumBlocksPerBuffer,Oscl_DefAlloc * gen_alloc)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 
enablenullpointerreturn()303 OSCL_EXPORT_REF void OsclMemPoolResizableAllocator::enablenullpointerreturn()
304 {
305     iEnableNullPtrReturn = true;
306 }
307 
allocate(const uint32 aNumBytes)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 
deallocate(OsclAny * aPtr)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 
trim(OsclAny * aPtr,uint32 aBytesToFree)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 
notifyfreeblockavailable(OsclMemPoolResizableAllocatorObserver & aObserver,uint32 aRequestedSize,OsclAny * aContextData)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 
CancelFreeChunkAvailableCallback()637 OSCL_EXPORT_REF void OsclMemPoolResizableAllocator::CancelFreeChunkAvailableCallback()
638 {
639     iCheckNextAvailable = false;
640     iObserver = NULL;
641     iRequestedNextAvailableSize = 0;
642     iNextAvailableContextData = NULL;
643 }
644 
notifyfreememoryavailable(OsclMemPoolResizableAllocatorMemoryObserver & aObserver,uint32 aRequestedSize,OsclAny * aContextData)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 
CancelFreeMemoryAvailableCallback()654 OSCL_EXPORT_REF void OsclMemPoolResizableAllocator::CancelFreeMemoryAvailableCallback()
655 {
656     iCheckFreeMemoryAvailable = false;
657     iFreeMemPoolObserver = NULL;
658     iRequestedAvailableFreeMemSize = 0;
659     iFreeMemContextData = NULL;
660 }
661 
addRef()662 OSCL_EXPORT_REF void OsclMemPoolResizableAllocator::addRef()
663 {
664     // Just increment the ref count
665     ++iRefCount;
666 }
667 
668 
removeRef()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 
~OsclMemPoolResizableAllocator()682 OSCL_EXPORT_REF OsclMemPoolResizableAllocator::~OsclMemPoolResizableAllocator()
683 {
684     destroyallmempoolbuffers();
685 }
686 
687 
addnewmempoolbuffer(uint32 aBufferAlignedSize)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 
destroyallmempoolbuffers()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 
findfreeblock(uint32 aBlockAlignedSize)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 
allocateblock(MemPoolBlockInfo & aBlockPtr,uint32 aNumAlignedBytes)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 
deallocateblock(MemPoolBlockInfo & aBlockPtr)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 
validateblock(OsclAny * aBlockBufPtr)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 
getBufferSize() const1084 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 
getAllocatedSize() const1099 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 
getAvailableSize() const1111 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 
getLargestContiguousFreeBlockSize() const1128 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 
setMaxSzForNewMemPoolBuffer(uint32 aMaxNewMemPoolBufferSz)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 
getMemPoolBufferSize(MemPoolBufferInfo * aBufferInfo) const1167 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 
getMemPoolBufferAllocatedSize(MemPoolBufferInfo * aBufferInfo) const1177 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 
memoryPoolBufferMgmtOverhead() const1199 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