• 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 // -*- 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