📄 rmmmhomemade.c
字号:
return (void *)beginning;}void MOD(RMFreeInZone)(void *mac,struct mz *pZ,void *ptr){ RMalignment al=MMREADFIELD(mac,pZ,alignment); struct mbh *pX; RMuint32 sizeOfX = 0; struct mbh *pCurrent,*pPrevious; struct mbh *pL=(struct mbh *)NULL,*pR=(struct mbh *)NULL; // ! &(x->field) is tricky but ok struct mbh **ppFirstFree=(struct mbh **)(&(pZ->pFirstFree)); LOCK(mac); if (!( (AmIBefore((struct mbh *)(MMREADFIELD(mac,pZ,beginning)+HeaderSkip(al)-1), (struct mbh *)ptr) && AmIBefore((struct mbh *)ptr, (struct mbh *)(MMREADFIELD(mac,pZ,beginning)+MMREADFIELD(mac,pZ,totalSize)))) )) goto bad; // rewind to the memory block header. pX=(struct mbh *)(((RMuint8 *)ptr)-HeaderSkip(al)); sizeOfX=MMREADFIELD(mac,pX,size); // can we assume this is a valid block header? Let's check the hash. if (Hash((RMuint32)ptr,MMREADFIELD(mac,pX,size))!=MMREADFIELD(mac,pX,hash)) goto bad; /************************************************************** Let's make eight cases: the block we want to free is pX. EMPTYFREELIST: the free block list has no blocks. Make pX part of it. Over. BEFOREFIRSTNEIGHBOR: pX is the left neighbor of the first free block. Gather them (one block disappears). Over. BEFOREFIRST: pX is not the left neighbor, but is before the first free block. Make pX the first free block and link to the free block list. Over. Now, let's go thru the free block list: while (pCurrent) { pCurrent is a candidate to be left neighbor pL of pX and pCurrent->next a candidate to be the right neighbor pR of pX. MIDDLEBOTH: if we find both neighbors L and R, we gather pL, pX and pR (two blocks disappear). Over. MIDDLELEFT: if we find only the left neighbor L, we gather pL and pX (one block disappears). Over. MIDDLERIGHT: if we find only the right neighbor R, we gather pX and pR (one block disappears). Over. MIDDLENONE: if pCurrent->next exists and pCurrent < pX < pCurrent->next we cannot gather anything, but we insert this lonely block in the free list. Over. pPrevious=pCurrent; pCurrent=pCurrent->next; } If the loop exits, it means pX is after the last free block (his name is pPrevious). pX cannot be the right neighbor of pPrevious, because this case has been treated by case MIDDLELEFT. Only solution left: AFTERLAST: pX is not the right neighbor, but is after pPrevious. Make a new link. Over. All cases have been treated. **************************************************************/ // EMPTYFREELIST if ((struct mbh *)MMREAD32(mac,ppFirstFree)==NULL) { RMDBGLOG((LOCALDBG,"RMFreeInZone: EMPTYFREELIST\n")); MMWRITEFIELD(mac,pX,hash,freeBlockHash); MMWRITE32(mac,ppFirstFree,pX); MMWRITEFIELD(mac,pX,next,(struct mbh *)NULL); goto returnok; } // BEFOREFIRSTNEIGHBOR if (AmILeftNeighbor(mac,pX,(struct mbh *)MMREAD32(mac,ppFirstFree),al)) { RMDBGLOG((LOCALDBG,"RMFreeInZone: BEFOREFIRSTNEIGHBOR\n")); MMWRITEFIELD(mac,(struct mbh *)MMREAD32(mac,ppFirstFree),hash,disappearedHash); MMWRITEFIELD(mac,pX,hash,freeBlockHash); MMWRITEFIELD(mac,pX,next,MMREADFIELD(mac,(struct mbh *)MMREAD32(mac,ppFirstFree),next)); MMWRITEFIELD(mac,pX,size, MMREADFIELD(mac,pX,size) +HeaderSkip(al) +MMREADFIELD(mac,(struct mbh *)MMREAD32(mac,ppFirstFree),size)); MMWRITE32(mac,ppFirstFree,pX); goto returnok; } // BEFOREFIRST if (AmIBefore(pX,(struct mbh *)MMREAD32(mac,ppFirstFree))) { RMDBGLOG((LOCALDBG,"RMFreeInZone: BEFOREFIRST\n")); MMWRITEFIELD(mac,pX,hash,freeBlockHash); MMWRITEFIELD(mac,pX,next,MMREAD32(mac,ppFirstFree)); MMWRITE32(mac,ppFirstFree,pX); goto returnok; } pPrevious=(struct mbh *)NULL; pCurrent=(struct mbh *)MMREAD32(mac,ppFirstFree); while (pCurrent) { /* notice that once one of pL or pR is not NULL we exit the while loop, so no need to reset them at each turn. */ // is pCurrent the left neighbor? if (AmILeftNeighbor(mac,pCurrent,pX,al)) pL=pCurrent; // is pCurrent->next the right neighbor? if (MMREADFIELD(mac,pCurrent,next)) if (AmILeftNeighbor(mac,pX,(struct mbh *)MMREADFIELD(mac,pCurrent,next),al)) pR=(struct mbh *)MMREADFIELD(mac,pCurrent,next); // MIDDLEBOTH if (pL&&pR) { RMDBGLOG((LOCALDBG,"RMFreeInZone: MIDDLEBOTH\n")); MMWRITEFIELD(mac,pX,hash,disappearedHash); MMWRITEFIELD(mac,pR,hash,disappearedHash); MMWRITEFIELD(mac,pL,next,MMREADFIELD(mac,pR,next)); MMWRITEFIELD(mac,pL,size, MMREADFIELD(mac,pL,size) +HeaderSkip(al) +MMREADFIELD(mac,pX,size) +HeaderSkip(al) +MMREADFIELD(mac,pR,size)); goto returnok; } // MIDDLELEFT if (pL) { RMDBGLOG((LOCALDBG,"RMFreeInZone: MIDDLELEFT\n")); MMWRITEFIELD(mac,pX,hash,disappearedHash); MMWRITEFIELD(mac,pL,next,MMREADFIELD(mac,pCurrent,next)); MMWRITEFIELD(mac,pL,size, MMREADFIELD(mac,pL,size) +HeaderSkip(al) +MMREADFIELD(mac,pX,size)); goto returnok; } // MIDDLERIGHT if (pR) { RMDBGLOG((LOCALDBG,"RMFreeInZone: MIDDLERIGHT\n")); // pPrevious cannot be NULL (treated by BEFOREFIRSTNEIGHBOR case). MMWRITEFIELD(mac,pX,hash,freeBlockHash); MMWRITEFIELD(mac,pR,hash,disappearedHash); MMWRITEFIELD(mac,pCurrent,next,pX); MMWRITEFIELD(mac,pX,next,MMREADFIELD(mac,pR,next)); MMWRITEFIELD(mac,pX,size, MMREADFIELD(mac,pX,size) +HeaderSkip(al) +MMREADFIELD(mac,pR,size)); goto returnok; } // MIDDLENONE if (MMREADFIELD(mac,pCurrent,next)) if (AmIBefore(pCurrent,pX)&&AmIBefore(pX,(struct mbh *)MMREADFIELD(mac,pCurrent,next))) { RMDBGLOG((LOCALDBG,"RMFreeInZone: MIDDLENONE\n")); MMWRITEFIELD(mac,pX,hash,freeBlockHash); MMWRITEFIELD(mac,pX,next,MMREADFIELD(mac,pCurrent,next)); MMWRITEFIELD(mac,pCurrent,next,pX); goto returnok; } pPrevious=pCurrent; pCurrent=(struct mbh *)MMREADFIELD(mac,pCurrent,next); //RMDBGLOG((LOCALDBG,"(RMFreeInZone: hop to next free block)\n")); } // AFTERLAST RMDBGLOG((LOCALDBG,"RMFreeInZone: AFTERLAST\n")); MMWRITEFIELD(mac,pX,hash,freeBlockHash); // pPrevious->next cannot be NULL since there is at least one item in the free block list. MMWRITEFIELD(mac,pPrevious,next,pX); MMWRITEFIELD(mac,pX,next,(struct mbh *)NULL); goto returnok; bad: UNLOCK(mac); RMDBGLOG((ENABLE,"RMFreeInZone: bad pointer %p\n",ptr));#ifdef WITH_FEEBLEMM // just let RMFree return#else RMPanic(RM_FATALINVALIDPOINTER);#endif // WITH_FEEBLEMM return; returnok: MMWRITEFIELD(mac,pZ,successfulFrees, MMREADFIELD(mac,pZ,successfulFrees)+1); MMWRITEFIELD(mac,pZ,occupiedSize, MMREADFIELD(mac,pZ,occupiedSize)-sizeOfX); // this is extremely serious. if ( ((MMREADFIELD(mac,pZ,successfulMallocs)-MMREADFIELD(mac,pZ,successfulFrees))<0) || (MMREADFIELD(mac,pZ,occupiedSize)<0) ) { UNLOCK(mac); RMPanic(RM_FATALMEMORYCORRUPTED); } UNLOCK(mac);}RMuint32 MOD(RMGetAreaSize)(void *mac,struct mz *pZ,void *ptr){ RMalignment al=MMREADFIELD(mac,pZ,alignment); struct mbh *pX; RMuint32 sizeOfX = 0; LOCK(mac); if (!( (AmIBefore((struct mbh *)(MMREADFIELD(mac,pZ,beginning)+HeaderSkip(al)-1), (struct mbh *)ptr) && AmIBefore((struct mbh *)ptr, (struct mbh *)(MMREADFIELD(mac,pZ,beginning)+MMREADFIELD(mac,pZ,totalSize)))) )) goto bad; // rewind to the memory block header. pX=(struct mbh *)(((RMuint8 *)ptr)-HeaderSkip(al)); // can we assume this is a valid block header? Let's check the hash. if (Hash((RMuint32)ptr,MMREADFIELD(mac,pX,size))!=MMREADFIELD(mac,pX,hash)) goto bad; sizeOfX=MMREADFIELD(mac,pX,size); goto do_return; bad: RMDBGLOG((ENABLE,"RMGetAreaSize: bad pointer %p\n",ptr));#ifdef WITH_FEEBLEMM // just let RMFree return#else RMPanic(RM_FATALINVALIDPOINTER);#endif // WITH_FEEBLEMM do_return: UNLOCK(mac); return sizeOfX;}void MOD(RMGetZoneStats)(void *mac, struct mz *pZ, RMuint32 *pSuccessfulMallocs, RMuint32 *pSuccessfulFrees, RMint32 *pOccupiedSize, RMint32 *pMaxSize){ if (pSuccessfulMallocs!=NULL) *pSuccessfulMallocs=MMREADFIELD(mac,pZ,successfulMallocs); if (pSuccessfulFrees!=NULL) *pSuccessfulFrees=MMREADFIELD(mac,pZ,successfulFrees); if (pOccupiedSize!=NULL) *pOccupiedSize=MMREADFIELD(mac,pZ,occupiedSize); if (pMaxSize!=NULL) *pMaxSize=MMREADFIELD(mac,pZ,maxSize);}void MOD(RMDumpMallocedBlocksInZone)(void *mac,struct mz *pZ){ RMalignment al=MMREADFIELD(mac,pZ,alignment); struct mbh *pX; struct mbh *pCurrent; // allow negative numbers to trap corruption RMint32 computed_allocCount,computed_occupiedSize; struct mbh **ppFirstFree; LOCK(mac); computed_allocCount = 0; computed_occupiedSize = 0; // ! &(x->field) is tricky but ok ppFirstFree = (struct mbh **)(&(pZ->pFirstFree)); pX=(struct mbh *)MMREADFIELD(mac,pZ,beginning); pCurrent=(struct mbh *)MMREAD32(mac,ppFirstFree); RMDBGLOG((ENABLE,"RMDumpMallocedBlocksInZone: allocCount=%ld occupiedSize=%ld\n", MMREADFIELD(mac,pZ,successfulMallocs)-MMREADFIELD(mac,pZ,successfulFrees), MMREADFIELD(mac,pZ,occupiedSize))); /* DOUBLE LOOP. pX goes thru candidates for occupied blocks (new pX is right neighbor of pX) pCurrent goes thru the linked list of free blocks as usual Focus attention on pX to understand the code. Let's start at the first possible pointer to an occupied block at the beginning of the zone */ while ( pX != (struct mbh *)(MMREADFIELD(mac,pZ,beginning)+MMREADFIELD(mac,pZ,totalSize)) ) { if (pX!=pCurrent) { // this must be an occupied block. // Let's check the hash. if (Hash((RMuint32)DataAddress(pX,al),MMREADFIELD(mac,pX,size))!=MMREADFIELD(mac,pX,hash)) goto bad; RMDBGLOG((ENABLE,"RMDumpMallocedBlocksInZone: occupied block #%3ld is (%p,%ld)\n", computed_allocCount, (void *)DataAddress(pX,al), MMREADFIELD(mac,pX,size))); computed_allocCount++; computed_occupiedSize+=MMREADFIELD(mac,pX,size); } else { RMDBGLOG((ENABLE,"RMDumpMallocedBlocksInZone: skipping free block\n")); // this is a free block. pCurrent=(struct mbh *)MMREADFIELD(mac,pCurrent,next); } // compute right neighbor. pX=(struct mbh *)(DataAddress(pX,al)+MMREADFIELD(mac,pX,size)); } if (computed_allocCount!=(RMint32)(MMREADFIELD(mac,pZ,successfulMallocs)-MMREADFIELD(mac,pZ,successfulFrees))) goto bad; if (computed_occupiedSize!=(RMint32)MMREADFIELD(mac,pZ,occupiedSize)) goto bad; RMDBGLOG((ENABLE,"RMDumpMallocedBlocksInZone: seems memory is not corrupted :-)\n")); UNLOCK(mac); return; bad: UNLOCK(mac); RMPanic(RM_FATALMEMORYCORRUPTED);}void *MOD(RMMemsetInZone)(void *mac,struct mz *pZ,void *s, RMuint8 c, RMuint32 n){ RMuint32 i; for (i=0;i<n;i++) MMWRITE8(mac,((RMuint8 *)s)+i,c); return s;}void *MOD(RMMemcpyInZone)(void *mac,struct mz *pZ,void *dest,const void *src,RMuint32 n){ RMuint32 i; for (i=0;i<n;i++) { RMuint8 c=MMREAD8(mac,((RMuint8 *)src)+i); MMWRITE8(mac,((RMuint8 *)dest)+i,c); } return dest;}RMint32 MOD(RMMemcmpInZone)(void *mac,struct mz *pZ,const void *s1, const void *s2,RMuint32 n) { RMuint32 i; for (i=0;i<n;i++) { RMuint8 c1=MMREAD8(mac,((RMuint8 *)s1)+i); RMuint8 c2=MMREAD8(mac,((RMuint8 *)s2)+i); if (c1<c2) return -1; if (c1>c2) return 1; } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -