memheap.c

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

C
1,332
字号
      }      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;

⌨️ 快捷键说明

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