aboutsummaryrefslogtreecommitdiffstats
path: root/addons/ooh323c/src/memheap.c
diff options
context:
space:
mode:
authorrussell <russell@f38db490-d61c-443f-a65b-d21fe96a405b>2009-06-30 16:40:38 +0000
committerrussell <russell@f38db490-d61c-443f-a65b-d21fe96a405b>2009-06-30 16:40:38 +0000
commite9d15cbea7a98184521c851500176da7aa424012 (patch)
treed3d6aa7ea86d11ecaa6e88efbc46a5dde1c63ea5 /addons/ooh323c/src/memheap.c
parentb85bdd32a783a8f07004d41db8a696645685a331 (diff)
Move Asterisk-addons modules into the main Asterisk source tree.
Someone asked yesterday, "is there a good reason why we can't just put these modules in Asterisk?". After a brief discussion, as long as the modules are clearly set aside in their own directory and not enabled by default, it is perfectly fine. For more information about why a module goes in addons, see README-addons.txt. chan_ooh323 does not currently compile as it is behind some trunk API updates. However, it will not build by default, so it should be okay for now. git-svn-id: http://svn.digium.com/svn/asterisk/trunk@204413 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'addons/ooh323c/src/memheap.c')
-rw-r--r--addons/ooh323c/src/memheap.c1331
1 files changed, 1331 insertions, 0 deletions
diff --git a/addons/ooh323c/src/memheap.c b/addons/ooh323c/src/memheap.c
new file mode 100644
index 000000000..48040a7ef
--- /dev/null
+++ b/addons/ooh323c/src/memheap.c
@@ -0,0 +1,1331 @@
+/*
+ * Copyright (C) 1997-2004 by Objective Systems, Inc.
+ *
+ * This software is furnished under an open source license and may be
+ * used and copied only in accordance with the terms of this license.
+ * The text of the license may generally be found in the root
+ * directory of this installation in the LICENSE.txt file. It
+ * can also be viewed online at the following URL:
+ *
+ * http://www.obj-sys.com/open/license.html
+ *
+ * Any redistributions of this file including modified versions must
+ * maintain this copyright notice.
+ *
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include "memheap.h"
+
+ASN1UINT g_defBlkSize = XM_K_MEMBLKSIZ;
+OSMallocFunc g_malloc_func = malloc;
+#ifndef _NO_REALLOC
+OSReallocFunc g_realloc_func = realloc;
+#else
+OSReallocFunc g_realloc_func = 0;
+#endif
+OSFreeFunc g_free_func = free;
+
+static OSMemLink* memHeapAddBlock (OSMemLink** ppMemLink,
+ void* pMemBlk, int blockType);
+
+typedef void OSMemElemDescr;
+
+
+#define pElem_flags(pElem) (*((ASN1OCTET*)pElem))
+#define pElem_nunits(pElem) (*((ASN1USINT*)(((ASN1OCTET*)pElem)+2)))
+#define pElem_prevOff(pElem) (*((ASN1USINT*)(((ASN1OCTET*)pElem)+4)))
+#define pElem_nextFreeOff(pElem) (*((ASN1USINT*)(((ASN1OCTET*)pElem)+6)))
+#define pElem_beginOff(pElem) (*((ASN1USINT*)(((ASN1OCTET*)pElem)+6)))
+#define sizeof_OSMemElemDescr 8
+#define pElem_data(pElem) (((ASN1OCTET*)pElem)+sizeof_OSMemElemDescr)
+
+typedef struct MemBlk {
+ OSMemLink* plink;
+ ASN1USINT free_x; /* index of free space at end of block */
+ ASN1USINT freeMem; /* size of free space before free_x */
+ ASN1USINT nunits; /* size of data */
+ ASN1USINT lastElemOff; /* last element offset in block */
+ ASN1USINT freeElemOff; /* first free element offset in block */
+ ASN1USINT nsaved; /* num of saved elems in the block */
+
+ ASN1USINT spare[2]; /* forces alignment on 8-bytes boundary,
+ for 64-bit systems */
+ char data[8];
+} OSMemBlk;
+
+/* Macros for operations with memory blocks */
+
+#define QOFFSETOF(pElem, pPrevElem) \
+((ASN1USINT)(((unsigned)((char*)pElem - (char*)pPrevElem)) >> 3u))
+
+#define OFFSETOF(pElem, pPrevElem) \
+((ASN1UINT)((char*)pElem - (char*)pPrevElem))
+
+#define ISFREE(pElem) (pElem_flags(pElem) & 1)
+#define SET_FREE(pElem) (pElem_flags(pElem) |= 1)
+#define CLEAR_FREE(pElem) (pElem_flags(pElem) &= (~1))
+
+#define ISLAST(pElem) (pElem_flags(pElem) & 2)
+#define SET_LAST(pElem) (pElem_flags(pElem) |= 2)
+#define CLEAR_LAST(pElem) (pElem_flags(pElem) &= (~2))
+
+#define ISSAVED(pElem) (pElem_flags(pElem) & 4)
+#define SET_SAVED(pMemBlk,pElem) do { \
+(pElem_flags (pElem) |= 4); pMemBlk->nsaved++; } while (0)
+#define CLEAR_SAVED(pMemBlk,pElem) do { \
+(pElem_flags (pElem) &= (~4)); pMemBlk->nsaved--; } while (0)
+
+#define ISFIRST(pElem) (int)(pElem_prevOff (pElem) == 0)
+
+#define GETPREV(pElem) \
+((pElem_prevOff (pElem) == 0) ? 0 : \
+((OSMemElemDescr*) (((char*)pElem) - (pElem_prevOff (pElem) * 8u))))
+
+#define GETNEXT(pElem) \
+((ISLAST (pElem)) ? 0 : \
+((OSMemElemDescr*)(((char*)pElem) + ((pElem_nunits (pElem) + 1) * 8u))))
+
+#define GET_NEXT_FREE(pElem) \
+((pElem_nextFreeOff (pElem) == 0) ? 0 : \
+((OSMemElemDescr*) (((char*)pElem) + (pElem_nextFreeOff (pElem) * 8u))))
+
+#define GET_MEMBLK(pElem) \
+((OSMemBlk*) (((char*)pElem) - (pElem_beginOff (pElem) * 8u) - \
+sizeof (OSMemBlk) + sizeof ((OSMemBlk*)0)->data))
+
+#define GET_LAST_ELEM(pMemBlk) \
+((pMemBlk->lastElemOff == 0) ? 0 : \
+(OSMemElemDescr*)&pMemBlk->data[(pMemBlk->lastElemOff - 1) * 8u])
+
+#define SET_LAST_ELEM(pMemBlk, pElem) \
+pMemBlk->lastElemOff = (ASN1USINT)((pElem == 0) ? 0 : \
+(SET_LAST (pElem), (QOFFSETOF (pElem, pMemBlk->data) + 1)))
+
+#define GET_FREE_ELEM(pMemBlk) \
+((pMemBlk->freeElemOff == 0) ? 0 : \
+(OSMemElemDescr*)&pMemBlk->data[(pMemBlk->freeElemOff - 1) * 8u])
+
+#define FORCE_SET_FREE_ELEM(pMemBlk, pElem) do { \
+if (pElem == 0) { pMemBlk->freeElemOff = 0; break; } \
+SET_FREE (pElem); \
+pMemBlk->freeElemOff = (ASN1USINT)(QOFFSETOF (pElem, pMemBlk->data) + 1); \
+} while (0)
+
+#define SET_FREE_ELEM(pMemBlk, pElem) setLastElem (pMemBlk, pElem)
+
+/* Memory debugging macros */
+#define RTMEMDIAG1(msg)
+#define RTMEMDIAG2(msg,a)
+#define RTMEMDIAG3(msg,a,b)
+#define RTMEMDIAG4(msg,a,b,c)
+#define FILLFREEMEM(mem,size)
+#define FILLNEWMEM(mem,size)
+
+#define CHECKMEMELEM(memblk,elem)
+#define CHECKMEMBLOCK(memheap,memblk)
+#define CHECKMEMHEAP(memheap)
+#define TRACEMEMELEM(memblk, elem, name)
+#define TRACEFREE(memlink,name)
+
+
+static void setLastElem (OSMemBlk* pMemBlk, OSMemElemDescr* pElem)
+{
+ if (pElem == 0) {
+ pMemBlk->freeElemOff = 0;
+ return;
+ }
+ else if (ISLAST (pElem))
+ return;
+ else if (pMemBlk->freeElemOff > QOFFSETOF (pElem, pMemBlk->data) + 1) {
+ pElem_nextFreeOff (pElem) = QOFFSETOF (GET_FREE_ELEM (pMemBlk), pElem);
+ FORCE_SET_FREE_ELEM (pMemBlk, pElem);
+ }
+ else if (pMemBlk->freeElemOff == 0) {
+ pElem_nextFreeOff (pElem) = 0;
+ FORCE_SET_FREE_ELEM (pMemBlk, pElem);
+ }
+ else {
+ SET_FREE (pElem);
+ pElem_nextFreeOff (pElem) = 0;
+ }
+}
+
+void* memHeapAlloc (void** ppvMemHeap, int nbytes)
+{
+ OSMemHeap* pMemHeap;
+ OSMemLink* pMemLink, **ppMemLink;
+ OSMemBlk* pMemBlk = 0;
+ void* mem_p = NULL;
+ unsigned remUnits;
+ ASN1UINT nunits;
+
+ if (ppvMemHeap == 0)
+ return 0;
+
+ if (*ppvMemHeap == 0)
+ if (memHeapCreate (ppvMemHeap) != ASN_OK)
+ return 0;
+
+ /* Round number of bytes to nearest 8-byte boundary */
+
+ nunits = (((unsigned)(nbytes + 7)) >> 3);
+
+ pMemHeap = (OSMemHeap*) *ppvMemHeap;
+ ppMemLink = &pMemHeap->phead;
+
+ /* if size is greater than 2**19, then allocate as RAW block */
+
+ if (nunits > (1<<16) - 2) {
+ void *data;
+
+ /* allocate raw block */
+
+ data = g_malloc_func (nbytes);
+ if (data == NULL) {
+ return NULL;
+ }
+ pMemLink = memHeapAddBlock (ppMemLink, data, RTMEMMALLOC | RTMEMRAW);
+ if (pMemLink == 0) {
+ g_free_func (data);
+ return NULL;
+ }
+ /* save size of the RAW memory block behind the pMemLink */
+ *(int*)(((char*)pMemLink) + sizeof (OSMemLink)) = nbytes;
+ return data;
+ }
+
+ RTMEMDIAG2 ("memHeapAlloc: adjusted nbytes = %d\n", nbytes);
+
+ /* Try to allocate a slot from an existing block on the list */
+
+ for (pMemLink = *ppMemLink; pMemLink != 0; pMemLink = pMemLink->pnext) {
+ if (pMemLink->blockType & RTMEMRAW) continue;
+ else pMemBlk = (OSMemBlk*) pMemLink->pMemBlk;
+
+ remUnits = pMemBlk->nunits - pMemBlk->free_x;
+
+ if ((unsigned)(nunits + 1) <= remUnits) {
+ OSMemElemDescr* pElem = (OSMemElemDescr*)
+ &pMemBlk->data [((ASN1UINT)pMemBlk->free_x) * 8u];
+ OSMemElemDescr* pPrevElem;
+
+ RTMEMDIAG1 ("memHeapAlloc: found existing slot..\n");
+
+ /* if block is clean, set some vars in heap */
+ if (pMemBlk->free_x == 0) {
+ pMemHeap->freeUnits -= pMemBlk->nunits;
+ pMemHeap->freeBlocks--;
+ }
+
+ pElem_flags (pElem) = 0;
+ if (pMemBlk->lastElemOff != 0)
+ pElem_prevOff (pElem) =
+ (ASN1USINT)(pMemBlk->free_x - pMemBlk->lastElemOff + 1);
+ else
+ pElem_prevOff (pElem) = 0;
+
+ pPrevElem = GET_LAST_ELEM (pMemBlk);
+ if (pPrevElem != 0)
+ CLEAR_LAST (pPrevElem);
+
+ pElem_nunits (pElem) = (ASN1USINT)nunits;
+ pElem_beginOff (pElem) = QOFFSETOF (pElem, pMemBlk->data);
+ pMemBlk->lastElemOff = (ASN1USINT)(pMemBlk->free_x + 1);
+
+ mem_p = (void*) (pElem_data (pElem));
+
+ /* sizeof (OSMemElemDescr) == 1 unit */
+ pMemBlk->free_x += nunits + 1;
+
+ SET_LAST_ELEM (pMemBlk, pElem);
+
+ FILLNEWMEM (mem_p, nunits * 8u);
+ TRACEMEMELEM(pMemBlk, pElem, "Allocated");
+ CHECKMEMELEM (pMemBlk, pElem);
+ CHECKMEMBLOCK (pMemHeap, pMemBlk);
+ break;
+ }
+ }
+
+ /* If not successful, look for empty elements in existing blocks */
+
+ if (0 == mem_p) {
+ for (pMemLink = *ppMemLink; pMemLink != 0; pMemLink = pMemLink->pnext) {
+ if (pMemLink->blockType & RTMEMRAW) continue;
+
+ pMemBlk = (OSMemBlk*) pMemLink->pMemBlk;
+
+ if (nunits <= (ASN1UINT)pMemBlk->freeMem) {
+ OSMemElemDescr* pElem = GET_FREE_ELEM(pMemBlk), *pPrevFree = 0;
+
+ RTMEMDIAG2
+ ("memHeapAlloc: try to reuse empty elems in pMemBlk = 0x%x...\n",
+ pMemBlk);
+
+ while (pElem != 0) {
+ if (ISFREE (pElem)) {
+ if (nunits <= (ASN1UINT)pElem_nunits (pElem)) {
+ RTMEMDIAG3
+ ("memHeapAlloc: "
+ "found an exisiting free element 0x%x, size %d\n",
+ pElem, (pElem_nunits (pElem) * 8u));
+
+ if (pMemBlk->freeElemOff ==
+ QOFFSETOF (pElem, pMemBlk->data) + 1)
+ {
+
+ /* modify the pMemBlk->freeElemOff value if necsry */
+
+ OSMemElemDescr* nextFree = GET_NEXT_FREE (pElem);
+ FORCE_SET_FREE_ELEM (pMemBlk, nextFree);
+ }
+ else if (pPrevFree != 0) {
+ OSMemElemDescr* pNextFree = GET_NEXT_FREE (pElem);
+ if (pNextFree != 0)
+ pElem_nextFreeOff (pPrevFree) = QOFFSETOF (pNextFree,
+ pPrevFree);
+ else
+ pElem_nextFreeOff (pPrevFree) = 0;
+ }
+
+ CLEAR_FREE (pElem);
+
+ /* set beginOff value */
+
+ pElem_beginOff (pElem) = QOFFSETOF (pElem, pMemBlk->data);
+
+ pMemBlk->freeMem -= pElem_nunits (pElem);
+
+ CHECKMEMELEM (pMemBlk, pElem);
+ CHECKMEMBLOCK (pMemHeap, pMemBlk);
+
+ mem_p = memHeapRealloc
+ (ppvMemHeap, pElem_data (pElem), nunits * 8u);
+ if (mem_p != 0) {
+ FILLNEWMEM (mem_p, nunits * 8u);
+ TRACEMEMELEM(pMemBlk, pElem, "Allocated");
+ }
+ break;
+ }
+ }
+ pPrevFree = pElem;
+ pElem = GET_NEXT_FREE (pElem);
+ }
+ if (mem_p != 0) break;
+ }
+ }
+ }
+
+ /* If not successful, malloc a new block and alloc from it */
+
+ if (!mem_p) {
+ ASN1UINT allocSize, dataUnits;
+ ASN1OCTET* pmem;
+ register ASN1UINT defBlkSize = pMemHeap->defBlkSize;
+
+ RTMEMDIAG1 ("memHeapAlloc: alloc block..\n");
+
+ allocSize = (ASN1UINT) ((((ASN1UINT)nunits) * 8u) +
+ sizeof (OSMemBlk) + sizeof_OSMemElemDescr);
+ allocSize = (ASN1UINT) (allocSize < defBlkSize) ? defBlkSize :
+ ((allocSize + defBlkSize - 1) / defBlkSize * defBlkSize);
+ dataUnits = (ASN1UINT)((allocSize - sizeof (OSMemBlk)) >> 3u);
+ if (dataUnits >= (1u<<16)) {
+ dataUnits = (ASN1UINT)((1u<<16) - 1);
+ allocSize = (ASN1UINT)
+ ((((ASN1UINT)dataUnits) * 8u) + sizeof (OSMemBlk));
+ }
+
+ pmem = (ASN1OCTET*) g_malloc_func (allocSize + sizeof (OSMemLink));
+ if (0 != pmem) {
+ OSMemElemDescr* pElem;
+
+ pMemBlk = (OSMemBlk*) (pmem + sizeof (OSMemLink));
+ pElem = (OSMemElemDescr*)&pMemBlk->data[0];
+
+ mem_p = (void*) pElem_data (pElem);
+ pElem_nunits (pElem) = (ASN1USINT)nunits;
+ pElem_flags (pElem) = 0;
+ pElem_prevOff (pElem) = 0;
+ pElem_beginOff (pElem) = QOFFSETOF (pElem, pMemBlk->data);
+
+ /* sizeof (OSMemElemDescr) == 1 unit */
+ pMemBlk->free_x = (ASN1USINT)(nunits + 1);
+
+ pMemBlk->freeMem = 0;
+ pMemBlk->nunits = (ASN1USINT)dataUnits;
+ SET_LAST_ELEM (pMemBlk, pElem);
+ pMemBlk->freeElemOff = 0;
+ pMemBlk->nsaved = 0;
+
+ if (memHeapAddBlock (ppMemLink, pMemBlk, RTMEMSTD | RTMEMLINK) == 0)
+ {
+ g_free_func (pmem);
+ return NULL;
+ }
+
+ /* set vars in heap */
+ pMemHeap->usedUnits += dataUnits;
+ pMemHeap->usedBlocks++;
+
+ FILLNEWMEM (mem_p, nunits * 8u);
+ TRACEMEMELEM(pMemBlk, pElem, "Allocated");
+ CHECKMEMELEM (pMemBlk, pElem);
+ CHECKMEMBLOCK (pMemHeap, pMemBlk);
+ }
+ else
+ return NULL;
+ }
+ RTMEMDIAG2 ("memHeapAlloc: pMemBlk = 0x%x\n", pMemBlk);
+ RTMEMDIAG2 ("memHeapAlloc: pMemBlk->free_x = %d\n", pMemBlk->free_x);
+ RTMEMDIAG2 ("memHeapAlloc: pMemBlk->size = %d\n",
+ pMemBlk->nunits * 8u);
+ RTMEMDIAG2 ("memHeapAlloc: mem_p = 0x%x\n", mem_p);
+ RTMEMDIAG2 ("memHeapAlloc: sizeof (short) = %d\n", sizeof(short));
+
+ return (mem_p);
+}
+
+void* memHeapAllocZ (void** ppvMemHeap, int nbytes)
+{
+ void* ptr = memHeapAlloc (ppvMemHeap, nbytes);
+ if (0 != ptr) memset (ptr, 0, nbytes);
+ return ptr;
+}
+
+void memHeapFreePtr (void** ppvMemHeap, void* mem_p)
+{
+ OSMemHeap* pMemHeap;
+ OSMemLink** ppMemLink;
+ OSMemElemDescr* pElem;
+ OSMemBlk* pMemBlk;
+ OSMemLink* pMemLink, *pPrevMemLink = 0;
+
+ RTMEMDIAG2 ("memHeapFreePtr: freeing mem_p = 0x%x\n", mem_p);
+
+ if (mem_p == 0 || ppvMemHeap == 0 || *ppvMemHeap == 0) return;
+
+ pMemHeap = *(OSMemHeap**)ppvMemHeap;
+ ppMemLink = &pMemHeap->phead;
+
+ /* look for chain of RAW blocks first */
+
+ for (pMemLink = *ppMemLink; pMemLink != 0; pMemLink = pMemLink->pnextRaw) {
+ if ((pMemLink->blockType & RTMEMRAW) &&
+ pMemLink->pMemBlk == mem_p)
+ {
+ if(pMemLink->pnext != 0) {
+ pMemLink->pnext->pprev = pMemLink->pprev;
+ }
+ if(pMemLink->pprev != 0) {
+ pMemLink->pprev->pnext = pMemLink->pnext;
+ }
+ else { /* head */
+ *ppMemLink = pMemLink->pnext;
+ }
+ if (pPrevMemLink != 0)
+ pPrevMemLink->pnextRaw = pMemLink->pnextRaw;
+ else if (*ppMemLink != 0 && (*ppMemLink)->pnextRaw == 0 &&
+ *ppMemLink != pMemLink->pnextRaw)
+ {
+ (*ppMemLink)->pnextRaw = pMemLink->pnextRaw;
+ }
+ if ((pMemLink->blockType & RTMEMLINK) &&
+ (pMemLink->blockType & RTMEMMALLOC))
+ {
+ g_free_func (pMemLink);
+ }
+ else {
+ if (pMemLink->blockType & RTMEMMALLOC)
+ g_free_func (pMemLink->pMemBlk);
+ g_free_func (pMemLink);
+ }
+ return;
+ }
+ pPrevMemLink = pMemLink;
+ }
+
+ pElem = (OSMemElemDescr*) (((char*)mem_p) - sizeof_OSMemElemDescr);
+ pMemBlk = GET_MEMBLK (pElem);
+
+ CHECKMEMELEM (pMemBlk, pElem);
+ CHECKMEMBLOCK(pMemHeap, pMemBlk);
+
+ if (ISFREE (pElem)) { /* already freed! */
+ RTMEMDIAG2 ("memHeapFreePtr: "
+ "the element 0x%x is already freed!\n", pElem);
+ return;
+ }
+
+ if (ISSAVED (pElem)) {
+ CLEAR_SAVED (pMemBlk, pElem);
+ if (pMemBlk->nsaved == 0)
+ pMemBlk->plink->blockType &= (~RTMEMSAVED);
+ }
+
+ TRACEMEMELEM(pMemBlk, pElem, "Freed");
+ CHECKMEMELEM (pMemBlk, pElem);
+ CHECKMEMBLOCK(pMemHeap, pMemBlk);
+
+ RTMEMDIAG2 ("memHeapFreePtr: pMemBlk = 0x%x\n", pMemBlk);
+ RTMEMDIAG2 ("memHeapFreePtr: pMemBlk->size = %d\n",
+ pMemBlk->nunits * 8u);
+
+ if (ISLAST (pElem)) { /* is it the last? */
+ OSMemElemDescr* pPrevElem = GETPREV (pElem);
+
+ CHECKMEMELEM (pMemBlk, pPrevElem);
+
+ pMemBlk->free_x -= (pElem_nunits (pElem) + 1);
+
+ FILLFREEMEM (&pMemBlk->data [pMemBlk->free_x * 8u],
+ (pElem_nunits (pElem) + 1) * 8u);
+
+ if (pPrevElem != 0 && ISFREE (pPrevElem)) {
+ OSMemElemDescr* pFreeElem;
+
+ pMemBlk->free_x -= (pElem_nunits (pPrevElem) + 1);
+ pMemBlk->freeMem -= pElem_nunits (pPrevElem);
+ SET_LAST_ELEM (pMemBlk, GETPREV (pPrevElem));
+
+ /* wasn't it the last elem in block? */
+ if (pMemBlk->lastElemOff != 0) {
+
+ /* correct nextFreeOff for previous free element */
+
+ pFreeElem = GET_FREE_ELEM (pMemBlk);
+ if (pFreeElem == pPrevElem) {
+ pMemBlk->freeElemOff = 0; /* it was the last free elem */
+ }
+ else {
+ OSMemElemDescr* pNextFree = 0;
+
+ while (pFreeElem < pPrevElem) {
+ pNextFree = pFreeElem;
+ pFreeElem = GET_NEXT_FREE (pFreeElem);
+ }
+ pElem_nextFreeOff (pNextFree) = 0;
+ }
+ }
+ }
+ else {
+ SET_LAST_ELEM (pMemBlk, pPrevElem);
+ }
+
+ RTMEMDIAG2 ("memHeapFreePtr: pMemBlk->free_x = %d\n",
+ pMemBlk->free_x);
+
+ /* The question is: do we really want to get rid of the */
+ /* block or should we keep it around for reuse? */
+ if (pMemBlk->lastElemOff == 0) { /* was it the last elem in block? */
+
+ if ((pMemHeap->flags & RT_MH_DONTKEEPFREE) ||
+ (pMemHeap->keepFreeUnits > 0 &&
+ pMemHeap->freeUnits + pMemBlk->nunits > pMemHeap->keepFreeUnits))
+ {
+ ASN1OCTET blockType = pMemBlk->plink->blockType;
+
+ /* we may free the block */
+
+ pMemHeap->usedUnits -= pMemBlk->nunits;
+ pMemHeap->usedBlocks --;
+
+ if(pMemBlk->plink->pnext != 0) {
+ pMemBlk->plink->pnext->pprev = pMemBlk->plink->pprev;
+ }
+ if(pMemBlk->plink->pprev != 0) {
+ pMemBlk->plink->pprev->pnext = pMemBlk->plink->pnext;
+ }
+ else { /* head */
+ if (pMemBlk->plink->pnext != 0 &&
+ !(pMemBlk->plink->pnext->blockType & RTMEMRAW))
+ {
+ pMemBlk->plink->pnext->pnextRaw = (*ppMemLink)->pnextRaw;
+ }
+ *ppMemLink = pMemBlk->plink->pnext;
+ }
+ FILLFREEMEM (pMemBlk->plink, sizeof (*pMemBlk->plink));
+ FILLFREEMEM (pMemBlk->data, (pMemBlk->nunits * 8u));
+
+ g_free_func (pMemBlk->plink);
+
+ if (!(blockType & RTMEMLINK)) {
+ FILLFREEMEM (pMemBlk, sizeof (*pMemBlk));
+ g_free_func (pMemBlk);
+ }
+ RTMEMDIAG2 ("memHeapFreePtr: pMemBlk = 0x%x was freed\n",
+ pMemBlk);
+ }
+ else {
+ /* reset pMemBlk for re-usage */
+ pMemBlk->free_x = 0;
+ pMemBlk->freeElemOff = 0;
+ pMemBlk->lastElemOff = 0;
+ pMemBlk->freeMem = 0;
+ pMemBlk->nsaved = 0;
+ pMemHeap->freeUnits += pMemBlk->nunits;
+ pMemHeap->freeBlocks ++;
+ }
+ }
+ else {
+ SET_LAST (GET_LAST_ELEM (pMemBlk));
+ FILLFREEMEM (((char*) &pMemBlk->data[0]) + (pMemBlk->free_x * 8u),
+ (pMemBlk->nunits - pMemBlk->free_x) * 8u);
+ CHECKMEMBLOCK (pMemHeap, pMemBlk);
+ }
+ }
+ else { /* mark as free elem inside the block */
+ CHECKMEMBLOCK (pMemHeap, pMemBlk);
+
+ SET_FREE_ELEM(pMemBlk, pElem);
+
+ pMemBlk->freeMem += pElem_nunits (pElem);
+ RTMEMDIAG2 ("memHeapFreePtr: element 0x%x marked as free.\n",
+ pElem);
+
+ /* try to unite free blocks, if possible */
+ if (!ISFIRST (pElem)) {
+ if (ISFREE (GETPREV (pElem))) {
+ OSMemElemDescr* prevelem_p = GETPREV (pElem);
+
+ /* +1 because the OSMemElemDescr has size ONE unit (8 bytes) */
+ pElem_nunits (prevelem_p) += pElem_nunits (pElem) + 1;
+
+ pElem = prevelem_p;
+ pMemBlk->freeMem ++; /* sizeof (OSMemElemDescr) == 1 unit */
+ }
+ else {
+ /* look for nearest previous free block to correct nextFreeOff */
+
+ OSMemElemDescr* prevelem_p = pElem;
+
+ do {
+ prevelem_p = GETPREV (prevelem_p);
+ }
+ while (prevelem_p && !ISFREE (prevelem_p));
+
+ if (prevelem_p != 0) {
+ OSMemElemDescr* pNextFree = GET_NEXT_FREE (prevelem_p);
+ if (pNextFree != 0)
+ pElem_nextFreeOff (pElem) = QOFFSETOF (pNextFree, pElem);
+ else
+ pElem_nextFreeOff (pElem) = 0;
+ pElem_nextFreeOff (prevelem_p) = QOFFSETOF (pElem, prevelem_p);
+
+ CHECKMEMELEM (pMemBlk, prevelem_p);
+ }
+ }
+ }
+ if (!ISLAST (pElem) && ISFREE (GETNEXT (pElem))) {
+ OSMemElemDescr* nextelem_p = GETNEXT (pElem);
+
+ /* +1 because the OSMemElemDescr has size ONE unit (8 bytes) */
+ pElem_nunits (pElem) += pElem_nunits (nextelem_p) + 1;
+
+ if (pElem_nextFreeOff (nextelem_p) == 0)
+ pElem_nextFreeOff (pElem) = 0;
+ else
+ pElem_nextFreeOff (pElem) =
+ QOFFSETOF (GET_NEXT_FREE (nextelem_p), pElem);
+ pMemBlk->freeMem ++;
+ }
+
+ /* correct the prevOff field of next element */
+ if (!ISLAST (pElem)) {
+ OSMemElemDescr* nextelem_p = GETNEXT (pElem);
+ pElem_prevOff (nextelem_p) = QOFFSETOF (nextelem_p, pElem);
+ }
+
+ CHECKMEMELEM (pMemBlk, pElem);
+ FILLFREEMEM (pElem_data (pElem), (pElem_nunits (pElem) * 8u));
+ CHECKMEMELEM (pMemBlk, pElem);
+ CHECKMEMBLOCK (pMemHeap, pMemBlk);
+ }
+}
+
+static void initNewFreeElement (OSMemBlk* pMemBlk,
+ OSMemElemDescr* pNewElem, OSMemElemDescr* pElem)
+{
+ OSMemElemDescr *pNextElem, *pPrevElem = 0;
+
+ /* create new free element on the freed place */
+
+ pElem_flags (pNewElem) = 0;
+ SET_FREE (pNewElem);
+
+ pElem_prevOff (pNewElem) = QOFFSETOF (pNewElem, pElem);
+
+ if (pMemBlk->freeElemOff != 0 &&
+ pMemBlk->freeElemOff < QOFFSETOF (pElem, pMemBlk->data) + 1)
+ {
+ /* look for nearest previous free block to correct its nextFreeOff */
+
+ pPrevElem = pElem;
+
+ do {
+ pPrevElem = GETPREV (pPrevElem);
+ }
+ while (pPrevElem && !ISFREE (pPrevElem));
+ }
+ if (pPrevElem != 0) { /* if it is not first free element... */
+
+ /* correct nextFreeOff for prev free element */
+
+ pElem_nextFreeOff (pPrevElem) = QOFFSETOF (pNewElem, pPrevElem);
+ }
+ else { /* if it is first free element in the block */
+ FORCE_SET_FREE_ELEM (pMemBlk, pNewElem);
+ }
+
+ pNextElem = GETNEXT (pNewElem);
+ if (ISFREE (pNextElem)) {
+
+ /* if the next elem is free, then unite them together */
+
+ pElem_nunits (pNewElem) += pElem_nunits (pNextElem) + 1;
+ if (pElem_nextFreeOff (pNextElem) != 0)
+ pElem_nextFreeOff (pNewElem) = QOFFSETOF (GET_NEXT_FREE (pNextElem),
+ pNewElem);
+ else
+ pElem_nextFreeOff (pNewElem) = 0;
+ pMemBlk->freeMem++; /* +1 because space for MemElemDescr is freed now */
+ pNextElem = GETNEXT (pNewElem);
+ }
+ pElem_prevOff (pNextElem) = QOFFSETOF (pNextElem, pNewElem);
+
+ if (pMemBlk->freeElemOff != 0) {
+
+ /* look for the next nearest free elem */
+
+ pNextElem = GETNEXT (pNewElem);
+ while (pNextElem != 0 && !ISFREE (pNextElem))
+ pNextElem = GETNEXT (pNextElem);
+
+ /* set nextFreeOff for new element */
+
+ if (pNextElem != 0)
+ pElem_nextFreeOff (pNewElem) = QOFFSETOF (pNextElem, pNewElem);
+ else
+ pElem_nextFreeOff (pNewElem) = 0;
+ }
+ else
+ pElem_nextFreeOff (pNewElem) = 0;
+
+}
+
+void* memHeapRealloc (void** ppvMemHeap, void* mem_p, int nbytes_)
+{
+ OSMemHeap* pMemHeap;
+ OSMemLink** ppMemLink;
+ OSMemBlk* pMemBlk;
+ OSMemElemDescr* pElem;
+ OSMemLink* pMemLink, *pPrevMemLink = 0;
+ void *newMem_p;
+ unsigned nbytes, nunits;
+
+ /* if mem_p == NULL - do rtMemAlloc */
+
+ if (ppvMemHeap == 0 || *ppvMemHeap == 0) return 0;
+
+ if (mem_p == 0) {
+ return memHeapAlloc (ppvMemHeap, nbytes_);
+ }
+
+ pMemHeap = *(OSMemHeap**)ppvMemHeap;
+ ppMemLink = &pMemHeap->phead;
+
+ /* look for chain of RAW blocks first */
+
+ for (pMemLink = *ppMemLink; pMemLink != 0; pMemLink = pMemLink->pnextRaw) {
+ if ((pMemLink->blockType & RTMEMRAW) &&
+ pMemLink->pMemBlk == mem_p)
+ {
+ if (pMemLink->blockType & RTMEMMALLOC)
+ if (g_realloc_func != 0) {
+ void *newMemBlk = g_realloc_func (pMemLink->pMemBlk, nbytes_);
+ if (newMemBlk == 0)
+ return 0;
+ pMemLink->pMemBlk = newMemBlk;
+ }
+ else {
+ /* use malloc/memcpy/free sequence instead of realloc */
+ ASN1OCTET* newBuf;
+ int oldSize = *(int*)(((char*)pMemLink) + sizeof (OSMemLink));
+
+ if (oldSize == -1) return 0;
+ newBuf = (ASN1OCTET*)g_malloc_func (nbytes_);
+ if (newBuf == 0)
+ return 0;
+ memcpy (newBuf, pMemLink->pMemBlk, ASN1MIN (oldSize, nbytes_));
+ free (pMemLink->pMemBlk);
+ pMemLink->pMemBlk = newBuf;
+ }
+ else
+ return 0;
+ *(int*)(((char*)pMemLink) + sizeof (OSMemLink)) = nbytes_;
+ return pMemLink->pMemBlk;
+ }
+ pPrevMemLink = pMemLink;
+ }
+
+ /* Round number of bytes to nearest 8-byte boundary */
+
+ nbytes = ((unsigned)(nbytes_ + 7)) & (~7);
+ nunits = nbytes >> 3;
+
+ pElem = (OSMemElemDescr*) (((char*)mem_p) - sizeof_OSMemElemDescr);
+
+ RTMEMDIAG3 ("memHeapRealloc: mem_p = 0x%x, old size = %d,", mem_p,
+ pElem_nunits (pElem) * 8u);
+ RTMEMDIAG2 (" new nbytes = %d\n", nbytes);
+
+ if ((unsigned)pElem_nunits (pElem) == nunits)
+ return mem_p;
+
+ pMemBlk = GET_MEMBLK (pElem);
+
+ CHECKMEMELEM (pMemBlk, pElem);
+ CHECKMEMBLOCK(pMemHeap, pMemBlk);
+
+ if ((unsigned)pElem_nunits (pElem) < nunits) { /* expanding */
+
+ if (nunits - pElem_nunits (pElem) <= (unsigned)pMemBlk->nunits) {
+
+ /* Try to expand the existing element in the existing block */
+
+ if (ISLAST (pElem)) { /* if the last element in the block */
+
+ /* if the free space in the block is enough */
+
+ if ((int)(nunits - pElem_nunits (pElem)) <=
+ (int)(pMemBlk->nunits - pMemBlk->free_x))
+ {
+ pMemBlk->free_x += nunits - pElem_nunits (pElem);
+ pElem_nunits (pElem) = (ASN1USINT)nunits;
+
+ RTMEMDIAG1 ("memHeapRealloc: "
+ "memory element is expanded.\n");
+
+ FILLNEWMEM (&pMemBlk->data [(pMemBlk->free_x -
+ (nunits - pElem_nunits (pElem))) * 8u],
+ (nunits - pElem_nunits (pElem)) * 8u);
+
+ TRACEMEMELEM (pMemBlk, pElem, "Reallocated");
+ CHECKMEMELEM (pMemBlk, pElem);
+ CHECKMEMBLOCK (pMemHeap, pMemBlk);
+
+ return (mem_p);
+ }
+ }
+ else {
+ OSMemElemDescr* pNextElem, *pFreeElem;
+ unsigned sumSize = pElem_nunits (pElem), freeMem = 0;
+
+ RTMEMDIAG1 ("memHeapRealloc: look for free element after "
+ "current block.\n");
+
+ /* look for free element after pElem */
+
+ pNextElem = GETNEXT (pElem);
+ if (ISFREE (pNextElem)) {
+ /* +1 'cos sizeof (OSMemElemDescr) == 1 unit */
+ sumSize += pElem_nunits (pNextElem) + 1;
+ freeMem++;
+ }
+
+ if (sumSize >= nunits) {
+
+ RTMEMDIAG1 ("memHeapRealloc: reuse free element.\n");
+
+ if (ISFREE (pNextElem)) {
+ pFreeElem = GET_FREE_ELEM (pMemBlk);
+ if (pFreeElem == pNextElem) {
+ FORCE_SET_FREE_ELEM (pMemBlk, GET_NEXT_FREE (pNextElem));
+ }
+ else if (pFreeElem < pElem) {
+
+ /* look for previous free elem to correct nextFreeOff */
+
+ for (; pFreeElem != 0 && pFreeElem < pNextElem;) {
+ OSMemElemDescr* pNextFreeElem =
+ GET_NEXT_FREE (pFreeElem);
+ if (pNextFreeElem == pNextElem) {
+ if (pElem_nextFreeOff (pNextElem) != 0)
+ pElem_nextFreeOff (pFreeElem) = QOFFSETOF
+ (GET_NEXT_FREE (pNextElem), pFreeElem);
+ else
+ pElem_nextFreeOff (pFreeElem) = 0;
+ CHECKMEMELEM (pMemBlk, pFreeElem);
+ break;
+ }
+ pFreeElem = pNextFreeElem;
+ }
+ }
+ }
+
+ /* reuse empty elements after the pElem */
+
+ pMemBlk->freeMem += freeMem;
+
+ if (sumSize - nunits > 1) {
+ OSMemElemDescr* pNewElem;
+
+ /* if sumSize is too large, then create new empty element */
+
+ pNewElem = (OSMemElemDescr*)
+ (pElem_data (pElem) + nbytes);
+ pElem_nunits (pNewElem) = (ASN1USINT)(sumSize - nunits - 1);
+
+ initNewFreeElement (pMemBlk, pNewElem, pElem);
+
+ pMemBlk->freeMem--; /* sizeof (OSMemElemDescr) == 1 unit */
+ pMemBlk->freeMem -= (nunits - pElem_nunits (pElem));
+ pElem_nunits (pElem) = (ASN1USINT)nunits;
+ }
+ else {
+ pMemBlk->freeMem -= (sumSize - pElem_nunits (pElem));
+ pElem_nunits (pElem) = (ASN1USINT)sumSize;
+
+ /* modify the prevOff of the next elem */
+
+ pNextElem = GETNEXT (pElem);
+ if (pNextElem != 0)
+ pElem_prevOff (pNextElem) = QOFFSETOF (pNextElem, pElem);
+ }
+
+ TRACEMEMELEM (pMemBlk, pElem, "Reallocated");
+ CHECKMEMELEM (pMemBlk, pElem);
+ CHECKMEMELEM (pMemBlk, (!ISLAST (pElem)) ? GETNEXT (pElem) : 0);
+ CHECKMEMBLOCK (pMemHeap, pMemBlk);
+ return (mem_p);
+ }
+ }
+ }
+
+ /* If not successful, allocate a new element and move the data into it */
+
+ RTMEMDIAG1 ("memHeapRealloc: allocate new memory...\n");
+
+ CHECKMEMHEAP (pMemHeap);
+
+ newMem_p = memHeapAlloc (ppvMemHeap, nbytes);
+
+ if (newMem_p == 0)
+ return 0;
+
+ /* if the old memory block is marked as saved then mark the new block
+ as saved as well. */
+
+ if (ISSAVED (pElem))
+ memHeapMarkSaved (ppvMemHeap, newMem_p, TRUE);
+
+ CHECKMEMHEAP (pMemHeap);
+
+ memcpy (newMem_p, mem_p, (((ASN1UINT)pElem_nunits (pElem)) * 8u));
+
+ /* free old element */
+
+ RTMEMDIAG1 ("memHeapRealloc: free old pointer...\n");
+
+ memHeapFreePtr (ppvMemHeap, mem_p);
+
+ CHECKMEMHEAP (pMemHeap);
+
+ return (newMem_p);
+ }
+ else { /* shrinking */
+ RTMEMDIAG1 ("memHeapRealloc: shrinking ...\n");
+
+ /* just free the pointer, if nbytes == 0 */
+
+ if (nbytes == 0) {
+ RTMEMDIAG1 ("memHeapRealloc: free pointer...\n");
+ memHeapFreePtr (ppvMemHeap, mem_p);
+ return (NULL);
+ }
+
+ /* do not shrink, if size diff is too small */
+
+ /* sizeof (OSMemElemDescr) == 1 unit */
+ if (pElem_nunits (pElem) - nunits > 1) {
+
+ /* if it is the last element in the block, then just change the size
+ and free_x. */
+
+ if (ISLAST (pElem)) {
+ pMemBlk->free_x -= (pElem_nunits (pElem) - nunits);
+
+ FILLFREEMEM (&pMemBlk->data [pMemBlk->free_x * 8u],
+ (pElem_nunits (pElem) - nunits) * 8u);
+ }
+ else {
+ OSMemElemDescr* pNewElem;
+
+ /* create new free element on the freed place */
+
+ pNewElem = (OSMemElemDescr*) (pElem_data (pElem) + nbytes);
+
+ /* sizeof (OSMemElemDescr) == 1 unit */
+ pElem_nunits (pNewElem) = (ASN1USINT)(pElem_nunits (pElem) - nunits - 1);
+
+ initNewFreeElement (pMemBlk, pNewElem, pElem);
+
+ pMemBlk->freeMem += (pElem_nunits (pElem) - nunits) - 1;
+ }
+ pElem_nunits (pElem) = (ASN1USINT)nunits;
+
+ TRACEMEMELEM (pMemBlk, pElem, "Reallocated");
+ CHECKMEMELEM (pMemBlk, pElem);
+ CHECKMEMELEM (pMemBlk, (!ISLAST (pElem)) ? GETNEXT (pElem) : pElem);
+ CHECKMEMBLOCK (pMemHeap, pMemBlk);
+ }
+ return (mem_p);
+ }
+}
+
+/* Clears heap memory (frees all memory, reset all heap's variables) */
+void memHeapFreeAll (void** ppvMemHeap)
+{
+ OSMemHeap* pMemHeap;
+ OSMemLink* pMemLink;
+ OSMemLink* pMemLink2;
+
+ if (ppvMemHeap == 0 || *ppvMemHeap == 0) return;
+ pMemHeap = *(OSMemHeap**)ppvMemHeap;
+
+ pMemLink = pMemHeap->phead;
+ RTMEMDIAG2 ("memHeapFreeAll: pMemHeap = 0x%x\n", pMemHeap);
+
+ TRACEFREE (pMemHeap, "memHeapFreeAll\n\n");
+ CHECKMEMHEAP (pMemHeap);
+
+ /* Release any dynamic memory blocks that may have been allocated */
+
+ while (pMemLink) {
+ pMemLink2 = pMemLink;
+ pMemLink = pMemLink2->pnext;
+
+ RTMEMDIAG3 ("memHeapFreeAll: pMemLink2 = 0x%x, pMemLink = 0x%x\n",
+ pMemLink2, pMemLink);
+
+#ifdef _MEMDEBUG
+ if (pMemLink2->blockType & RTMEMSTD) {
+ OSMemBlk* pMemBlk = (OSMemBlk*) pMemLink2->pMemBlk;
+ FILLFREEMEM (pMemBlk->data, (pMemBlk->nunits * 8u));
+ FILLFREEMEM (pMemBlk, sizeof (*pMemBlk));
+ }
+#endif
+ if (!(pMemLink2->blockType & RTMEMSAVED)) {
+ OSMemBlk* pMemBlk = (OSMemBlk*) pMemLink2->pMemBlk;
+
+ /* unlink block first */
+
+ if(pMemLink2->pnext != 0) {
+ pMemLink2->pnext->pprev = pMemLink2->pprev;
+ }
+ if(pMemLink2->pprev != 0) {
+ pMemLink2->pprev->pnext = pMemLink2->pnext;
+ }
+ else { /* head */
+ pMemHeap->phead = pMemLink2->pnext;
+ }
+
+ /* correct heap's variables */
+
+ pMemHeap->usedUnits -= pMemBlk->nunits;
+
+ if (pMemBlk->free_x == 0)
+ pMemHeap->freeBlocks --;
+ else
+ pMemHeap->usedBlocks --;
+
+ /* free link and block */
+
+ if (((pMemLink2->blockType & RTMEMSTD) ||
+ (pMemLink2->blockType & RTMEMMALLOC)) &&
+ !(pMemLink2->blockType & RTMEMLINK))
+ g_free_func (pMemLink2->pMemBlk);
+ g_free_func (pMemLink2);
+ }
+ }
+}
+
+/* increments internal refCnt. use memHeapRelease to decrement and release */
+void memHeapAddRef (void** ppvMemHeap)
+{
+ OSMemHeap* pMemHeap;
+
+ if (ppvMemHeap == 0 || *ppvMemHeap == 0) return;
+ pMemHeap = *(OSMemHeap**)ppvMemHeap;
+ pMemHeap->refCnt++;
+}
+
+/* Frees all memory and heap structure as well (if was allocated) */
+void memHeapRelease (void** ppvMemHeap)
+{
+ OSMemHeap** ppMemHeap = (OSMemHeap**)ppvMemHeap;
+
+ if (ppMemHeap != 0 && *ppMemHeap != 0 && --(*ppMemHeap)->refCnt == 0) {
+ OSMemLink* pMemLink, *pMemLink2;
+
+ memHeapFreeAll (ppvMemHeap);
+
+ /* if there are RTMEMSAVED blocks - release memory for links only */
+
+ pMemLink = (*ppMemHeap)->phead;
+ while (pMemLink) {
+ pMemLink2 = pMemLink;
+ pMemLink = pMemLink2->pnext;
+
+ free (pMemLink2);
+ }
+
+ if ((*ppMemHeap)->flags & RT_MH_FREEHEAPDESC)
+ free (*ppMemHeap);
+
+ *ppMemHeap = 0;
+ }
+}
+
+/* This function is used for marking memory block as "saved". It means
+ * that the memory block containing the specified memory pointer won't be
+ * freed after calls to memHeapFreeAll/memHeapReset. User is responsible
+ * for freeing the marked memory block by call to memFreeBlock */
+
+void* memHeapMarkSaved (void** ppvMemHeap, const void* mem_p,
+ ASN1BOOL saved)
+{
+ OSMemHeap* pMemHeap;
+ OSMemLink* pMemLink;
+ ASN1UINT nsaved = 1;
+
+ RTMEMDIAG2 ("memHeapMarkSaved: for mem_p = 0x%x\n", mem_p);
+
+ if (ppvMemHeap == 0 || *ppvMemHeap == 0 || mem_p == 0)
+ return 0;
+
+ pMemHeap = *(OSMemHeap**)ppvMemHeap;
+ pMemLink = pMemHeap->phead;
+
+ /* look for chain of RAW blocks first */
+
+ for (; pMemLink != 0; pMemLink = pMemLink->pnextRaw) {
+ if ((pMemLink->blockType & RTMEMRAW) &&
+ pMemLink->pMemBlk == mem_p)
+ {
+ break;
+ }
+ }
+ if (pMemLink == 0) {
+ OSMemElemDescr* pElem;
+ OSMemBlk* pMemBlk;
+
+ /* gain the MemLink from pointer */
+
+ pElem = (OSMemElemDescr*) (((char*)mem_p) - sizeof_OSMemElemDescr);
+
+ if (ISFREE (pElem)) { /* already freed! */
+ RTMEMDIAG2 ("memHeapMarkSaved: the element 0x%x is "
+ "already free!\n", pElem);
+ return 0;
+ }
+
+ if ((ISSAVED (pElem) && !saved) || (!ISSAVED (pElem) && saved)) {
+
+ pMemBlk = GET_MEMBLK (pElem);
+
+ CHECKMEMELEM (pMemBlk, pElem);
+ CHECKMEMBLOCK(pMemHeap, pMemBlk);
+
+ pMemLink = pMemBlk->plink;
+
+ if (saved)
+ SET_SAVED (pMemBlk, pElem);
+ else
+ CLEAR_SAVED (pMemBlk, pElem);
+ nsaved = pMemBlk->nsaved;
+ }
+ else
+ return 0;
+ }
+ if (saved && nsaved > 0)
+ pMemLink->blockType |= RTMEMSAVED;
+ else if (nsaved == 0)
+ pMemLink->blockType &= (~RTMEMSAVED);
+ return pMemLink->pMemBlk;
+}
+
+/* This function will set the free index in all blocks to zero thereby */
+/* allowing the blocks to be reused (ED, 3/17/2002).. */
+
+void memHeapReset (void** ppvMemHeap)
+{
+ OSMemHeap* pMemHeap;
+ OSMemLink *pMemLink;
+
+ if (ppvMemHeap == 0 || *ppvMemHeap == 0) return;
+ pMemHeap = *(OSMemHeap**)ppvMemHeap;
+
+ pMemLink = pMemHeap->phead;
+ TRACEFREE (pMemHeap, "memHeapReset\n\n");
+ while (pMemLink) {
+ if (!(pMemLink->blockType & RTMEMSAVED)) {
+ if (pMemLink->blockType & RTMEMSTD) {
+ OSMemBlk* pMemBlk = (OSMemBlk*) pMemLink->pMemBlk;
+ if (pMemBlk->free_x != 0) {
+ pMemHeap->freeUnits += pMemBlk->nunits;
+ pMemHeap->freeBlocks ++;
+ }
+ pMemBlk->free_x = 0;
+ pMemBlk->freeElemOff = 0;
+ pMemBlk->lastElemOff = 0;
+ pMemBlk->freeMem = 0;
+ FILLFREEMEM (pMemBlk->data, pMemBlk->nunits * 8u);
+ }
+ else if (pMemLink->blockType & RTMEMRAW) {
+ /* if RAW block - free it */
+ memHeapFreePtr (ppvMemHeap, pMemLink->pMemBlk);
+ }
+ }
+ pMemLink = pMemLink->pnext;
+ }
+}
+
+/* add memory block to list */
+
+static OSMemLink* memHeapAddBlock (OSMemLink** ppMemLink,
+ void* pMemBlk, int blockType)
+{
+ OSMemLink* pMemLink;
+
+ /* if pMemBlk has RTMEMLINK flags it means that it is allocated
+ * cooperatively with OSMemLink, and we don't need to do additional
+ * allocations for it. Just use pointer's arithemtic. */
+
+ if (blockType & RTMEMLINK)
+ pMemLink = (OSMemLink*) (((ASN1OCTET*)pMemBlk) - sizeof (OSMemLink));
+ else {
+ pMemLink = (OSMemLink*) g_malloc_func (
+ sizeof(OSMemLink) + sizeof (int));
+ if (pMemLink == 0) return 0;
+ /* An extra integer is necessary to save a size of a RAW memory block
+ to perform rtMemRealloc through malloc/memcpy/free */
+ *(int*)(((char*)pMemLink) + sizeof (OSMemLink)) = (int)-1;
+ }
+ if (pMemLink == NULL)
+ return NULL;
+ pMemLink->blockType = (ASN1OCTET)blockType;
+ pMemLink->pMemBlk = pMemBlk;
+ pMemLink->pprev = 0;
+ pMemLink->pnext = *ppMemLink;
+
+ if (*ppMemLink != 0) {
+ if ((*ppMemLink)->blockType & RTMEMRAW)
+ pMemLink->pnextRaw = *ppMemLink;
+ else {
+ pMemLink->pnextRaw = (*ppMemLink)->pnextRaw;
+ (*ppMemLink)->pnextRaw = 0;
+ }
+ }
+ else {
+ pMemLink->pnextRaw = 0;
+ }
+
+ *ppMemLink = pMemLink;
+ if (pMemLink->pnext != 0)
+ pMemLink->pnext->pprev = pMemLink;
+ ((OSMemBlk*)pMemBlk)->plink = pMemLink; /*!AB */
+
+ RTMEMDIAG2 ("memHeapAddBlock: pMemLink = 0x%x\n", pMemLink);
+ RTMEMDIAG2 ("memHeapAddBlock: pMemLink->pnext = 0x%x\n",
+ pMemLink->pnext);
+ RTMEMDIAG2 ("memHeapAddBlock: pMemLink->pprev = 0x%x\n",
+ pMemLink->pprev);
+
+ return pMemLink;
+}
+
+int memHeapCheckPtr (void** ppvMemHeap, void* mem_p)
+{
+ OSMemHeap* pMemHeap;
+ OSMemLink* pMemLink;
+
+ RTMEMDIAG2 ("memHeapCheckPtr: for mem_p = 0x%x\n", mem_p);
+
+ if (ppvMemHeap == 0 || *ppvMemHeap == 0 || mem_p == 0)
+ return 0;
+ pMemHeap = *(OSMemHeap**)ppvMemHeap;
+
+ pMemLink = pMemHeap->phead;
+
+ for (; pMemLink != 0; pMemLink = pMemLink->pnext) {
+ if (pMemLink->blockType & RTMEMRAW) {
+
+ /* if RAW block, the pointer should be stored in pMemBlk */
+
+ if (pMemLink->pMemBlk == mem_p)
+ return 1;
+ }
+ else {
+ OSMemBlk* pMemBlk = (OSMemBlk*)pMemLink->pMemBlk;
+
+ /* Check, is the pointer inside this memory page */
+
+ if (mem_p > pMemLink->pMemBlk &&
+ mem_p < (void*)(((ASN1OCTET*)pMemLink->pMemBlk) + pMemBlk->nunits * 8u))
+ {
+ /* Check, is the pointer a correct element of the mem page */
+
+ OSMemElemDescr* pElem = (OSMemElemDescr*) pMemBlk->data;
+ for (; pElem != 0; pElem = GETNEXT (pElem)) {
+
+ void* curMem_p = (void*) pElem_data (pElem);
+ if (curMem_p == mem_p && !ISFREE (pElem))
+ return 1;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+void memHeapSetProperty (void** ppvMemHeap, ASN1UINT propId, void* pProp)
+{
+ OSMemHeap* pMemHeap;
+
+ if (ppvMemHeap == 0)
+ return;
+
+ if (*ppvMemHeap == 0)
+ memHeapCreate (ppvMemHeap);
+
+ pMemHeap = *(OSMemHeap**)ppvMemHeap;
+ switch (propId) {
+ case OSRTMH_PROPID_DEFBLKSIZE:
+ pMemHeap->defBlkSize = *(ASN1UINT*)pProp;
+ break;
+ case OSRTMH_PROPID_SETFLAGS:
+ pMemHeap->flags |= ((*(ASN1UINT*)pProp) & (~RT_MH_INTERNALMASK));
+ break;
+ case OSRTMH_PROPID_CLEARFLAGS:
+ pMemHeap->flags &= ((~(*(ASN1UINT*)pProp)) | RT_MH_INTERNALMASK);
+ break;
+ }
+}
+
+int memHeapCreate (void** ppvMemHeap)
+{
+ OSMemHeap* pMemHeap;
+ if (ppvMemHeap == 0) return ASN_E_INVPARAM;
+
+ pMemHeap = (OSMemHeap*) g_malloc_func (sizeof (OSMemHeap));
+ if (pMemHeap == NULL) return ASN_E_NOMEM;
+ memset (pMemHeap, 0, sizeof (OSMemHeap));
+ pMemHeap->defBlkSize = g_defBlkSize;
+ pMemHeap->refCnt = 1;
+ pMemHeap->flags = RT_MH_FREEHEAPDESC;
+ *ppvMemHeap = (void*)pMemHeap;
+ return ASN_OK;
+}
+