13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*-------------------------------------------------------------------------
23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * drawElements Memory Pool Library
33c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * --------------------------------
43c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
53c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Copyright 2014 The Android Open Source Project
63c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
73c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Licensed under the Apache License, Version 2.0 (the "License");
83c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * you may not use this file except in compliance with the License.
93c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * You may obtain a copy of the License at
103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *      http://www.apache.org/licenses/LICENSE-2.0
123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Unless required by applicable law or agreed to in writing, software
143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * distributed under the License is distributed on an "AS IS" BASIS,
153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * See the License for the specific language governing permissions and
173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * limitations under the License.
183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*!
203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \file
213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Memory pool management.
223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deMemPool.h"
253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deMemory.h"
263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deInt32.h"
273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#if defined(DE_SUPPORT_FAILING_POOL_ALLOC)
293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#	include "deRandom.h"
303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif
313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <stdlib.h>
333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <string.h>
343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
353c827367444ee418f129b2c238299f49d3264554Jarkko Poyryenum
363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	INITIAL_PAGE_SIZE		= 128,		/*!< Size for the first allocated memory page.			*/
383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	MAX_PAGE_SIZE			= 8096,		/*!< Maximum size for a memory page.					*/
393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	MEM_PAGE_BASE_ALIGN		= 4			/*!< Base alignment guarantee for mem page data ptr.	*/
403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
423c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytypedef struct MemPage_s MemPage;
433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \internal
463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Memory page header.
473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Represent a page of memory allocate by a memory pool.
493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
503c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct MemPage_s
513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int			capacity;
533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int			bytesAllocated;
543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	MemPage*	nextPage;
563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#if defined(DE_SUPPORT_DEBUG_POOLS)
593c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytypedef struct DebugAlloc_s DebugAlloc;
603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
613c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct DebugAlloc_s
623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void*			memPtr;
643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DebugAlloc*		next;
653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif
673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Memory pool.
703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * A pool of memory from which individual memory allocations can be made.
723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * The memory pools don't have a freeing operation for individual allocations,
733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * but rather all of the memory allocated from a pool is freed when the pool
743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * is destroyed.
753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * The pools can be arranged into a hierarchy. If a pool with children is
773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * destroyed, all of the children are first recursively destroyed and then
783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * the pool itself.
793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * The memory pools support a feature where individual allocations can be
813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * made to simulate failure (i.e., return null). This can be enabled by
823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * creating the root pool with the deMemPool_createFailingRoot() function.
833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * When the feature is enabled, also creation of sub-pools occasionally
843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * fails.
853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
863c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct deMemPool_s
873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32		flags;				/*!< Flags.											*/
893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deMemPool*		parent;				/*!< Pointer to parent (null for root pools).		*/
903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deMemPoolUtil*	util;				/*!< Utilities (callbacks etc.).					*/
913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int				numChildren;		/*!< Number of child pools.							*/
923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deMemPool*		firstChild;			/*!< Pointer to first child pool in linked list.	*/
933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deMemPool*		prevPool;			/*!< Previous pool in parent's linked list.			*/
943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deMemPool*		nextPool;			/*!< Next pool in parent's linked list.				*/
953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	MemPage*		currentPage;		/*!< Current memory page from which to allocate.	*/
973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#if defined(DE_SUPPORT_FAILING_POOL_ALLOC)
993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deBool			allowFailing;		/*!< Is allocation failure simulation enabled?		*/
1003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deRandom		failRandom;			/*!< RNG for failing allocations.					*/
1013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif
1023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#if defined(DE_SUPPORT_DEBUG_POOLS)
1033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deBool			enableDebugAllocs;	/*!< If true, always allocates using deMalloc().	*/
1043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DebugAlloc*		debugAllocListHead;	/*!< List of allocation in debug mode.				*/
1053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int				lastAllocatedIndex;	/*!< Index of last allocated pool (rootPool only).	*/
1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int				allocIndex;			/*!< Allocation index (running counter).			*/
1083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif
1093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#if defined(DE_SUPPORT_POOL_MEMORY_TRACKING)
1103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int				maxMemoryAllocated;	/*!< Maximum amount of memory allocated from pools.	*/
1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int				maxMemoryCapacity;	/*!< Maximum amount of memory allocated for pools.	*/
1123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif
1133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
1143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
1163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \internal
1173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Initialize a memory page.
1183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \param page		Memory page to initialize.
1193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \param capacity	Capacity allocated for the memory page.
1203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
1218eb43bbbb25645f6765f79608da7fea6f2e9d86cJarkko Pöyrystatic void MemPage_init (MemPage* page, size_t capacity)
1223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	memset(page, 0, sizeof(MemPage));
1243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#if defined(DE_DEBUG)
1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	memset(page + 1, 0xCD, capacity);
1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif
1278eb43bbbb25645f6765f79608da7fea6f2e9d86cJarkko Pöyry	page->capacity = (int)capacity;
1283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \internal
1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Create a new memory page.
1333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \param capacity	Capacity for the memory page.
1343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \return The created memory page (or null on failure).
1353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
1368eb43bbbb25645f6765f79608da7fea6f2e9d86cJarkko Pöyrystatic MemPage* MemPage_create (size_t capacity)
1373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	MemPage* page = (MemPage*)deMalloc(sizeof(MemPage) + capacity);
1393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!page)
1403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_NULL;
1413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(deIsAlignedPtr(page+1, MEM_PAGE_BASE_ALIGN));
1433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	MemPage_init(page, capacity);
1453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return page;
1463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
1493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \internal
1503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Destroy a memory page.
1513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \param page	Memory page to destroy.
1523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
1533c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void MemPage_destroy (MemPage* page)
1543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#if defined(DE_DEBUG)
1563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Fill with garbage to hopefully catch dangling pointer bugs easier. */
1573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint8* dataPtr = (deUint8*)(page + 1);
15824ceed3e1acf66512ee25ee75002198b6672879dJarkko Pöyry	memset(dataPtr, 0xCD, (size_t)page->capacity);
1593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif
1603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deFree(page);
1613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
1643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \internal
1653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Internal function for creating a new memory pool.
1663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \param parent	Parent pool (may be null).
1673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \return The created memory pool (or null on failure).
1683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
1693c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic deMemPool* createPoolInternal (deMemPool* parent)
1703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deMemPool*	pool;
1723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	MemPage*	initialPage;
1733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#if defined(DE_SUPPORT_FAILING_POOL_ALLOC)
1753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (parent && parent->allowFailing)
1763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if ((deRandom_getUint32(&parent->failRandom) & 16383) <= 15)
1783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return DE_NULL;
1793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif
1813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Init first page. */
1833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	initialPage = MemPage_create(INITIAL_PAGE_SIZE);
1843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!initialPage)
1853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_NULL;
1863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Alloc pool from initial page. */
1883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT((int)sizeof(deMemPool) <= initialPage->capacity);
1893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	pool = (deMemPool*)(initialPage + 1);
1903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	initialPage->bytesAllocated += (int)sizeof(deMemPool);
1913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	memset(pool, 0, sizeof(deMemPool));
1933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	pool->currentPage = initialPage;
1943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Register to parent. */
1963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	pool->parent = parent;
1973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (parent)
1983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		parent->numChildren++;
2003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (parent->firstChild) parent->firstChild->prevPool = pool;
2013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		pool->nextPool = parent->firstChild;
2023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		parent->firstChild = pool;
2033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Get utils from parent. */
2063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	pool->util = parent ? parent->util : DE_NULL;
2073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#if defined(DE_SUPPORT_FAILING_POOL_ALLOC)
2093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	pool->allowFailing = parent ? parent->allowFailing : DE_FALSE;
2103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deRandom_init(&pool->failRandom, parent ? deRandom_getUint32(&parent->failRandom) : 0x1234abcd);
2113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif
2123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#if defined(DE_SUPPORT_DEBUG_POOLS)
2143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	pool->enableDebugAllocs		= parent ? parent->enableDebugAllocs : DE_FALSE;
2153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	pool->debugAllocListHead	= DE_NULL;
2163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Pool allocation index. */
2183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deMemPool* root = pool;
2203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		while (root->parent)
2213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			root = root->parent;
2223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (pool == root)
2243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			root->lastAllocatedIndex = 0;
2253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		pool->allocIndex = ++root->lastAllocatedIndex;
2273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		/* \note Put the index of leaking pool here and add a breakpoint to catch leaks easily. */
2293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*		if (pool->allocIndex == 51)
2303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			root = root;*/
2313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif
2333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return pool;
2353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
2383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Create a new root memory pool.
2393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \return The created memory pool (or null on failure).
2403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
2413c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeMemPool* deMemPool_createRoot	(const deMemPoolUtil* util, deUint32 flags)
2423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deMemPool* pool = createPoolInternal(DE_NULL);
2443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!pool)
2453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return DE_NULL;
2463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#if defined(DE_SUPPORT_FAILING_POOL_ALLOC)
2473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (flags & DE_MEMPOOL_ENABLE_FAILING_ALLOCS)
2483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		pool->allowFailing = DE_TRUE;
2493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif
2503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#if defined(DE_SUPPORT_DEBUG_POOLS)
2513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (flags & DE_MEMPOOL_ENABLE_DEBUG_ALLOCS)
2523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		pool->enableDebugAllocs		= DE_TRUE;
2543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		pool->debugAllocListHead	= DE_NULL;
2553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif
2573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_UNREF(flags); /* in case no debug features enabled */
2583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Get copy of utilities. */
2603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (util)
2613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deMemPoolUtil* utilCopy = DE_POOL_NEW(pool, deMemPoolUtil);
2633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(util->allocFailCallback);
2643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!utilCopy)
2653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
2663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			deMemPool_destroy(pool);
2673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return DE_NULL;
2683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
2693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		memcpy(utilCopy, util, sizeof(deMemPoolUtil));
2713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		pool->util = utilCopy;
2723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return pool;
2753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
2783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Create a sub-pool for an existing memory pool.
2793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \return The created memory pool (or null on failure).
2803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
2813c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeMemPool* deMemPool_create (deMemPool* parent)
2823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deMemPool* pool;
2843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(parent);
2853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	pool = createPoolInternal(parent);
2863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!pool && parent->util)
2873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		parent->util->allocFailCallback(parent->util->userPointer);
2883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return pool;
2893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
2923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Destroy a memory pool.
2933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \param pool	Pool to be destroyed.
2943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
2953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Frees all the memory allocated from the pool. Also destroyed any child
2963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * pools that the pool has (recursively).
2973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
2983c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid deMemPool_destroy (deMemPool* pool)
2993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deMemPool* iter;
3013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deMemPool* iterNext;
3023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#if defined(DE_SUPPORT_POOL_MEMORY_TRACKING)
3043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Update memory consumption statistics. */
3053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (pool->parent)
3063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deMemPool* root = pool->parent;
3083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		while (root->parent)
3093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			root = root->parent;
3103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		root->maxMemoryAllocated	= deMax32(root->maxMemoryAllocated, deMemPool_getNumAllocatedBytes(root, DE_TRUE));
3113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		root->maxMemoryCapacity		= deMax32(root->maxMemoryCapacity, deMemPool_getCapacity(root, DE_TRUE));
3123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif
3143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Destroy all children. */
3163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	iter = pool->firstChild;
3173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	while (iter)
3183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		iterNext = iter->nextPool;
3203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deMemPool_destroy(iter);
3213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		iter = iterNext;
3223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(pool->numChildren == 0);
3253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Update pointers. */
3273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (pool->prevPool) pool->prevPool->nextPool = pool->nextPool;
3283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (pool->nextPool) pool->nextPool->prevPool = pool->prevPool;
3293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (pool->parent)
3313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deMemPool* parent = pool->parent;
3333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (parent->firstChild == pool)
3343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			parent->firstChild = pool->nextPool;
3353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		parent->numChildren--;
3373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(parent->numChildren >= 0);
3383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#if defined(DE_SUPPORT_DEBUG_POOLS)
3413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Free all debug allocations. */
3423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (pool->enableDebugAllocs)
3433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DebugAlloc* alloc	= pool->debugAllocListHead;
3453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DebugAlloc* next;
3463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		while (alloc)
3483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
3493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			next = alloc->next;
3503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			deAlignedFree(alloc->memPtr);
3513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			deFree(alloc);
3523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			alloc = next;
3533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
3543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		pool->debugAllocListHead = DE_NULL;
3563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif
3583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Free pages. */
3603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* \note Pool itself is allocated from first page, so we must not touch the pool after freeing the page! */
3613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		MemPage* page = pool->currentPage;
3633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		MemPage* nextPage;
3643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		while (page)
3663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
3673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			nextPage = page->nextPage;
3683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			MemPage_destroy(page);
3693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			page = nextPage;
3703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
3713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
3753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Get the number of children for a pool.
3763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \return The number of (immediate) child pools a memory pool has.
3773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
3783c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint deMemPool_getNumChildren (const deMemPool* pool)
3793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return pool->numChildren;
3813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
3843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Get the number of bytes allocated (by the user) from the pool.
3853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \param pool		Pool pointer.
3863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \param recurse	Is operation recursive to child pools?
3873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \return The number of bytes allocated by the pool (including child pools
3883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *		   if 'recurse' is true).
3893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
3903c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint deMemPool_getNumAllocatedBytes (const deMemPool* pool, deBool recurse)
3913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int			numAllocatedBytes = 0;
3933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	MemPage*	memPage;
3943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (memPage = pool->currentPage; memPage; memPage = memPage->nextPage)
3963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		numAllocatedBytes += memPage->bytesAllocated;
3973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (recurse)
3993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deMemPool* child;
4013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (child = pool->firstChild; child; child = child->nextPool)
4023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			numAllocatedBytes += deMemPool_getNumAllocatedBytes(child, DE_TRUE);
4033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return numAllocatedBytes;
4063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4083c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint deMemPool_getCapacity (const deMemPool* pool, deBool recurse)
4093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int			numCapacityBytes = 0;
4113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	MemPage*	memPage;
4123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (memPage = pool->currentPage; memPage; memPage = memPage->nextPage)
4143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		numCapacityBytes += memPage->capacity;
4153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (recurse)
4173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deMemPool* child;
4193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (child = pool->firstChild; child; child = child->nextPool)
4203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			numCapacityBytes += deMemPool_getCapacity(child, DE_TRUE);
4213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return numCapacityBytes;
4243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4268eb43bbbb25645f6765f79608da7fea6f2e9d86cJarkko PöyryDE_INLINE void* deMemPool_allocInternal (deMemPool* pool, size_t numBytes, deUint32 alignBytes)
4273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	MemPage* curPage = pool->currentPage;
4293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#if defined(DE_SUPPORT_FAILING_POOL_ALLOC)
4313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (pool->allowFailing)
4323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if ((deRandom_getUint32(&pool->failRandom) & 16383) <= 15)
4343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return DE_NULL;
4353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif
4373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#if defined(DE_SUPPORT_DEBUG_POOLS)
4393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (pool->enableDebugAllocs)
4403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DebugAlloc*	header	= DE_NEW(DebugAlloc);
4423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		void*		ptr		= deAlignedMalloc(numBytes, alignBytes);
4433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!header || !ptr)
4453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
4463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			deFree(header);
4473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			deAlignedFree(ptr);
4483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return DE_NULL;
4493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
4503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		header->memPtr	= ptr;
4523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		header->next	= pool->debugAllocListHead;
4533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		pool->debugAllocListHead = header;
4543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return ptr;
4563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif
4583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(curPage);
46024ceed3e1acf66512ee25ee75002198b6672879dJarkko Pöyry	DE_ASSERT(deIsPowerOfTwo32((int)alignBytes));
4613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		void*	curPagePtr		= (void*)((deUint8*)(curPage + 1) + curPage->bytesAllocated);
4633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		void*	alignedPtr		= deAlignPtr(curPagePtr, alignBytes);
4648eb43bbbb25645f6765f79608da7fea6f2e9d86cJarkko Pöyry		size_t	alignPadding	= (size_t)((deUintptr)alignedPtr - (deUintptr)curPagePtr);
4653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4668eb43bbbb25645f6765f79608da7fea6f2e9d86cJarkko Pöyry		if (numBytes + alignPadding > (size_t)(curPage->capacity - curPage->bytesAllocated))
4673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
4683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			/* Does not fit to current page. */
4698eb43bbbb25645f6765f79608da7fea6f2e9d86cJarkko Pöyry			int		maxAlignPadding		= deMax32(0, ((int)alignBytes)-MEM_PAGE_BASE_ALIGN);
4708eb43bbbb25645f6765f79608da7fea6f2e9d86cJarkko Pöyry			int		newPageCapacity		= deMax32(deMin32(2*curPage->capacity, MAX_PAGE_SIZE), ((int)numBytes)+maxAlignPadding);
4713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4728eb43bbbb25645f6765f79608da7fea6f2e9d86cJarkko Pöyry			curPage = MemPage_create((size_t)newPageCapacity);
4733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (!curPage)
4743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return DE_NULL;
4753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			curPage->nextPage	= pool->currentPage;
4773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			pool->currentPage	= curPage;
4783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(curPage->bytesAllocated == 0);
4803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			curPagePtr			= (void*)(curPage + 1);
4823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			alignedPtr			= deAlignPtr(curPagePtr, alignBytes);
4838eb43bbbb25645f6765f79608da7fea6f2e9d86cJarkko Pöyry			alignPadding		= (size_t)((deUintptr)alignedPtr - (deUintptr)curPagePtr);
4843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4858eb43bbbb25645f6765f79608da7fea6f2e9d86cJarkko Pöyry			DE_ASSERT(numBytes + alignPadding <= (size_t)curPage->capacity);
4863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
4873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4888eb43bbbb25645f6765f79608da7fea6f2e9d86cJarkko Pöyry		curPage->bytesAllocated += (int)(numBytes + alignPadding);
4893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return alignedPtr;
4903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
4943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Allocate memory from a pool.
4953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \param pool		Memory pool to allocate from.
4963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \param numBytes	Number of bytes to allocate.
4973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \return Pointer to the allocate memory (or null on failure).
4983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
4998eb43bbbb25645f6765f79608da7fea6f2e9d86cJarkko Pöyryvoid* deMemPool_alloc (deMemPool* pool, size_t numBytes)
5003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void* ptr;
5023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(pool);
5033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(numBytes > 0);
5043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ptr = deMemPool_allocInternal(pool, numBytes, DE_POOL_DEFAULT_ALLOC_ALIGNMENT);
5053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!ptr && pool->util)
5063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		pool->util->allocFailCallback(pool->util->userPointer);
5073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return ptr;
5083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
5113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Allocate aligned memory from a pool.
5123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \param pool			Memory pool to allocate from.
5133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \param numBytes		Number of bytes to allocate.
5143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \param alignBytes	Required alignment in bytes, must be power of two.
5153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \return Pointer to the allocate memory (or null on failure).
5163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
5178eb43bbbb25645f6765f79608da7fea6f2e9d86cJarkko Pöyryvoid* deMemPool_alignedAlloc (deMemPool* pool, size_t numBytes, deUint32 alignBytes)
5183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void* ptr;
5203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(pool);
5213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(numBytes > 0);
5223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(deIsPowerOfTwo32((int)alignBytes));
5233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ptr = deMemPool_allocInternal(pool, numBytes, alignBytes);
5243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(deIsAlignedPtr(ptr, alignBytes));
5253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!ptr && pool->util)
5263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		pool->util->allocFailCallback(pool->util->userPointer);
5273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return ptr;
5283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
5313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Duplicate a piece of memory into a memory pool.
5323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \param pool	Memory pool to allocate from.
5333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \param ptr	Piece of memory to duplicate.
5343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \return Pointer to the copied memory block (or null on failure).
5353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
5368eb43bbbb25645f6765f79608da7fea6f2e9d86cJarkko Pöyryvoid* deMemPool_memDup (deMemPool* pool, const void* ptr, size_t numBytes)
5373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void* newPtr = deMemPool_alloc(pool, numBytes);
5393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (newPtr)
5403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		memcpy(newPtr, ptr, numBytes);
5413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return newPtr;
5423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
5453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Duplicate a string into a memory pool.
5463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \param pool	Memory pool to allocate from.
5473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \param str	String to duplicate.
5483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \return Pointer to the new string (or null on failure).
5493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
5503c827367444ee418f129b2c238299f49d3264554Jarkko Poyrychar* deMemPool_strDup (deMemPool* pool, const char* str)
5513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5528eb43bbbb25645f6765f79608da7fea6f2e9d86cJarkko Pöyry	size_t	len		= strlen(str);
5533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	char*	newStr	= (char*)deMemPool_alloc(pool, len+1);
5543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (newStr)
5553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		memcpy(newStr, str, len+1);
5563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return newStr;
5573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*--------------------------------------------------------------------*//*!
5603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Duplicate a string into a memory pool, with a maximum length.
5613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \param pool		Memory pool to allocate from.
5623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \param str		String to duplicate.
5633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \param maxLength	Maximum number of characters to duplicate.
5643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \return Pointer to the new string (or null on failure).
5653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
5663c827367444ee418f129b2c238299f49d3264554Jarkko Poyrychar* deMemPool_strnDup (deMemPool* pool, const char* str, int maxLength)
5673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5688eb43bbbb25645f6765f79608da7fea6f2e9d86cJarkko Pöyry	size_t	len			= (size_t)deMin32((int)strlen(str), deMax32(0, maxLength));
5693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	char*	newStr		= (char*)deMemPool_alloc(pool, len + 1);
5708eb43bbbb25645f6765f79608da7fea6f2e9d86cJarkko Pöyry
5718eb43bbbb25645f6765f79608da7fea6f2e9d86cJarkko Pöyry	DE_ASSERT(maxLength >= 0);
5728eb43bbbb25645f6765f79608da7fea6f2e9d86cJarkko Pöyry
5733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (newStr)
5743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		memcpy(newStr, str, len);
5763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		newStr[len] = 0;
5773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return newStr;
5793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#if defined(DE_SUPPORT_POOL_MEMORY_TRACKING)
5823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5833c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint deMemPool_getMaxNumAllocatedBytes (const deMemPool* pool)
5843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(pool && !pool->parent); /* must be root */
5863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return deMax32(pool->maxMemoryAllocated, deMemPool_getNumAllocatedBytes(pool, DE_TRUE));
5873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5893c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint deMemPool_getMaxCapacity (const deMemPool* pool)
5903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(pool && !pool->parent); /* must be root */
5923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return deMax32(pool->maxMemoryCapacity, deMemPool_getCapacity(pool, DE_TRUE));
5933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif
596