memheap.c

来自「一个非常美妙的proxy。功能强大。基于sip的协议。如果还要的话」· C语言 代码 · 共 1,332 行 · 第 1/3 页

C
1,332
字号
/* * 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_REALLOCOSReallocFunc g_realloc_func = realloc;#elseOSReallocFunc g_realloc_func = 0;#endifOSFreeFunc    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;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?