xref: /aosp_15_r20/external/deqp/framework/delibs/depool/deMemPool.c (revision 35238bce31c2a825756842865a792f8cf7f89930)
1*35238bceSAndroid Build Coastguard Worker /*-------------------------------------------------------------------------
2*35238bceSAndroid Build Coastguard Worker  * drawElements Memory Pool Library
3*35238bceSAndroid Build Coastguard Worker  * --------------------------------
4*35238bceSAndroid Build Coastguard Worker  *
5*35238bceSAndroid Build Coastguard Worker  * Copyright 2014 The Android Open Source Project
6*35238bceSAndroid Build Coastguard Worker  *
7*35238bceSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
8*35238bceSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
9*35238bceSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
10*35238bceSAndroid Build Coastguard Worker  *
11*35238bceSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
12*35238bceSAndroid Build Coastguard Worker  *
13*35238bceSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
14*35238bceSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
15*35238bceSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16*35238bceSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
17*35238bceSAndroid Build Coastguard Worker  * limitations under the License.
18*35238bceSAndroid Build Coastguard Worker  *
19*35238bceSAndroid Build Coastguard Worker  *//*!
20*35238bceSAndroid Build Coastguard Worker  * \file
21*35238bceSAndroid Build Coastguard Worker  * \brief Memory pool management.
22*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
23*35238bceSAndroid Build Coastguard Worker 
24*35238bceSAndroid Build Coastguard Worker #include "deMemPool.h"
25*35238bceSAndroid Build Coastguard Worker #include "deMemory.h"
26*35238bceSAndroid Build Coastguard Worker #include "deInt32.h"
27*35238bceSAndroid Build Coastguard Worker 
28*35238bceSAndroid Build Coastguard Worker #if defined(DE_SUPPORT_FAILING_POOL_ALLOC)
29*35238bceSAndroid Build Coastguard Worker #include "deRandom.h"
30*35238bceSAndroid Build Coastguard Worker #endif
31*35238bceSAndroid Build Coastguard Worker 
32*35238bceSAndroid Build Coastguard Worker #include <stdlib.h>
33*35238bceSAndroid Build Coastguard Worker #include <string.h>
34*35238bceSAndroid Build Coastguard Worker 
35*35238bceSAndroid Build Coastguard Worker enum
36*35238bceSAndroid Build Coastguard Worker {
37*35238bceSAndroid Build Coastguard Worker     INITIAL_PAGE_SIZE   = 128,  /*!< Size for the first allocated memory page.            */
38*35238bceSAndroid Build Coastguard Worker     MAX_PAGE_SIZE       = 8096, /*!< Maximum size for a memory page.                    */
39*35238bceSAndroid Build Coastguard Worker     MEM_PAGE_BASE_ALIGN = 4     /*!< Base alignment guarantee for mem page data ptr.    */
40*35238bceSAndroid Build Coastguard Worker };
41*35238bceSAndroid Build Coastguard Worker 
42*35238bceSAndroid Build Coastguard Worker typedef struct MemPage_s MemPage;
43*35238bceSAndroid Build Coastguard Worker 
44*35238bceSAndroid Build Coastguard Worker /*--------------------------------------------------------------------*//*!
45*35238bceSAndroid Build Coastguard Worker  * \internal
46*35238bceSAndroid Build Coastguard Worker  * \brief Memory page header.
47*35238bceSAndroid Build Coastguard Worker  *
48*35238bceSAndroid Build Coastguard Worker  * Represent a page of memory allocate by a memory pool.
49*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
50*35238bceSAndroid Build Coastguard Worker struct MemPage_s
51*35238bceSAndroid Build Coastguard Worker {
52*35238bceSAndroid Build Coastguard Worker     int capacity;
53*35238bceSAndroid Build Coastguard Worker     int bytesAllocated;
54*35238bceSAndroid Build Coastguard Worker 
55*35238bceSAndroid Build Coastguard Worker     MemPage *nextPage;
56*35238bceSAndroid Build Coastguard Worker };
57*35238bceSAndroid Build Coastguard Worker 
58*35238bceSAndroid Build Coastguard Worker #if defined(DE_SUPPORT_DEBUG_POOLS)
59*35238bceSAndroid Build Coastguard Worker typedef struct DebugAlloc_s DebugAlloc;
60*35238bceSAndroid Build Coastguard Worker 
61*35238bceSAndroid Build Coastguard Worker struct DebugAlloc_s
62*35238bceSAndroid Build Coastguard Worker {
63*35238bceSAndroid Build Coastguard Worker     void *memPtr;
64*35238bceSAndroid Build Coastguard Worker     DebugAlloc *next;
65*35238bceSAndroid Build Coastguard Worker };
66*35238bceSAndroid Build Coastguard Worker #endif
67*35238bceSAndroid Build Coastguard Worker 
68*35238bceSAndroid Build Coastguard Worker /*--------------------------------------------------------------------*//*!
69*35238bceSAndroid Build Coastguard Worker  * \brief Memory pool.
70*35238bceSAndroid Build Coastguard Worker  *
71*35238bceSAndroid Build Coastguard Worker  * A pool of memory from which individual memory allocations can be made.
72*35238bceSAndroid Build Coastguard Worker  * The memory pools don't have a freeing operation for individual allocations,
73*35238bceSAndroid Build Coastguard Worker  * but rather all of the memory allocated from a pool is freed when the pool
74*35238bceSAndroid Build Coastguard Worker  * is destroyed.
75*35238bceSAndroid Build Coastguard Worker  *
76*35238bceSAndroid Build Coastguard Worker  * The pools can be arranged into a hierarchy. If a pool with children is
77*35238bceSAndroid Build Coastguard Worker  * destroyed, all of the children are first recursively destroyed and then
78*35238bceSAndroid Build Coastguard Worker  * the pool itself.
79*35238bceSAndroid Build Coastguard Worker  *
80*35238bceSAndroid Build Coastguard Worker  * The memory pools support a feature where individual allocations can be
81*35238bceSAndroid Build Coastguard Worker  * made to simulate failure (i.e., return null). This can be enabled by
82*35238bceSAndroid Build Coastguard Worker  * creating the root pool with the deMemPool_createFailingRoot() function.
83*35238bceSAndroid Build Coastguard Worker  * When the feature is enabled, also creation of sub-pools occasionally
84*35238bceSAndroid Build Coastguard Worker  * fails.
85*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
86*35238bceSAndroid Build Coastguard Worker struct deMemPool_s
87*35238bceSAndroid Build Coastguard Worker {
88*35238bceSAndroid Build Coastguard Worker     uint32_t flags;        /*!< Flags.                                            */
89*35238bceSAndroid Build Coastguard Worker     deMemPool *parent;     /*!< Pointer to parent (null for root pools).        */
90*35238bceSAndroid Build Coastguard Worker     deMemPoolUtil *util;   /*!< Utilities (callbacks etc.).                    */
91*35238bceSAndroid Build Coastguard Worker     int numChildren;       /*!< Number of child pools.                            */
92*35238bceSAndroid Build Coastguard Worker     deMemPool *firstChild; /*!< Pointer to first child pool in linked list.    */
93*35238bceSAndroid Build Coastguard Worker     deMemPool *prevPool;   /*!< Previous pool in parent's linked list.            */
94*35238bceSAndroid Build Coastguard Worker     deMemPool *nextPool;   /*!< Next pool in parent's linked list.                */
95*35238bceSAndroid Build Coastguard Worker 
96*35238bceSAndroid Build Coastguard Worker     MemPage *currentPage; /*!< Current memory page from which to allocate.    */
97*35238bceSAndroid Build Coastguard Worker 
98*35238bceSAndroid Build Coastguard Worker #if defined(DE_SUPPORT_FAILING_POOL_ALLOC)
99*35238bceSAndroid Build Coastguard Worker     bool allowFailing;   /*!< Is allocation failure simulation enabled?        */
100*35238bceSAndroid Build Coastguard Worker     deRandom failRandom; /*!< RNG for failing allocations.                    */
101*35238bceSAndroid Build Coastguard Worker #endif
102*35238bceSAndroid Build Coastguard Worker #if defined(DE_SUPPORT_DEBUG_POOLS)
103*35238bceSAndroid Build Coastguard Worker     bool enableDebugAllocs;         /*!< If true, always allocates using deMalloc().    */
104*35238bceSAndroid Build Coastguard Worker     DebugAlloc *debugAllocListHead; /*!< List of allocation in debug mode.                */
105*35238bceSAndroid Build Coastguard Worker 
106*35238bceSAndroid Build Coastguard Worker     int lastAllocatedIndex; /*!< Index of last allocated pool (rootPool only).    */
107*35238bceSAndroid Build Coastguard Worker     int allocIndex;         /*!< Allocation index (running counter).            */
108*35238bceSAndroid Build Coastguard Worker #endif
109*35238bceSAndroid Build Coastguard Worker #if defined(DE_SUPPORT_POOL_MEMORY_TRACKING)
110*35238bceSAndroid Build Coastguard Worker     int maxMemoryAllocated; /*!< Maximum amount of memory allocated from pools.    */
111*35238bceSAndroid Build Coastguard Worker     int maxMemoryCapacity;  /*!< Maximum amount of memory allocated for pools.    */
112*35238bceSAndroid Build Coastguard Worker #endif
113*35238bceSAndroid Build Coastguard Worker };
114*35238bceSAndroid Build Coastguard Worker 
115*35238bceSAndroid Build Coastguard Worker /*--------------------------------------------------------------------*//*!
116*35238bceSAndroid Build Coastguard Worker  * \internal
117*35238bceSAndroid Build Coastguard Worker  * \brief Initialize a memory page.
118*35238bceSAndroid Build Coastguard Worker  * \param page        Memory page to initialize.
119*35238bceSAndroid Build Coastguard Worker  * \param capacity    Capacity allocated for the memory page.
120*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
MemPage_init(MemPage * page,size_t capacity)121*35238bceSAndroid Build Coastguard Worker static void MemPage_init(MemPage *page, size_t capacity)
122*35238bceSAndroid Build Coastguard Worker {
123*35238bceSAndroid Build Coastguard Worker     memset(page, 0, sizeof(MemPage));
124*35238bceSAndroid Build Coastguard Worker #if defined(DE_DEBUG)
125*35238bceSAndroid Build Coastguard Worker     memset(page + 1, 0xCD, capacity);
126*35238bceSAndroid Build Coastguard Worker #endif
127*35238bceSAndroid Build Coastguard Worker     page->capacity = (int)capacity;
128*35238bceSAndroid Build Coastguard Worker }
129*35238bceSAndroid Build Coastguard Worker 
130*35238bceSAndroid Build Coastguard Worker /*--------------------------------------------------------------------*//*!
131*35238bceSAndroid Build Coastguard Worker  * \internal
132*35238bceSAndroid Build Coastguard Worker  * \brief Create a new memory page.
133*35238bceSAndroid Build Coastguard Worker  * \param capacity    Capacity for the memory page.
134*35238bceSAndroid Build Coastguard Worker  * \return The created memory page (or null on failure).
135*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
MemPage_create(size_t capacity)136*35238bceSAndroid Build Coastguard Worker static MemPage *MemPage_create(size_t capacity)
137*35238bceSAndroid Build Coastguard Worker {
138*35238bceSAndroid Build Coastguard Worker     MemPage *page = (MemPage *)deMalloc(sizeof(MemPage) + capacity);
139*35238bceSAndroid Build Coastguard Worker     if (!page)
140*35238bceSAndroid Build Coastguard Worker         return DE_NULL;
141*35238bceSAndroid Build Coastguard Worker 
142*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(deIsAlignedPtr(page + 1, MEM_PAGE_BASE_ALIGN));
143*35238bceSAndroid Build Coastguard Worker 
144*35238bceSAndroid Build Coastguard Worker     MemPage_init(page, capacity);
145*35238bceSAndroid Build Coastguard Worker     return page;
146*35238bceSAndroid Build Coastguard Worker }
147*35238bceSAndroid Build Coastguard Worker 
148*35238bceSAndroid Build Coastguard Worker /*--------------------------------------------------------------------*//*!
149*35238bceSAndroid Build Coastguard Worker  * \internal
150*35238bceSAndroid Build Coastguard Worker  * \brief Destroy a memory page.
151*35238bceSAndroid Build Coastguard Worker  * \param page    Memory page to destroy.
152*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
MemPage_destroy(MemPage * page)153*35238bceSAndroid Build Coastguard Worker static void MemPage_destroy(MemPage *page)
154*35238bceSAndroid Build Coastguard Worker {
155*35238bceSAndroid Build Coastguard Worker #if defined(DE_DEBUG)
156*35238bceSAndroid Build Coastguard Worker     /* Fill with garbage to hopefully catch dangling pointer bugs easier. */
157*35238bceSAndroid Build Coastguard Worker     uint8_t *dataPtr = (uint8_t *)(page + 1);
158*35238bceSAndroid Build Coastguard Worker     memset(dataPtr, 0xCD, (size_t)page->capacity);
159*35238bceSAndroid Build Coastguard Worker #endif
160*35238bceSAndroid Build Coastguard Worker     deFree(page);
161*35238bceSAndroid Build Coastguard Worker }
162*35238bceSAndroid Build Coastguard Worker 
163*35238bceSAndroid Build Coastguard Worker /*--------------------------------------------------------------------*//*!
164*35238bceSAndroid Build Coastguard Worker  * \internal
165*35238bceSAndroid Build Coastguard Worker  * \brief Internal function for creating a new memory pool.
166*35238bceSAndroid Build Coastguard Worker  * \param parent    Parent pool (may be null).
167*35238bceSAndroid Build Coastguard Worker  * \return The created memory pool (or null on failure).
168*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
createPoolInternal(deMemPool * parent)169*35238bceSAndroid Build Coastguard Worker static deMemPool *createPoolInternal(deMemPool *parent)
170*35238bceSAndroid Build Coastguard Worker {
171*35238bceSAndroid Build Coastguard Worker     deMemPool *pool;
172*35238bceSAndroid Build Coastguard Worker     MemPage *initialPage;
173*35238bceSAndroid Build Coastguard Worker 
174*35238bceSAndroid Build Coastguard Worker #if defined(DE_SUPPORT_FAILING_POOL_ALLOC)
175*35238bceSAndroid Build Coastguard Worker     if (parent && parent->allowFailing)
176*35238bceSAndroid Build Coastguard Worker     {
177*35238bceSAndroid Build Coastguard Worker         if ((deRandom_getUint32(&parent->failRandom) & 16383) <= 15)
178*35238bceSAndroid Build Coastguard Worker             return DE_NULL;
179*35238bceSAndroid Build Coastguard Worker     }
180*35238bceSAndroid Build Coastguard Worker #endif
181*35238bceSAndroid Build Coastguard Worker 
182*35238bceSAndroid Build Coastguard Worker     /* Init first page. */
183*35238bceSAndroid Build Coastguard Worker     initialPage = MemPage_create(INITIAL_PAGE_SIZE);
184*35238bceSAndroid Build Coastguard Worker     if (!initialPage)
185*35238bceSAndroid Build Coastguard Worker         return DE_NULL;
186*35238bceSAndroid Build Coastguard Worker 
187*35238bceSAndroid Build Coastguard Worker     /* Alloc pool from initial page. */
188*35238bceSAndroid Build Coastguard Worker     DE_ASSERT((int)sizeof(deMemPool) <= initialPage->capacity);
189*35238bceSAndroid Build Coastguard Worker     pool = (deMemPool *)(initialPage + 1);
190*35238bceSAndroid Build Coastguard Worker     initialPage->bytesAllocated += (int)sizeof(deMemPool);
191*35238bceSAndroid Build Coastguard Worker 
192*35238bceSAndroid Build Coastguard Worker     memset(pool, 0, sizeof(deMemPool));
193*35238bceSAndroid Build Coastguard Worker     pool->currentPage = initialPage;
194*35238bceSAndroid Build Coastguard Worker 
195*35238bceSAndroid Build Coastguard Worker     /* Register to parent. */
196*35238bceSAndroid Build Coastguard Worker     pool->parent = parent;
197*35238bceSAndroid Build Coastguard Worker     if (parent)
198*35238bceSAndroid Build Coastguard Worker     {
199*35238bceSAndroid Build Coastguard Worker         parent->numChildren++;
200*35238bceSAndroid Build Coastguard Worker         if (parent->firstChild)
201*35238bceSAndroid Build Coastguard Worker             parent->firstChild->prevPool = pool;
202*35238bceSAndroid Build Coastguard Worker         pool->nextPool     = parent->firstChild;
203*35238bceSAndroid Build Coastguard Worker         parent->firstChild = pool;
204*35238bceSAndroid Build Coastguard Worker     }
205*35238bceSAndroid Build Coastguard Worker 
206*35238bceSAndroid Build Coastguard Worker     /* Get utils from parent. */
207*35238bceSAndroid Build Coastguard Worker     pool->util = parent ? parent->util : DE_NULL;
208*35238bceSAndroid Build Coastguard Worker 
209*35238bceSAndroid Build Coastguard Worker #if defined(DE_SUPPORT_FAILING_POOL_ALLOC)
210*35238bceSAndroid Build Coastguard Worker     pool->allowFailing = parent ? parent->allowFailing : false;
211*35238bceSAndroid Build Coastguard Worker     deRandom_init(&pool->failRandom, parent ? deRandom_getUint32(&parent->failRandom) : 0x1234abcd);
212*35238bceSAndroid Build Coastguard Worker #endif
213*35238bceSAndroid Build Coastguard Worker 
214*35238bceSAndroid Build Coastguard Worker #if defined(DE_SUPPORT_DEBUG_POOLS)
215*35238bceSAndroid Build Coastguard Worker     pool->enableDebugAllocs  = parent ? parent->enableDebugAllocs : false;
216*35238bceSAndroid Build Coastguard Worker     pool->debugAllocListHead = DE_NULL;
217*35238bceSAndroid Build Coastguard Worker 
218*35238bceSAndroid Build Coastguard Worker     /* Pool allocation index. */
219*35238bceSAndroid Build Coastguard Worker     {
220*35238bceSAndroid Build Coastguard Worker         deMemPool *root = pool;
221*35238bceSAndroid Build Coastguard Worker         while (root->parent)
222*35238bceSAndroid Build Coastguard Worker             root = root->parent;
223*35238bceSAndroid Build Coastguard Worker 
224*35238bceSAndroid Build Coastguard Worker         if (pool == root)
225*35238bceSAndroid Build Coastguard Worker             root->lastAllocatedIndex = 0;
226*35238bceSAndroid Build Coastguard Worker 
227*35238bceSAndroid Build Coastguard Worker         pool->allocIndex = ++root->lastAllocatedIndex;
228*35238bceSAndroid Build Coastguard Worker 
229*35238bceSAndroid Build Coastguard Worker         /* \note Put the index of leaking pool here and add a breakpoint to catch leaks easily. */
230*35238bceSAndroid Build Coastguard Worker         /*        if (pool->allocIndex == 51)
231*35238bceSAndroid Build Coastguard Worker                     root = root;*/
232*35238bceSAndroid Build Coastguard Worker     }
233*35238bceSAndroid Build Coastguard Worker #endif
234*35238bceSAndroid Build Coastguard Worker 
235*35238bceSAndroid Build Coastguard Worker     return pool;
236*35238bceSAndroid Build Coastguard Worker }
237*35238bceSAndroid Build Coastguard Worker 
238*35238bceSAndroid Build Coastguard Worker /*--------------------------------------------------------------------*//*!
239*35238bceSAndroid Build Coastguard Worker  * \brief Create a new root memory pool.
240*35238bceSAndroid Build Coastguard Worker  * \return The created memory pool (or null on failure).
241*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
deMemPool_createRoot(const deMemPoolUtil * util,uint32_t flags)242*35238bceSAndroid Build Coastguard Worker deMemPool *deMemPool_createRoot(const deMemPoolUtil *util, uint32_t flags)
243*35238bceSAndroid Build Coastguard Worker {
244*35238bceSAndroid Build Coastguard Worker     deMemPool *pool = createPoolInternal(DE_NULL);
245*35238bceSAndroid Build Coastguard Worker     if (!pool)
246*35238bceSAndroid Build Coastguard Worker         return DE_NULL;
247*35238bceSAndroid Build Coastguard Worker #if defined(DE_SUPPORT_FAILING_POOL_ALLOC)
248*35238bceSAndroid Build Coastguard Worker     if (flags & DE_MEMPOOL_ENABLE_FAILING_ALLOCS)
249*35238bceSAndroid Build Coastguard Worker         pool->allowFailing = true;
250*35238bceSAndroid Build Coastguard Worker #endif
251*35238bceSAndroid Build Coastguard Worker #if defined(DE_SUPPORT_DEBUG_POOLS)
252*35238bceSAndroid Build Coastguard Worker     if (flags & DE_MEMPOOL_ENABLE_DEBUG_ALLOCS)
253*35238bceSAndroid Build Coastguard Worker     {
254*35238bceSAndroid Build Coastguard Worker         pool->enableDebugAllocs  = true;
255*35238bceSAndroid Build Coastguard Worker         pool->debugAllocListHead = DE_NULL;
256*35238bceSAndroid Build Coastguard Worker     }
257*35238bceSAndroid Build Coastguard Worker #endif
258*35238bceSAndroid Build Coastguard Worker     DE_UNREF(flags); /* in case no debug features enabled */
259*35238bceSAndroid Build Coastguard Worker 
260*35238bceSAndroid Build Coastguard Worker     /* Get copy of utilities. */
261*35238bceSAndroid Build Coastguard Worker     if (util)
262*35238bceSAndroid Build Coastguard Worker     {
263*35238bceSAndroid Build Coastguard Worker         deMemPoolUtil *utilCopy = DE_POOL_NEW(pool, deMemPoolUtil);
264*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(util->allocFailCallback);
265*35238bceSAndroid Build Coastguard Worker         if (!utilCopy)
266*35238bceSAndroid Build Coastguard Worker         {
267*35238bceSAndroid Build Coastguard Worker             deMemPool_destroy(pool);
268*35238bceSAndroid Build Coastguard Worker             return DE_NULL;
269*35238bceSAndroid Build Coastguard Worker         }
270*35238bceSAndroid Build Coastguard Worker 
271*35238bceSAndroid Build Coastguard Worker         memcpy(utilCopy, util, sizeof(deMemPoolUtil));
272*35238bceSAndroid Build Coastguard Worker         pool->util = utilCopy;
273*35238bceSAndroid Build Coastguard Worker     }
274*35238bceSAndroid Build Coastguard Worker 
275*35238bceSAndroid Build Coastguard Worker     return pool;
276*35238bceSAndroid Build Coastguard Worker }
277*35238bceSAndroid Build Coastguard Worker 
278*35238bceSAndroid Build Coastguard Worker /*--------------------------------------------------------------------*//*!
279*35238bceSAndroid Build Coastguard Worker  * \brief Create a sub-pool for an existing memory pool.
280*35238bceSAndroid Build Coastguard Worker  * \return The created memory pool (or null on failure).
281*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
deMemPool_create(deMemPool * parent)282*35238bceSAndroid Build Coastguard Worker deMemPool *deMemPool_create(deMemPool *parent)
283*35238bceSAndroid Build Coastguard Worker {
284*35238bceSAndroid Build Coastguard Worker     deMemPool *pool;
285*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(parent);
286*35238bceSAndroid Build Coastguard Worker     pool = createPoolInternal(parent);
287*35238bceSAndroid Build Coastguard Worker     if (!pool && parent->util)
288*35238bceSAndroid Build Coastguard Worker         parent->util->allocFailCallback(parent->util->userPointer);
289*35238bceSAndroid Build Coastguard Worker     return pool;
290*35238bceSAndroid Build Coastguard Worker }
291*35238bceSAndroid Build Coastguard Worker 
292*35238bceSAndroid Build Coastguard Worker /*--------------------------------------------------------------------*//*!
293*35238bceSAndroid Build Coastguard Worker  * \brief Destroy a memory pool.
294*35238bceSAndroid Build Coastguard Worker  * \param pool    Pool to be destroyed.
295*35238bceSAndroid Build Coastguard Worker  *
296*35238bceSAndroid Build Coastguard Worker  * Frees all the memory allocated from the pool. Also destroyed any child
297*35238bceSAndroid Build Coastguard Worker  * pools that the pool has (recursively).
298*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
deMemPool_destroy(deMemPool * pool)299*35238bceSAndroid Build Coastguard Worker void deMemPool_destroy(deMemPool *pool)
300*35238bceSAndroid Build Coastguard Worker {
301*35238bceSAndroid Build Coastguard Worker     deMemPool *iter;
302*35238bceSAndroid Build Coastguard Worker     deMemPool *iterNext;
303*35238bceSAndroid Build Coastguard Worker 
304*35238bceSAndroid Build Coastguard Worker #if defined(DE_SUPPORT_POOL_MEMORY_TRACKING)
305*35238bceSAndroid Build Coastguard Worker     /* Update memory consumption statistics. */
306*35238bceSAndroid Build Coastguard Worker     if (pool->parent)
307*35238bceSAndroid Build Coastguard Worker     {
308*35238bceSAndroid Build Coastguard Worker         deMemPool *root = pool->parent;
309*35238bceSAndroid Build Coastguard Worker         while (root->parent)
310*35238bceSAndroid Build Coastguard Worker             root = root->parent;
311*35238bceSAndroid Build Coastguard Worker         root->maxMemoryAllocated = deMax32(root->maxMemoryAllocated, deMemPool_getNumAllocatedBytes(root, true));
312*35238bceSAndroid Build Coastguard Worker         root->maxMemoryCapacity  = deMax32(root->maxMemoryCapacity, deMemPool_getCapacity(root, true));
313*35238bceSAndroid Build Coastguard Worker     }
314*35238bceSAndroid Build Coastguard Worker #endif
315*35238bceSAndroid Build Coastguard Worker 
316*35238bceSAndroid Build Coastguard Worker     /* Destroy all children. */
317*35238bceSAndroid Build Coastguard Worker     iter = pool->firstChild;
318*35238bceSAndroid Build Coastguard Worker     while (iter)
319*35238bceSAndroid Build Coastguard Worker     {
320*35238bceSAndroid Build Coastguard Worker         iterNext = iter->nextPool;
321*35238bceSAndroid Build Coastguard Worker         deMemPool_destroy(iter);
322*35238bceSAndroid Build Coastguard Worker         iter = iterNext;
323*35238bceSAndroid Build Coastguard Worker     }
324*35238bceSAndroid Build Coastguard Worker 
325*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(pool->numChildren == 0);
326*35238bceSAndroid Build Coastguard Worker 
327*35238bceSAndroid Build Coastguard Worker     /* Update pointers. */
328*35238bceSAndroid Build Coastguard Worker     if (pool->prevPool)
329*35238bceSAndroid Build Coastguard Worker         pool->prevPool->nextPool = pool->nextPool;
330*35238bceSAndroid Build Coastguard Worker     if (pool->nextPool)
331*35238bceSAndroid Build Coastguard Worker         pool->nextPool->prevPool = pool->prevPool;
332*35238bceSAndroid Build Coastguard Worker 
333*35238bceSAndroid Build Coastguard Worker     if (pool->parent)
334*35238bceSAndroid Build Coastguard Worker     {
335*35238bceSAndroid Build Coastguard Worker         deMemPool *parent = pool->parent;
336*35238bceSAndroid Build Coastguard Worker         if (parent->firstChild == pool)
337*35238bceSAndroid Build Coastguard Worker             parent->firstChild = pool->nextPool;
338*35238bceSAndroid Build Coastguard Worker 
339*35238bceSAndroid Build Coastguard Worker         parent->numChildren--;
340*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(parent->numChildren >= 0);
341*35238bceSAndroid Build Coastguard Worker     }
342*35238bceSAndroid Build Coastguard Worker 
343*35238bceSAndroid Build Coastguard Worker #if defined(DE_SUPPORT_DEBUG_POOLS)
344*35238bceSAndroid Build Coastguard Worker     /* Free all debug allocations. */
345*35238bceSAndroid Build Coastguard Worker     if (pool->enableDebugAllocs)
346*35238bceSAndroid Build Coastguard Worker     {
347*35238bceSAndroid Build Coastguard Worker         DebugAlloc *alloc = pool->debugAllocListHead;
348*35238bceSAndroid Build Coastguard Worker         DebugAlloc *next;
349*35238bceSAndroid Build Coastguard Worker 
350*35238bceSAndroid Build Coastguard Worker         while (alloc)
351*35238bceSAndroid Build Coastguard Worker         {
352*35238bceSAndroid Build Coastguard Worker             next = alloc->next;
353*35238bceSAndroid Build Coastguard Worker             deAlignedFree(alloc->memPtr);
354*35238bceSAndroid Build Coastguard Worker             deFree(alloc);
355*35238bceSAndroid Build Coastguard Worker             alloc = next;
356*35238bceSAndroid Build Coastguard Worker         }
357*35238bceSAndroid Build Coastguard Worker 
358*35238bceSAndroid Build Coastguard Worker         pool->debugAllocListHead = DE_NULL;
359*35238bceSAndroid Build Coastguard Worker     }
360*35238bceSAndroid Build Coastguard Worker #endif
361*35238bceSAndroid Build Coastguard Worker 
362*35238bceSAndroid Build Coastguard Worker     /* Free pages. */
363*35238bceSAndroid Build Coastguard Worker     /* \note Pool itself is allocated from first page, so we must not touch the pool after freeing the page! */
364*35238bceSAndroid Build Coastguard Worker     {
365*35238bceSAndroid Build Coastguard Worker         MemPage *page = pool->currentPage;
366*35238bceSAndroid Build Coastguard Worker         MemPage *nextPage;
367*35238bceSAndroid Build Coastguard Worker 
368*35238bceSAndroid Build Coastguard Worker         while (page)
369*35238bceSAndroid Build Coastguard Worker         {
370*35238bceSAndroid Build Coastguard Worker             nextPage = page->nextPage;
371*35238bceSAndroid Build Coastguard Worker             MemPage_destroy(page);
372*35238bceSAndroid Build Coastguard Worker             page = nextPage;
373*35238bceSAndroid Build Coastguard Worker         }
374*35238bceSAndroid Build Coastguard Worker     }
375*35238bceSAndroid Build Coastguard Worker }
376*35238bceSAndroid Build Coastguard Worker 
377*35238bceSAndroid Build Coastguard Worker /*--------------------------------------------------------------------*//*!
378*35238bceSAndroid Build Coastguard Worker  * \brief Get the number of children for a pool.
379*35238bceSAndroid Build Coastguard Worker  * \return The number of (immediate) child pools a memory pool has.
380*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
deMemPool_getNumChildren(const deMemPool * pool)381*35238bceSAndroid Build Coastguard Worker int deMemPool_getNumChildren(const deMemPool *pool)
382*35238bceSAndroid Build Coastguard Worker {
383*35238bceSAndroid Build Coastguard Worker     return pool->numChildren;
384*35238bceSAndroid Build Coastguard Worker }
385*35238bceSAndroid Build Coastguard Worker 
386*35238bceSAndroid Build Coastguard Worker /*--------------------------------------------------------------------*//*!
387*35238bceSAndroid Build Coastguard Worker  * \brief Get the number of bytes allocated (by the user) from the pool.
388*35238bceSAndroid Build Coastguard Worker  * \param pool        Pool pointer.
389*35238bceSAndroid Build Coastguard Worker  * \param recurse    Is operation recursive to child pools?
390*35238bceSAndroid Build Coastguard Worker  * \return The number of bytes allocated by the pool (including child pools
391*35238bceSAndroid Build Coastguard Worker  *           if 'recurse' is true).
392*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
deMemPool_getNumAllocatedBytes(const deMemPool * pool,bool recurse)393*35238bceSAndroid Build Coastguard Worker int deMemPool_getNumAllocatedBytes(const deMemPool *pool, bool recurse)
394*35238bceSAndroid Build Coastguard Worker {
395*35238bceSAndroid Build Coastguard Worker     int numAllocatedBytes = 0;
396*35238bceSAndroid Build Coastguard Worker     MemPage *memPage;
397*35238bceSAndroid Build Coastguard Worker 
398*35238bceSAndroid Build Coastguard Worker     for (memPage = pool->currentPage; memPage; memPage = memPage->nextPage)
399*35238bceSAndroid Build Coastguard Worker         numAllocatedBytes += memPage->bytesAllocated;
400*35238bceSAndroid Build Coastguard Worker 
401*35238bceSAndroid Build Coastguard Worker     if (recurse)
402*35238bceSAndroid Build Coastguard Worker     {
403*35238bceSAndroid Build Coastguard Worker         deMemPool *child;
404*35238bceSAndroid Build Coastguard Worker         for (child = pool->firstChild; child; child = child->nextPool)
405*35238bceSAndroid Build Coastguard Worker             numAllocatedBytes += deMemPool_getNumAllocatedBytes(child, true);
406*35238bceSAndroid Build Coastguard Worker     }
407*35238bceSAndroid Build Coastguard Worker 
408*35238bceSAndroid Build Coastguard Worker     return numAllocatedBytes;
409*35238bceSAndroid Build Coastguard Worker }
410*35238bceSAndroid Build Coastguard Worker 
deMemPool_getCapacity(const deMemPool * pool,bool recurse)411*35238bceSAndroid Build Coastguard Worker int deMemPool_getCapacity(const deMemPool *pool, bool recurse)
412*35238bceSAndroid Build Coastguard Worker {
413*35238bceSAndroid Build Coastguard Worker     int numCapacityBytes = 0;
414*35238bceSAndroid Build Coastguard Worker     MemPage *memPage;
415*35238bceSAndroid Build Coastguard Worker 
416*35238bceSAndroid Build Coastguard Worker     for (memPage = pool->currentPage; memPage; memPage = memPage->nextPage)
417*35238bceSAndroid Build Coastguard Worker         numCapacityBytes += memPage->capacity;
418*35238bceSAndroid Build Coastguard Worker 
419*35238bceSAndroid Build Coastguard Worker     if (recurse)
420*35238bceSAndroid Build Coastguard Worker     {
421*35238bceSAndroid Build Coastguard Worker         deMemPool *child;
422*35238bceSAndroid Build Coastguard Worker         for (child = pool->firstChild; child; child = child->nextPool)
423*35238bceSAndroid Build Coastguard Worker             numCapacityBytes += deMemPool_getCapacity(child, true);
424*35238bceSAndroid Build Coastguard Worker     }
425*35238bceSAndroid Build Coastguard Worker 
426*35238bceSAndroid Build Coastguard Worker     return numCapacityBytes;
427*35238bceSAndroid Build Coastguard Worker }
428*35238bceSAndroid Build Coastguard Worker 
deMemPool_allocInternal(deMemPool * pool,size_t numBytes,uint32_t alignBytes)429*35238bceSAndroid Build Coastguard Worker DE_INLINE void *deMemPool_allocInternal(deMemPool *pool, size_t numBytes, uint32_t alignBytes)
430*35238bceSAndroid Build Coastguard Worker {
431*35238bceSAndroid Build Coastguard Worker     MemPage *curPage = pool->currentPage;
432*35238bceSAndroid Build Coastguard Worker 
433*35238bceSAndroid Build Coastguard Worker #if defined(DE_SUPPORT_FAILING_POOL_ALLOC)
434*35238bceSAndroid Build Coastguard Worker     if (pool->allowFailing)
435*35238bceSAndroid Build Coastguard Worker     {
436*35238bceSAndroid Build Coastguard Worker         if ((deRandom_getUint32(&pool->failRandom) & 16383) <= 15)
437*35238bceSAndroid Build Coastguard Worker             return DE_NULL;
438*35238bceSAndroid Build Coastguard Worker     }
439*35238bceSAndroid Build Coastguard Worker #endif
440*35238bceSAndroid Build Coastguard Worker 
441*35238bceSAndroid Build Coastguard Worker #if defined(DE_SUPPORT_DEBUG_POOLS)
442*35238bceSAndroid Build Coastguard Worker     if (pool->enableDebugAllocs)
443*35238bceSAndroid Build Coastguard Worker     {
444*35238bceSAndroid Build Coastguard Worker         DebugAlloc *header = DE_NEW(DebugAlloc);
445*35238bceSAndroid Build Coastguard Worker         void *ptr          = deAlignedMalloc(numBytes, alignBytes);
446*35238bceSAndroid Build Coastguard Worker 
447*35238bceSAndroid Build Coastguard Worker         if (!header || !ptr)
448*35238bceSAndroid Build Coastguard Worker         {
449*35238bceSAndroid Build Coastguard Worker             deFree(header);
450*35238bceSAndroid Build Coastguard Worker             deAlignedFree(ptr);
451*35238bceSAndroid Build Coastguard Worker             return DE_NULL;
452*35238bceSAndroid Build Coastguard Worker         }
453*35238bceSAndroid Build Coastguard Worker 
454*35238bceSAndroid Build Coastguard Worker         header->memPtr           = ptr;
455*35238bceSAndroid Build Coastguard Worker         header->next             = pool->debugAllocListHead;
456*35238bceSAndroid Build Coastguard Worker         pool->debugAllocListHead = header;
457*35238bceSAndroid Build Coastguard Worker 
458*35238bceSAndroid Build Coastguard Worker         return ptr;
459*35238bceSAndroid Build Coastguard Worker     }
460*35238bceSAndroid Build Coastguard Worker #endif
461*35238bceSAndroid Build Coastguard Worker 
462*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(curPage);
463*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(deIsPowerOfTwo32((int)alignBytes));
464*35238bceSAndroid Build Coastguard Worker     {
465*35238bceSAndroid Build Coastguard Worker         void *curPagePtr    = (void *)((uint8_t *)(curPage + 1) + curPage->bytesAllocated);
466*35238bceSAndroid Build Coastguard Worker         void *alignedPtr    = deAlignPtr(curPagePtr, alignBytes);
467*35238bceSAndroid Build Coastguard Worker         size_t alignPadding = (size_t)((uintptr_t)alignedPtr - (uintptr_t)curPagePtr);
468*35238bceSAndroid Build Coastguard Worker 
469*35238bceSAndroid Build Coastguard Worker         if (numBytes + alignPadding > (size_t)(curPage->capacity - curPage->bytesAllocated))
470*35238bceSAndroid Build Coastguard Worker         {
471*35238bceSAndroid Build Coastguard Worker             /* Does not fit to current page. */
472*35238bceSAndroid Build Coastguard Worker             int maxAlignPadding = deMax32(0, ((int)alignBytes) - MEM_PAGE_BASE_ALIGN);
473*35238bceSAndroid Build Coastguard Worker             int newPageCapacity =
474*35238bceSAndroid Build Coastguard Worker                 deMax32(deMin32(2 * curPage->capacity, MAX_PAGE_SIZE), ((int)numBytes) + maxAlignPadding);
475*35238bceSAndroid Build Coastguard Worker 
476*35238bceSAndroid Build Coastguard Worker             curPage = MemPage_create((size_t)newPageCapacity);
477*35238bceSAndroid Build Coastguard Worker             if (!curPage)
478*35238bceSAndroid Build Coastguard Worker                 return DE_NULL;
479*35238bceSAndroid Build Coastguard Worker 
480*35238bceSAndroid Build Coastguard Worker             curPage->nextPage = pool->currentPage;
481*35238bceSAndroid Build Coastguard Worker             pool->currentPage = curPage;
482*35238bceSAndroid Build Coastguard Worker 
483*35238bceSAndroid Build Coastguard Worker             DE_ASSERT(curPage->bytesAllocated == 0);
484*35238bceSAndroid Build Coastguard Worker 
485*35238bceSAndroid Build Coastguard Worker             curPagePtr   = (void *)(curPage + 1);
486*35238bceSAndroid Build Coastguard Worker             alignedPtr   = deAlignPtr(curPagePtr, alignBytes);
487*35238bceSAndroid Build Coastguard Worker             alignPadding = (size_t)((uintptr_t)alignedPtr - (uintptr_t)curPagePtr);
488*35238bceSAndroid Build Coastguard Worker 
489*35238bceSAndroid Build Coastguard Worker             DE_ASSERT(numBytes + alignPadding <= (size_t)curPage->capacity);
490*35238bceSAndroid Build Coastguard Worker         }
491*35238bceSAndroid Build Coastguard Worker 
492*35238bceSAndroid Build Coastguard Worker         curPage->bytesAllocated += (int)(numBytes + alignPadding);
493*35238bceSAndroid Build Coastguard Worker         return alignedPtr;
494*35238bceSAndroid Build Coastguard Worker     }
495*35238bceSAndroid Build Coastguard Worker }
496*35238bceSAndroid Build Coastguard Worker 
497*35238bceSAndroid Build Coastguard Worker /*--------------------------------------------------------------------*//*!
498*35238bceSAndroid Build Coastguard Worker  * \brief Allocate memory from a pool.
499*35238bceSAndroid Build Coastguard Worker  * \param pool        Memory pool to allocate from.
500*35238bceSAndroid Build Coastguard Worker  * \param numBytes    Number of bytes to allocate.
501*35238bceSAndroid Build Coastguard Worker  * \return Pointer to the allocate memory (or null on failure).
502*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
deMemPool_alloc(deMemPool * pool,size_t numBytes)503*35238bceSAndroid Build Coastguard Worker void *deMemPool_alloc(deMemPool *pool, size_t numBytes)
504*35238bceSAndroid Build Coastguard Worker {
505*35238bceSAndroid Build Coastguard Worker     void *ptr;
506*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(pool);
507*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(numBytes > 0);
508*35238bceSAndroid Build Coastguard Worker     ptr = deMemPool_allocInternal(pool, numBytes, DE_POOL_DEFAULT_ALLOC_ALIGNMENT);
509*35238bceSAndroid Build Coastguard Worker     if (!ptr && pool->util)
510*35238bceSAndroid Build Coastguard Worker         pool->util->allocFailCallback(pool->util->userPointer);
511*35238bceSAndroid Build Coastguard Worker     return ptr;
512*35238bceSAndroid Build Coastguard Worker }
513*35238bceSAndroid Build Coastguard Worker 
514*35238bceSAndroid Build Coastguard Worker /*--------------------------------------------------------------------*//*!
515*35238bceSAndroid Build Coastguard Worker  * \brief Allocate aligned memory from a pool.
516*35238bceSAndroid Build Coastguard Worker  * \param pool            Memory pool to allocate from.
517*35238bceSAndroid Build Coastguard Worker  * \param numBytes        Number of bytes to allocate.
518*35238bceSAndroid Build Coastguard Worker  * \param alignBytes    Required alignment in bytes, must be power of two.
519*35238bceSAndroid Build Coastguard Worker  * \return Pointer to the allocate memory (or null on failure).
520*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
deMemPool_alignedAlloc(deMemPool * pool,size_t numBytes,uint32_t alignBytes)521*35238bceSAndroid Build Coastguard Worker void *deMemPool_alignedAlloc(deMemPool *pool, size_t numBytes, uint32_t alignBytes)
522*35238bceSAndroid Build Coastguard Worker {
523*35238bceSAndroid Build Coastguard Worker     void *ptr;
524*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(pool);
525*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(numBytes > 0);
526*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(deIsPowerOfTwo32((int)alignBytes));
527*35238bceSAndroid Build Coastguard Worker     ptr = deMemPool_allocInternal(pool, numBytes, alignBytes);
528*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(deIsAlignedPtr(ptr, alignBytes));
529*35238bceSAndroid Build Coastguard Worker     if (!ptr && pool->util)
530*35238bceSAndroid Build Coastguard Worker         pool->util->allocFailCallback(pool->util->userPointer);
531*35238bceSAndroid Build Coastguard Worker     return ptr;
532*35238bceSAndroid Build Coastguard Worker }
533*35238bceSAndroid Build Coastguard Worker 
534*35238bceSAndroid Build Coastguard Worker /*--------------------------------------------------------------------*//*!
535*35238bceSAndroid Build Coastguard Worker  * \brief Duplicate a piece of memory into a memory pool.
536*35238bceSAndroid Build Coastguard Worker  * \param pool    Memory pool to allocate from.
537*35238bceSAndroid Build Coastguard Worker  * \param ptr    Piece of memory to duplicate.
538*35238bceSAndroid Build Coastguard Worker  * \return Pointer to the copied memory block (or null on failure).
539*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
deMemPool_memDup(deMemPool * pool,const void * ptr,size_t numBytes)540*35238bceSAndroid Build Coastguard Worker void *deMemPool_memDup(deMemPool *pool, const void *ptr, size_t numBytes)
541*35238bceSAndroid Build Coastguard Worker {
542*35238bceSAndroid Build Coastguard Worker     void *newPtr = deMemPool_alloc(pool, numBytes);
543*35238bceSAndroid Build Coastguard Worker     if (newPtr)
544*35238bceSAndroid Build Coastguard Worker         memcpy(newPtr, ptr, numBytes);
545*35238bceSAndroid Build Coastguard Worker     return newPtr;
546*35238bceSAndroid Build Coastguard Worker }
547*35238bceSAndroid Build Coastguard Worker 
548*35238bceSAndroid Build Coastguard Worker /*--------------------------------------------------------------------*//*!
549*35238bceSAndroid Build Coastguard Worker  * \brief Duplicate a string into a memory pool.
550*35238bceSAndroid Build Coastguard Worker  * \param pool    Memory pool to allocate from.
551*35238bceSAndroid Build Coastguard Worker  * \param str    String to duplicate.
552*35238bceSAndroid Build Coastguard Worker  * \return Pointer to the new string (or null on failure).
553*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
deMemPool_strDup(deMemPool * pool,const char * str)554*35238bceSAndroid Build Coastguard Worker char *deMemPool_strDup(deMemPool *pool, const char *str)
555*35238bceSAndroid Build Coastguard Worker {
556*35238bceSAndroid Build Coastguard Worker     size_t len   = strlen(str);
557*35238bceSAndroid Build Coastguard Worker     char *newStr = (char *)deMemPool_alloc(pool, len + 1);
558*35238bceSAndroid Build Coastguard Worker     if (newStr)
559*35238bceSAndroid Build Coastguard Worker         memcpy(newStr, str, len + 1);
560*35238bceSAndroid Build Coastguard Worker     return newStr;
561*35238bceSAndroid Build Coastguard Worker }
562*35238bceSAndroid Build Coastguard Worker 
563*35238bceSAndroid Build Coastguard Worker /*--------------------------------------------------------------------*//*!
564*35238bceSAndroid Build Coastguard Worker  * \brief Duplicate a string into a memory pool, with a maximum length.
565*35238bceSAndroid Build Coastguard Worker  * \param pool        Memory pool to allocate from.
566*35238bceSAndroid Build Coastguard Worker  * \param str        String to duplicate.
567*35238bceSAndroid Build Coastguard Worker  * \param maxLength    Maximum number of characters to duplicate.
568*35238bceSAndroid Build Coastguard Worker  * \return Pointer to the new string (or null on failure).
569*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
deMemPool_strnDup(deMemPool * pool,const char * str,int maxLength)570*35238bceSAndroid Build Coastguard Worker char *deMemPool_strnDup(deMemPool *pool, const char *str, int maxLength)
571*35238bceSAndroid Build Coastguard Worker {
572*35238bceSAndroid Build Coastguard Worker     size_t len   = (size_t)deMin32((int)strlen(str), deMax32(0, maxLength));
573*35238bceSAndroid Build Coastguard Worker     char *newStr = (char *)deMemPool_alloc(pool, len + 1);
574*35238bceSAndroid Build Coastguard Worker 
575*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(maxLength >= 0);
576*35238bceSAndroid Build Coastguard Worker 
577*35238bceSAndroid Build Coastguard Worker     if (newStr)
578*35238bceSAndroid Build Coastguard Worker     {
579*35238bceSAndroid Build Coastguard Worker         memcpy(newStr, str, len);
580*35238bceSAndroid Build Coastguard Worker         newStr[len] = 0;
581*35238bceSAndroid Build Coastguard Worker     }
582*35238bceSAndroid Build Coastguard Worker     return newStr;
583*35238bceSAndroid Build Coastguard Worker }
584*35238bceSAndroid Build Coastguard Worker 
585*35238bceSAndroid Build Coastguard Worker #if defined(DE_SUPPORT_POOL_MEMORY_TRACKING)
586*35238bceSAndroid Build Coastguard Worker 
deMemPool_getMaxNumAllocatedBytes(const deMemPool * pool)587*35238bceSAndroid Build Coastguard Worker int deMemPool_getMaxNumAllocatedBytes(const deMemPool *pool)
588*35238bceSAndroid Build Coastguard Worker {
589*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(pool && !pool->parent); /* must be root */
590*35238bceSAndroid Build Coastguard Worker     return deMax32(pool->maxMemoryAllocated, deMemPool_getNumAllocatedBytes(pool, true));
591*35238bceSAndroid Build Coastguard Worker }
592*35238bceSAndroid Build Coastguard Worker 
deMemPool_getMaxCapacity(const deMemPool * pool)593*35238bceSAndroid Build Coastguard Worker int deMemPool_getMaxCapacity(const deMemPool *pool)
594*35238bceSAndroid Build Coastguard Worker {
595*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(pool && !pool->parent); /* must be root */
596*35238bceSAndroid Build Coastguard Worker     return deMax32(pool->maxMemoryCapacity, deMemPool_getCapacity(pool, true));
597*35238bceSAndroid Build Coastguard Worker }
598*35238bceSAndroid Build Coastguard Worker 
599*35238bceSAndroid Build Coastguard Worker #endif
600