📄 balloc.c
字号:
*/
if (bp->u.size >= newsize) {
return mp;
}
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 (defined (B_FILL) || defined (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
/******************************************************************************/
#ifdef 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 sprintf
static 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 */
/******************************************************************************/
#ifdef 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)
{
#ifdef 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 + -