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