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 + -
显示快捷键?