📄 tclalloc.c
字号:
* * Allocate more memory to the indicated bucket. * * Assumes Mutex is already held. * * Results: * None. * * Side effects: * Attempts to get more memory from the system. * *---------------------------------------------------------------------- */static voidMoreCore(bucket) int bucket; /* What bucket to allocat to. */{ register union overhead *op; register long sz; /* size of desired block */ long amt; /* amount to allocate */ int nblks; /* how many blocks we get */ struct block *blockPtr; /* * sbrk_size <= 0 only for big, FLUFFY, requests (about * 2^30 bytes on a VAX, I think) or for a negative arg. */ sz = 1 << (bucket + 3); ASSERT(sz > 0); amt = MAXMALLOC; nblks = amt / sz; ASSERT(nblks*sz == amt); blockPtr = (struct block *) TclpSysAlloc((unsigned) (sizeof(struct block) + amt), 1); /* no more room! */ if (blockPtr == NULL) { return; } blockPtr->nextPtr = blockList; blockList = blockPtr; op = (union overhead *) (blockPtr + 1); /* * Add new memory allocated to that on * free list for this hash bucket. */ nextf[bucket] = op; while (--nblks > 0) { op->ov_next = (union overhead *)((caddr_t)op + sz); op = (union overhead *)((caddr_t)op + sz); } op->ov_next = (union overhead *)NULL;}/* *---------------------------------------------------------------------- * * TclpFree -- * * Free memory. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */voidTclpFree(cp) char *cp; /* Pointer to memory to free. */{ register long size; register union overhead *op; struct block *bigBlockPtr; if (cp == NULL) { return; } Tcl_MutexLock(allocMutexPtr); op = (union overhead *)((caddr_t)cp - sizeof (union overhead)); ASSERT(op->ov_magic0 == MAGIC); /* make sure it was in use */ ASSERT(op->ov_magic1 == MAGIC); if (op->ov_magic0 != MAGIC || op->ov_magic1 != MAGIC) { Tcl_MutexUnlock(allocMutexPtr); return; } RANGE_ASSERT(op->ov_rmagic == RMAGIC); RANGE_ASSERT(*(unsigned short *)((caddr_t)(op + 1) + op->ov_size) == RMAGIC); size = op->ov_index; if ( size == 0xff ) {#ifdef MSTATS nmalloc[NBUCKETS]--;#endif bigBlockPtr = (struct block *) op - 1; bigBlockPtr->prevPtr->nextPtr = bigBlockPtr->nextPtr; bigBlockPtr->nextPtr->prevPtr = bigBlockPtr->prevPtr; TclpSysFree(bigBlockPtr); Tcl_MutexUnlock(allocMutexPtr); return; } ASSERT(size < NBUCKETS); op->ov_next = nextf[size]; /* also clobbers ov_magic */ nextf[size] = op;#ifdef MSTATS nmalloc[size]--;#endif Tcl_MutexUnlock(allocMutexPtr);}/* *---------------------------------------------------------------------- * * TclpRealloc -- * * Reallocate memory. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */char *TclpRealloc(cp, nbytes) char *cp; /* Pointer to alloced block. */ unsigned int nbytes; /* New size of memory. */{ int i; union overhead *op; struct block *bigBlockPtr; int expensive; unsigned long maxsize; if (cp == NULL) { return (TclpAlloc(nbytes)); } Tcl_MutexLock(allocMutexPtr); op = (union overhead *)((caddr_t)cp - sizeof (union overhead)); ASSERT(op->ov_magic0 == MAGIC); /* make sure it was in use */ ASSERT(op->ov_magic1 == MAGIC); if (op->ov_magic0 != MAGIC || op->ov_magic1 != MAGIC) { Tcl_MutexUnlock(allocMutexPtr); return NULL; } RANGE_ASSERT(op->ov_rmagic == RMAGIC); RANGE_ASSERT(*(unsigned short *)((caddr_t)(op + 1) + op->ov_size) == RMAGIC); i = op->ov_index; /* * If the block isn't in a bin, just realloc it. */ if (i == 0xff) { struct block *prevPtr, *nextPtr; bigBlockPtr = (struct block *) op - 1; prevPtr = bigBlockPtr->prevPtr; nextPtr = bigBlockPtr->nextPtr; bigBlockPtr = (struct block *) TclpSysRealloc(bigBlockPtr, sizeof(struct block) + OVERHEAD + nbytes); if (bigBlockPtr == NULL) { Tcl_MutexUnlock(allocMutexPtr); return NULL; } if (prevPtr->nextPtr != bigBlockPtr) { /* * If the block has moved, splice the new block into the list where * the old block used to be. */ prevPtr->nextPtr = bigBlockPtr; nextPtr->prevPtr = bigBlockPtr; } op = (union overhead *) (bigBlockPtr + 1);#ifdef MSTATS nmalloc[NBUCKETS]++;#endif#ifdef RCHECK /* * Record allocated size of block and update magic number bounds. */ op->ov_size = (nbytes + RSLOP - 1) & ~(RSLOP - 1); *(unsigned short *)((caddr_t)(op + 1) + op->ov_size) = RMAGIC;#endif Tcl_MutexUnlock(allocMutexPtr); return (char *)(op+1); } maxsize = 1 << (i+3); expensive = 0; if ( nbytes + OVERHEAD > maxsize ) { expensive = 1; } else if ( i > 0 && nbytes + OVERHEAD < (maxsize/2) ) { expensive = 1; } if (expensive) { void *newp; Tcl_MutexUnlock(allocMutexPtr); newp = TclpAlloc(nbytes); if ( newp == NULL ) { return NULL; } maxsize -= OVERHEAD; if ( maxsize < nbytes ) nbytes = maxsize; memcpy((VOID *) newp, (VOID *) cp, (size_t) nbytes); TclpFree(cp); return newp; } /* * Ok, we don't have to copy, it fits as-is */#ifdef RCHECK op->ov_size = (nbytes + RSLOP - 1) & ~(RSLOP - 1); *(unsigned short *)((caddr_t)(op + 1) + op->ov_size) = RMAGIC;#endif Tcl_MutexUnlock(allocMutexPtr); return(cp);}/* *---------------------------------------------------------------------- * * mstats -- * * Prints two lines of numbers, one showing the length of the * free list for each size category, the second showing the * number of mallocs - frees for each size category. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */#ifdef MSTATSvoidmstats(s) char *s; /* Where to write info. */{ register int i, j; register union overhead *p; int totfree = 0, totused = 0; Tcl_MutexLock(allocMutexPtr); fprintf(stderr, "Memory allocation statistics %s\nTclpFree:\t", s); for (i = 0; i < NBUCKETS; i++) { for (j = 0, p = nextf[i]; p; p = p->ov_next, j++) fprintf(stderr, " %d", j); totfree += j * (1 << (i + 3)); } fprintf(stderr, "\nused:\t"); for (i = 0; i < NBUCKETS; i++) { fprintf(stderr, " %d", nmalloc[i]); totused += nmalloc[i] * (1 << (i + 3)); } fprintf(stderr, "\n\tTotal small in use: %d, total free: %d\n", totused, totfree); fprintf(stderr, "\n\tNumber of big (>%d) blocks in use: %d\n", MAXMALLOC, nmalloc[NBUCKETS]); Tcl_MutexUnlock(allocMutexPtr);}#endif#else /* !USE_TCLALLOC *//* *---------------------------------------------------------------------- * * TclpAlloc -- * * Allocate more memory. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */char *TclpAlloc(nbytes) unsigned int nbytes; /* Number of bytes to allocate. */{ return (char*) malloc(nbytes);}/* *---------------------------------------------------------------------- * * TclpFree -- * * Free memory. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */voidTclpFree(cp) char *cp; /* Pointer to memory to free. */{ free(cp); return;}/* *---------------------------------------------------------------------- * * TclpRealloc -- * * Reallocate memory. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */char *TclpRealloc(cp, nbytes) char *cp; /* Pointer to alloced block. */ unsigned int nbytes; /* New size of memory. */{ return (char*) realloc(cp, nbytes);}#endif /* !USE_TCLALLOC */#endif /* !TCL_THREADS */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -