diff options
author | Russell Bryant <russell@russellbryant.com> | 2009-06-30 16:40:38 +0000 |
---|---|---|
committer | Russell Bryant <russell@russellbryant.com> | 2009-06-30 16:40:38 +0000 |
commit | c511a2674906fd93470f0a9b77340041771466e1 (patch) | |
tree | d3d6aa7ea86d11ecaa6e88efbc46a5dde1c63ea5 /addons/ooh323c/src/memheap.c | |
parent | 62d3f1dfd9632f18c4f7c12e44af30f4cc08c292 (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: https://origsvn.digium.com/svn/asterisk/trunk@204413 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'addons/ooh323c/src/memheap.c')
-rw-r--r-- | addons/ooh323c/src/memheap.c | 1331 |
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; +} + |