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 // -*- c++ -*- 19 // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = 20 21 // O S C L _ M E M _ M E M P O O L 22 23 // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = 24 25 /*! \addtogroup osclmemory OSCL Memory 26 * 27 * @{ 28 */ 29 30 31 /*! \file oscl_mem_mempool.h 32 \brief This file contains the definition of memory pool allocators 33 */ 34 35 36 #ifndef OSCL_MEM_MEMPOOL_H_INCLUDED 37 #define OSCL_MEM_MEMPOOL_H_INCLUDED 38 39 #ifndef OSCL_MEM_H_INCLUDED 40 #include "oscl_mem.h" 41 #endif 42 43 #ifndef OSCL_DEFALLOC_H_INCLUDED 44 #include "oscl_defalloc.h" 45 #endif 46 47 #ifndef OSCL_VECTOR_H_INCLUDED 48 #include "oscl_vector.h" 49 #endif 50 51 52 /** \class allocator 53 ** A memory allocator class which allocates and deallocates from a fixed size memory pool; 54 ** The memory pool is a multiple of fixed chunk size and does not grow. All allocation size must be the same as this chunk size. 55 ** 56 */ 57 58 class OsclMemPoolFixedChunkAllocatorObserver 59 { 60 public: 61 virtual void freechunkavailable(OsclAny* aContextData) = 0; ~OsclMemPoolFixedChunkAllocatorObserver()62 virtual ~OsclMemPoolFixedChunkAllocatorObserver() {} 63 }; 64 65 66 class OsclMemPoolFixedChunkAllocator : public Oscl_DefAlloc 67 { 68 public: 69 /** This API throws an exception when the memory allocation for pool fails 70 * If numchunk and chunksize parameters are not set, memory pool of 1 chunk will be created in the first call to allocate. 71 * The chunk size will be set to the n passed in for allocate(). 72 * If numchunk parameter is set to 0, the memory pool will use 1 for numchunk. 73 * 74 * @return void 75 * 76 */ 77 OSCL_IMPORT_REF OsclMemPoolFixedChunkAllocator(const uint32 numchunk = 1, const uint32 chunksize = 0, Oscl_DefAlloc* gen_alloc = NULL); 78 79 /** This API will disable exceptions in case the memory pool runs out of memory 80 * Instead of doing "OSCL_LEAVE(OsclErrNoResources)" allocate API will return 81 * NULL. 82 * 83 * @return void 84 * 85 */ 86 OSCL_IMPORT_REF virtual void enablenullpointerreturn(); 87 88 /** The destructor for the memory pool 89 */ 90 OSCL_IMPORT_REF virtual ~OsclMemPoolFixedChunkAllocator(); 91 92 /** This API throws an exception when n is greater than the fixed chunk size or there are no free chunk available in the pool, 93 * if "enablenullpointerreturn" has not been called. 94 * If the memory pool hasn't been created yet, the pool will be created with chunk size equal to n so n must be greater than 0. 95 * Exception will be thrown if memory allocation for the memory pool fails. 96 * 97 * @return pointer to available chunk from memory pool 98 * 99 */ 100 OSCL_IMPORT_REF virtual OsclAny* allocate(const uint32 n); 101 102 /** This API throws an exception when the pointer p passed in is not part of the memory pool. 103 * Exception will be thrown if the memory pool is not set up yet. 104 * 105 * @return void 106 * 107 */ 108 OSCL_IMPORT_REF virtual void deallocate(OsclAny* p); 109 110 /** This API will set the flag to send a callback via specified observer object when the 111 * next memory chunk is deallocated by deallocate() call.. 112 * 113 * @return void 114 * 115 */ 116 OSCL_IMPORT_REF virtual void notifyfreechunkavailable(OsclMemPoolFixedChunkAllocatorObserver& obs, OsclAny* aContextData = NULL); 117 118 /** This API will cancel any past callback requests.. 119 * 120 * @return void 121 * 122 */ 123 OSCL_IMPORT_REF virtual void CancelFreeChunkAvailableCallback(); 124 125 /** Increments the reference count for this memory pool allocator 126 * 127 * @return void 128 * 129 */ 130 OSCL_IMPORT_REF void addRef(); 131 132 /** Decrements the reference count for this memory pool allocator 133 * When the reference count goes to 0, this instance of the memory pool object is deleted 134 * 135 * @return void 136 * 137 */ 138 OSCL_IMPORT_REF void removeRef(); 139 140 protected: 141 OSCL_IMPORT_REF virtual void createmempool(); 142 OSCL_IMPORT_REF virtual void destroymempool(); 143 144 uint32 iNumChunk; 145 uint32 iChunkSize; 146 uint32 iChunkSizeMemAligned; 147 Oscl_DefAlloc* iMemPoolAllocator; 148 OsclAny* iMemPool; 149 150 Oscl_Vector<OsclAny*, OsclMemAllocator> iFreeMemChunkList; 151 152 bool iCheckNextAvailableFreeChunk; 153 OsclMemPoolFixedChunkAllocatorObserver* iObserver; 154 OsclAny* iNextAvailableContextData; 155 156 int32 iRefCount; 157 bool iEnableNullPtrReturn; 158 }; 159 160 161 /** \class allocator 162 ** A memory allocator class which allocates and deallocates from a fixed size memory pool; 163 ** The memory pool is one block of memory and allocations are not fixed in size. The memory pool 164 ** also has the capability of growing by allocating more block one at a time. This memory pool 165 ** also provides the capability of returning the tail end of memory previously allocated from 166 ** the memory pool 167 ** 168 */ 169 170 class OsclMemPoolResizableAllocatorObserver 171 { 172 public: 173 virtual void freeblockavailable(OsclAny* aContextData) = 0; ~OsclMemPoolResizableAllocatorObserver()174 virtual ~OsclMemPoolResizableAllocatorObserver() {} 175 }; 176 177 class OsclMemPoolResizableAllocatorMemoryObserver 178 { 179 public: 180 virtual void freememoryavailable(OsclAny* aContextData) = 0; ~OsclMemPoolResizableAllocatorMemoryObserver()181 virtual ~OsclMemPoolResizableAllocatorMemoryObserver() {} 182 }; 183 184 class OsclMemPoolResizableAllocator : public Oscl_DefAlloc 185 { 186 public: 187 /** Create the memory pool allocator with resizing functionality. 188 * The size of the memory pool buffer needs to be passed-in. The maximum number of 189 * memory pool buffers, expected number of blocks in a memory pool buffer, and outside allocator are optional. 190 * This API throws an exception when the memory allocation for the pool buffer fails. 191 * If memory pool buffer number limit parameter is not set, the assumption is that 192 * there is no limit and memory pool will grow as needed. 193 * If the expected number of blocks is not set or not known, the memory pool will use 194 * a default value to 10 to allocate extra memory for the block info header. 195 * 196 * @return void 197 * 198 */ 199 OSCL_IMPORT_REF OsclMemPoolResizableAllocator(uint32 aMemPoolBufferSize, uint32 aMemPoolBufferNumLimit = 0, uint32 aExpectedNumBlocksPerBuffer = 0, Oscl_DefAlloc* gen_alloc = NULL); 200 201 /** This API will disable exceptions in case the memory pool runs out of memory 202 * Instead of doing "OSCL_LEAVE(OsclErrNoResources)" allocate API will return 203 * NULL. 204 * 205 * @return void 206 * 207 */ 208 OSCL_IMPORT_REF virtual void enablenullpointerreturn(); 209 210 /** Allocates a block from the memory pool that is at least in size requested 211 * This API throws an exception if there isn't enough memory (if "enablenullpointerreturn" has not been called) 212 * for the requested amount in the pool or if the extra pool buffer cannot be allocated. 213 * 214 * @return Pointer to memory buffer from memory pool 215 * 216 */ 217 OSCL_IMPORT_REF virtual OsclAny* allocate(const uint32 aNumBytes); 218 219 /** Deallocates and returns a block back to the memory pool 220 * This API throws an exception if the pointer passed in is not part of the memory pool, aligned, or has corrupted block header. 221 * 222 * @return void 223 * 224 */ 225 OSCL_IMPORT_REF virtual void deallocate(OsclAny* aPtr); 226 227 /** Returns a tail segment of a previously allocated memory block back to the memory pool. The passed-in 228 * pointer to the memory buffer is still valid after the call completes but the buffer size is smaller by 229 * by specified amount that was freed. 230 * This function allows the user to allocate a larger size block initially when the amount needed is unknown 231 * and then return the unused portion of the block when the amount becomes known. 232 * This API throws an exception if the pointer passed in is not part of the memory pool or the 233 * size to return is bigger than the size of the passed-in block. 234 * Exception will be thrown if the memory pool is not set up yet. 235 * 236 * @return bool True if trim operation successful. False if the block wasn't trimmed 237 * 238 */ 239 OSCL_IMPORT_REF virtual bool trim(OsclAny* aPtr, uint32 aBytesToFree); 240 241 /** Returns the size of the buffer <including the overhead bytes that may be allocated by the allocater> 242 */ 243 OSCL_IMPORT_REF uint32 getBufferSize() const; 244 245 /** Returns the number of bytes allocated from the buffer<including the overhead bytes that may be 246 * allocated by the allocater to keep track of the chunks allocated> 247 */ 248 OSCL_IMPORT_REF virtual uint32 getAllocatedSize() const; 249 250 /** Returns the number of bytes available with the buffer 251 */ 252 OSCL_IMPORT_REF virtual uint32 getAvailableSize() const; 253 254 /** Returns the size of the largest available chunk in the memory. 255 */ 256 OSCL_IMPORT_REF virtual uint32 getLargestContiguousFreeBlockSize() const; 257 258 OSCL_IMPORT_REF virtual bool setMaxSzForNewMemPoolBuffer(uint32 aMaxNewMemPoolBufferSz); 259 260 /** This API will set the flag to send a callback via specified observer object when the 261 * next memory block is deallocated by deallocate() call. If the optional requested size 262 * parameter is set, the callback is sent when a free memory space of requested size becomes available. 263 * The optional context data is returned with the callback and can be used by the user to 264 * differentiate.between different instances of memory pool objects. 265 * This memory pool only allows one notify to be queued. Another call to this function will just overwrite 266 * the previous call. 267 * 268 * @return void 269 * 270 */ 271 OSCL_IMPORT_REF virtual void notifyfreeblockavailable(OsclMemPoolResizableAllocatorObserver& aObserver, uint32 aRequestedSize = 0, OsclAny* aContextData = NULL); 272 273 /** This API will cancel any past callback requests.. 274 * 275 * @return void 276 * 277 */ 278 OSCL_IMPORT_REF virtual void CancelFreeChunkAvailableCallback(); 279 280 OSCL_IMPORT_REF virtual void notifyfreememoryavailable(OsclMemPoolResizableAllocatorMemoryObserver& aObserver, uint32 aRequestedSize = 0, OsclAny* aContextData = NULL); 281 OSCL_IMPORT_REF void CancelFreeMemoryAvailableCallback(); 282 283 /** Increments the reference count for this memory pool allocator 284 * 285 * @return void 286 * 287 */ 288 OSCL_IMPORT_REF void addRef(); 289 290 /** Decrements the reference count for this memory pool allocator 291 * When the reference count goes to 0, this instance of the memory pool object is deleted 292 * 293 * @return void 294 * 295 */ 296 OSCL_IMPORT_REF void removeRef(); 297 298 299 struct MemPoolBlockInfo; 300 301 struct MemPoolBufferInfo 302 { 303 uint32 iBufferPreFence; // Pre-fence to check for memory corruption 304 OsclAny* iStartAddr; // Starting memory address of the memory pool buffer after the buffer info 305 OsclAny* iEndAddr; // Ending memory address of the memory pool buffer 306 uint32 iBufferSize; // Total size of the memory pool buffer including the buffer info header 307 uint32 iNumOutstanding; // Number of outstanding blocks from this memory pool buffer 308 MemPoolBlockInfo* iNextFreeBlock; // Pointer to the next free memory block 309 uint32 iAllocatedSz; //Number of butes allocated from the mempool 310 uint32 iBufferPostFence; // Post-fence to check for memory corruption 311 }; 312 313 struct MemPoolBlockInfo 314 { 315 uint32 iBlockPreFence; // Pre-fence to check for memory corruption 316 MemPoolBlockInfo* iNextFreeBlock; // Pointer to the next (right neighbor) free block in the buffer. NULL if none. 317 MemPoolBlockInfo* iPrevFreeBlock; // Pointer to the previous (left neighbor) free block in the buffer. NULL if first free block 318 uint32 iBlockSize; // Total size of the block including the block info header 319 uint8* iBlockBuffer; // Pointer to the buffer area of the block 320 MemPoolBufferInfo* iParentBuffer; // Pointer to the block's parent memory pool buffer 321 uint32 iBlockPostFence; // Post-fence to check for memory corruption 322 }; 323 324 protected: 325 326 /** The destructor for the memory pool. Should not be called directly. Use removeRef() instead. 327 */ 328 OSCL_IMPORT_REF virtual ~OsclMemPoolResizableAllocator(); 329 330 MemPoolBufferInfo* addnewmempoolbuffer(uint32 aBufferSize); 331 void destroyallmempoolbuffers(); 332 MemPoolBlockInfo* findfreeblock(uint32 aBlockSize); 333 OsclAny* allocateblock(MemPoolBlockInfo& aBlockPtr, uint32 aNumBytes); 334 void deallocateblock(MemPoolBlockInfo& aBlockPtr); 335 bool validateblock(OsclAny* aBlockBufPtr); 336 337 uint32 iMemPoolBufferSize; 338 uint32 iMemPoolBufferNumLimit; 339 uint32 iExpectedNumBlocksPerBuffer; 340 uint32 iMaxNewMemPoolBufferSz; 341 Oscl_DefAlloc* iMemPoolBufferAllocator; 342 Oscl_Vector<MemPoolBufferInfo*, OsclMemAllocator> iMemPoolBufferList; 343 344 uint32 iBufferInfoAlignedSize; 345 uint32 iBlockInfoAlignedSize; 346 347 bool iCheckNextAvailable; 348 uint32 iRequestedNextAvailableSize; 349 OsclAny* iNextAvailableContextData; 350 OsclMemPoolResizableAllocatorObserver* iObserver; 351 352 bool iCheckFreeMemoryAvailable; 353 uint32 iRequestedAvailableFreeMemSize; 354 OsclAny* iFreeMemContextData; 355 OsclMemPoolResizableAllocatorMemoryObserver* iFreeMemPoolObserver; 356 357 int32 iRefCount; 358 bool iEnableNullPtrReturn; 359 //To compute the size of the buffer, excluding the extra memory in the buffer for its management 360 uint32 getMemPoolBufferSize(MemPoolBufferInfo* aBufferInfo) const; 361 //To compute the number of bytes allocated from the buffer 362 uint32 getMemPoolBufferAllocatedSize(MemPoolBufferInfo* aBufferInfo) const; 363 //To compute the addition bytes which were allocated while createing the memory pool for the buffer. 364 uint32 memoryPoolBufferMgmtOverhead() const; 365 }; 366 367 #endif 368 369 /*! @} */ 370