📄 balloc.c
字号:
} if ((newbuf = balloc(B_ARGS, newsize)) != NULL) { memcpy(newbuf, mp, bp->u.size); bfree(B_ARGS, mp); } return newbuf;}/******************************************************************************//* * Find the size of the block to be balloc'ed. It takes in a size, finds the * smallest binary block it fits into, adds an overhead amount and returns. * q is the binary size used to keep track of block sizes in use. Called * from both balloc and bfree. */static int ballocGetSize(int size, int *q){ int mask; mask = (size == 0) ? 0 : (size-1) >> B_SHIFT; for (*q = 0; mask; mask >>= 1) { *q = *q + 1; } return ((1 << (B_SHIFT + *q)) + sizeof(bType));}/******************************************************************************/#if B_FILL || B_VERIFY_CAUSES_SEVERE_OVERHEAD/* * Fill the block (useful during development to catch zero fill assumptions) */static void bFillBlock(void *buf, int bufsize){ memset(buf, B_FILL_CHAR, bufsize);}#endif/******************************************************************************/#if B_STATS/* * Statistics. Do output via calling the writefn callback function with * "handle" as the output file handle. */void bstats(int handle, void (*writefn)(int handle, char_t *fmt, ...)){ bStatsFileType *fp, *files; bStatsBlkType *blkp; bType *bp; char_t *cp; int q, count, mem, total, len; static int recurseProtect = 0; if (recurseProtect++ > 0) { recurseProtect--; return; } if (writefn == NULL) { writefn = bstatsWrite; }/* * Print stats for each memory block */ (*writefn)(handle, T("\nMemory Stats\n"));/* * The following tabular format is now used for the output. * Q Size Free Bytes Inuse Bytes Allocs * dd ddddd ddd ddddd dddd ddddd dddd */ (*writefn)(handle, " Q Size Free Bytes Inuse Bytes Allocs\n"); total = 0; for (q = 0; q < B_MAX_CLASS; q++) { count = 0; for (bp = bQhead[q]; bp; bp = bp->u.next) { count++; } mem = count * (1 << (q + B_SHIFT)); total += mem; (*writefn)(handle, T("%2d %5d %4d %6d %4d %5d %4d\n"), q, 1 << (q + B_SHIFT), count, mem, bStats[q].inuse, bStats[q].inuse * (1 << (q + B_SHIFT)), bStats[q].alloc); } (*writefn)(handle, T("\n"));/* * Print summary stats * * bFreeSize Initial memory reserved with bopen call * bStatsMemMalloc memory from calls to system MALLOC * bStatsMemMax * bStatsBallocMax largest amount of memory from balloc calls * bStatsMemInUse * bStatsBallocInUse present balloced memory being used * bStatsBlksMax); * bStackStart * bStackMin); * total); * bFreeLeft); * */ (*writefn)(handle, T("Initial free list size %7d\n"), bFreeSize); (*writefn)(handle, T("Max memory malloced %7d\n"), bStatsMemMalloc); (*writefn)(handle, T("Max memory ever used %7d\n"), bStatsMemMax); (*writefn)(handle, T("Max memory ever balloced %7d\n"), bStatsBallocMax); (*writefn)(handle, T("Memory currently in use %7d\n"), bStatsMemInUse); (*writefn)(handle, T("Memory currently balloced %7d\n"), bStatsBallocInUse); (*writefn)(handle, T("Max blocks allocated %7d\n"), bStatsBlksMax); (*writefn)(handle, T("Maximum stack used %7d\n"), (int) bStackStart - (int) bStackMin); (*writefn)(handle, T("Free memory on all queues %7d\n"), total); (*writefn)(handle, T("Free list buffer left %7d\n"), bFreeLeft); (*writefn)(handle, T("Total free memory %7d\n"), bFreeLeft + total);/* * Print per file allocation stats. Sort the copied table. */ len = sizeof(bStatsFileType) * B_MAX_FILES; files = malloc(len); if (files == NULL) { (*writefn)(handle, T("Can't allocate stats memory\n")); recurseProtect--; return; } memcpy(files, bStatsFiles, len); qsort(files, bStatsFilesMax, sizeof(bStatsFileType), bStatsFileSort); (*writefn)(handle, T("\nMemory Currently Allocated\n")); total = 0; (*writefn)(handle, T(" bytes, blocks in use, total times,") T("largest, q\n")); for (fp = files; fp < &files[bStatsFilesMax]; fp++) { if (fp->file[0]) { (*writefn)(handle, T("%18s, %7d, %5d, %6d, %7d,%4d\n"), fp->file, fp->allocated, fp->count, fp->times, fp->largest, fp->q); total += fp->allocated; } } (*writefn)(handle, T("\nTotal allocated %7d\n\n"), total);/* * Dump the actual strings */ (*writefn)(handle, T("\nStrings\n")); for (blkp = &bStatsBlks[bStatsBlksMax - 1]; blkp >= bStatsBlks; blkp--) { if (blkp->ptr) { cp = (char_t*) ((char*) blkp->ptr + sizeof(bType)); fp = blkp->who; if (gisalnum(*cp)) { (*writefn)(handle, T("%-50s allocated by %s\n"), cp, fp->file); } } } free(files); recurseProtect--;}/******************************************************************************//* * File sort function. Used to sort per file stats */static int bStatsFileSort(const void *cp1, const void *cp2){ bStatsFileType *s1, *s2; s1 = (bStatsFileType*) cp1; s2 = (bStatsFileType*) cp2; if (s1->allocated < s2->allocated) return -1; else if (s1->allocated == s2->allocated) return 0; return 1;}/******************************************************************************//* * Accumulate allocation statistics */static void bStatsAlloc(B_ARGS_DEC, void *ptr, int q, int size){ int memSize; bStatsFileType *fp; bStatsBlkType *bp; char_t name[FNAMESIZE + 10]; gsprintf(name, T("%s:%d"), B_ARGS); bStats[q].alloc++; bStats[q].inuse++; bStatsMemInUse += size; if (bStatsMemInUse > bStatsMemMax) { bStatsMemMax = bStatsMemInUse; } memSize = (1 << (B_SHIFT + q)) + sizeof(bType); bStatsBallocInUse += memSize; if (bStatsBallocInUse > bStatsBallocMax) { bStatsBallocMax = bStatsBallocInUse; }/* * Track maximum stack usage. Assumes a stack growth down. Approximate as * we only measure this on block allocation. */ if ((void*) &file < bStackMin) { bStackMin = (void*) &file; }/* * Find the file and adjust the stats for this file */ for (fp = bStatsFiles; fp < &bStatsFiles[bStatsFilesMax]; fp++) { if (fp->file[0] == file[0] && gstrcmp(fp->file, name) == 0) { fp->allocated += size; fp->count++; fp->times++; if (fp->largest < size) { fp->largest = size; fp->q = q; } break; } }/* * New entry: find the first free slot and create a new entry */ if (fp >= &bStatsFiles[bStatsFilesMax]) { for (fp = bStatsFiles; fp < &bStatsFiles[B_MAX_FILES]; fp++) { if (fp->file[0] == '\0') { gstrncpy(fp->file, name, TSZ(fp->file)); fp->allocated += size; fp->count++; fp->times++; fp->largest = size; fp->q = q; if ((fp - bStatsFiles) >= bStatsFilesMax) { bStatsFilesMax = (fp - bStatsFiles) + 1; } break; } } }/* * Update the per block stats. Allocate a new slot. */ for (bp = bStatsBlks; bp < &bStatsBlks[B_MAX_BLOCKS]; bp++) { if (bp->ptr == NULL) { bp->ptr = ptr; bp->who = fp; if ((bp - bStatsBlks) >= bStatsBlksMax) { bStatsBlksMax = (bp - bStatsBlks) + 1; } break; } }}/******************************************************************************//* * Free statistics */static void bStatsFree(B_ARGS_DEC, void *ptr, int q, int size){ int memSize; bStatsFileType *fp; bStatsBlkType *bp; memSize = (1 << (B_SHIFT + q)) + sizeof(bType); bStatsMemInUse -= size; bStatsBallocInUse -= memSize; bStats[q].inuse--;/* * Update the per block stats. Try from the end first */ for (bp = &bStatsBlks[bStatsBlksMax - 1]; bp >= bStatsBlks; bp--) { if (bp->ptr == ptr) { bp->ptr = NULL; fp = bp->who; bp->who = NULL; fp->allocated -= size; fp->count--; return; } }}/******************************************************************************//* * Default output function. Just send to trace channel. */#undef sprintfstatic void bstatsWrite(int handle, char_t *fmt, ...){ va_list args; char_t buf[BUF_MAX]; va_start(args, fmt); vsprintf(buf, fmt, args); va_end(args); traceRaw(buf);}#else /* not B_STATS *//******************************************************************************//* * Dummy bstats for external calls that aren't protected by #if B_STATS. */void bstats(int handle, void (*writefn)(int handle, char_t *fmt, ...)){}#endif /* B_STATS *//******************************************************************************/#if B_VERIFY_CAUSES_SEVERE_OVERHEAD/* * The following routines verify the integrity of the balloc memory space. * These functions use the B_FILL feature. Corruption is defined * as bad integrity flags in allocated blocks or data other than B_FILL_CHAR * being found anywhere in the space which is unallocated and that is not a * next pointer in the free queues. a_assert is called if any corruption is * found. CAUTION: These functions add severe processing overhead and should * only be used when searching for a tough corruption problem. *//******************************************************************************//* * verifyUsedBlock verifies that a block which was previously allocated is * still uncorrupted. */static void verifyUsedBlock(bType *bp, int q){ int memSize, size; char *p; memSize = (1 << (B_SHIFT + q)) + sizeof(bType); a_assert((bp->flags & ~B_MALLOCED) == B_INTEGRITY); size = bp->u.size; for (p = ((char *)bp)+sizeof(bType)+size; p < ((char*)bp)+memSize; p++) { a_assert(*p == B_FILL_CHAR); }}/******************************************************************************//* * verifyFreeBlock verifies that a previously free'd block in one of the queues * is still uncorrupted. */static void verifyFreeBlock(bType *bp, int q){ int memSize; char *p; memSize = (1 << (B_SHIFT + q)) + sizeof(bType); for (p = ((char *)bp)+sizeof(void*); p < ((char*)bp)+memSize; p++) { a_assert(*p == B_FILL_CHAR); } bp = (bType *)p; a_assert((bp->flags & ~B_MALLOCED) == B_INTEGRITY || bp->flags == B_FILL_WORD);}/******************************************************************************//* * verifyBallocSpace reads through the entire balloc memory space and * verifies that all allocated blocks are uncorrupted and that, with the * exception of free list next pointers, all other unallocated space is * filled with B_FILL_CHAR. */void verifyBallocSpace(){ int q; char *p; bType *bp;/* * First verify all the free blocks. */ for (q = 0; q < B_MAX_CLASS; q++) { for (bp = bQhead[q]; bp != NULL; bp = bp->u.next) { verifyFreeBlock(bp, q); } }/* * Now verify other space */ p = bFreeBuf; while (p < (bFreeBuf + bFreeSize)) { bp = (bType *)p; if (bp->u.size > 0xFFFFF) { p += sizeof(bp->u); while (p < (bFreeBuf + bFreeSize) && *p == B_FILL_CHAR) { p++; } } else { a_assert(((bp->flags & ~B_MALLOCED) == B_INTEGRITY) || bp->flags == B_FILL_WORD); p += (sizeof(bType) + bp->u.size); while (p < (bFreeBuf + bFreeSize) && *p == B_FILL_CHAR) { p++; } } }}#endif /* B_VERIFY_CAUSES_SEVERE_OVERHEAD *//******************************************************************************/#else /* NO_BALLOC */int bopen(void *buf, int bufsize, int flags){ return 0;}/******************************************************************************/void bclose(){}/******************************************************************************/void bstats(int handle, void (*writefn)(int handle, char_t *fmt, ...)){}/******************************************************************************/char_t *bstrdupNoBalloc(char_t *s){#if UNICODE if (s) { return wcsdup(s); } else { return wcsdup(T("")); }#else return bstrdupANoBalloc(s);#endif}/******************************************************************************/char *bstrdupANoBalloc(char *s){ char* buf; if (s == NULL) { s = ""; } buf = malloc(strlen(s)+1); strcpy(buf, s); return buf;}#endif /* NO_BALLOC *//******************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -