📄 malloc.c
字号:
DELFREEQ(blk); /* make head of free queue immediately follow blk, unless blk was at the end of the queue */ nblk = blk->nextfree; if (nblk != &(freeptr[1])) { MOVEHEAD(nblk); } } /* blk now points to an adequate block */ if (((char *)blk->nextblk - (char *)blk) - nb >= MINBLKSZ) { /* carve out the right size block */ /* newblk will be the remainder */ newblk = (struct header *)((char *)blk + nb); newblk->nextblk = blk->nextblk; /* mark the block busy */ blk->nextblk = SETBUSY(newblk); ADDFREEQ(newblk); /* if blk was lastblk, make newblk lastblk */ if(blk==lastblk) lastblk = newblk; } else { /* just mark the block busy */ blk->nextblk = SETBUSY(blk->nextblk); } } CHECKQ; return (char *)blk + minhead;}/* free(ptr) - free block that user thinks starts at ptr input - ptr-1 contains the block header. If the header points forward, we have a normal block pointing to the next block if the header points backward, we have a small block from a holding block. In both cases, the busy bit must be set*/voidfree(ptr)char *ptr;{ register struct holdblk *holdblk; /* block holding blk */ register struct holdblk *oldhead; /* former head of the hold block queue containing blk's holder */ if (TESTSMAL(((struct header *)(ptr - MINHEAD))->nextblk)) { register struct lblk *lblk; /* pointer to freed block */ register offset; /* choice of header lists */ lblk = (struct lblk *)CLRBUSY(ptr - MINHEAD); assert((struct header *)lblk < arenaend); assert((struct header *)lblk > arena); /* allow twits (e.g. awk) to free a block twice */ if (!TESTBUSY(holdblk = lblk->header.holder)) return; holdblk = (struct holdblk *)CLRALL(holdblk); /* put lblk on its hold block's free list */ lblk->header.nextfree = SETSMAL(holdblk->lfreeq); holdblk->lfreeq = lblk; /* move holdblk to head of queue, if its not already there */ offset = holdblk->blksz/grain; oldhead = holdhead[offset]; if (oldhead != holdblk) { /* first take out of current spot */ holdhead[offset] = holdblk; holdblk->nexthblk->prevhblk = holdblk->prevhblk; holdblk->prevhblk->nexthblk = holdblk->nexthblk; /* now add at front */ holdblk->nexthblk = oldhead; holdblk->prevhblk = oldhead->prevhblk; oldhead->prevhblk = holdblk; holdblk->prevhblk->nexthblk = holdblk; } } else { register struct header *blk; /* real start of block*/ register struct header *next; /* next = blk->nextblk*/ register struct header *nextnext; /* block after next */ blk = (struct header *)(ptr - minhead); next = blk->nextblk; /* take care of twits (e.g. awk) who return blocks twice */ if (!TESTBUSY(next)) return; blk->nextblk = next = CLRBUSY(next); ADDFREEQ(blk); /* see if we can compact */ if (!TESTBUSY(nextnext = next->nextblk)) { do { DELFREEQ(next); next = nextnext; } while (!TESTBUSY(nextnext = next->nextblk)); if (next == arenaend) lastblk = blk; blk->nextblk = next; } } CHECKQ}/* realloc(ptr,size) - give the user a block of size "size", with the contents pointed to by ptr. Free ptr.*/void *realloc(ptr,size)char *ptr; /* block to change size of */unsigned size; /* size to change to */{ register struct header *blk; /* block ptr is contained in */ register unsigned trusize; /* size of block, as allocaters see it*/ char *newptr; /* pointer to user's new block */ register unsigned cpysize; /* amount to copy */ register struct header *next; /* block after blk */ if(size == 0) return NULL; if (TESTSMAL(((struct lblk *)(ptr - MINHEAD))->header.holder)) { /* we have a special small block which can't be expanded */ /* This makes the assumption that even if the user is reallocating a free block, malloc doesn't alter the contents of small blocks */ newptr = malloc(size); if (newptr == NULL) return NULL; /* this isn't to save time--its to protect the twits */ if(ptr != newptr) { (void)memcpy(newptr,ptr,(int)size); free(ptr); } } else { blk = (struct header *)(ptr - minhead); next = blk->nextblk; /* deal with twits who reallocate free blocks */ /* if they haven't reset minblk via getopt, that's thier problem */ if (!TESTBUSY(next)) { DELFREEQ(blk); blk->nextblk = SETBUSY(next); } next = CLRBUSY(next); /* make blk as big as possible */ if (!TESTBUSY(next->nextblk)) { do { DELFREEQ(next); next = next->nextblk; } while (!TESTBUSY(next->nextblk)); blk->nextblk = SETBUSY(next); if (next >= arenaend) lastblk = blk; } /* get size we really need */ trusize = size+minhead; trusize = (trusize + ALIGNSZ - 1)/ALIGNSZ*ALIGNSZ; trusize = (trusize >= MINBLKSZ) ? trusize : MINBLKSZ; /* see if we have enough */ /* this isn't really the copy size, but I need a register */ cpysize = (char *)next - (char *)blk; if (cpysize >= trusize) { /* carve out the size we need */ register struct header *newblk; /* remainder */ if (cpysize - trusize >= MINBLKSZ) { /* carve out the right size block */ /* newblk will be the remainder */ newblk = (struct header *)((char *)blk + trusize); newblk->nextblk = next; blk->nextblk = SETBUSY(newblk); /* at this point, next is invalid */ ADDFREEQ(newblk); /* if blk was lastblk, make newblk lastblk */ if(blk==lastblk) lastblk = newblk; } newptr = ptr; } else { /* bite the bullet, and call malloc */ cpysize = (size > cpysize) ? cpysize : size; newptr = malloc(size); if (newptr == NULL) return NULL; (void)memcpy(newptr,ptr,(int)cpysize); free(ptr); } } return newptr;}/*LINTLIBRARY*//* calloc - allocate and clear memory block*/void *calloc(num, size)register unsigned num, size;{ register char *mp; num *= size; mp = malloc(num); if(mp == NULL) return(NULL); (void)memset(mp,0,(int)num); return(mp);}/* Mallopt - set options for allocation Mallopt provides for control over the allocation algorithm. The cmds available are: M_MXFAST Set maxfast to value. Maxfast is the size of the largest small, quickly allocated block. Maxfast may be set to 0 to disable fast allocation entirely. M_NLBLKS Set numlblks to value. Numlblks is the number of small blocks per holding block. Value must be greater than 0. M_GRAIN Set grain to value. The sizes of all blocks smaller than maxfast are considered to be rounded up to the nearest multiple of grain. The default value of grain is the smallest number of bytes which will allow alignment of any data type. Grain will be rounded up to a multiple of its default, and maxsize will be rounded up to a multiple of grain. Value must be greater than 0. M_KEEP Retain data in freed block until the next malloc, realloc, or calloc. Value is ignored. This option is provided only for compatibility with the old version of malloc, and is not recommended. returns - 0, upon successful completion 1, if malloc has previously been called or if value or cmd have illegal values*/mallopt(cmd, value)register int cmd; /* specifies option to set */register int value; /* value of option */{ /* disallow changes once a small block is allocated */ if (change) { return 1; } switch (cmd) { case M_MXFAST: if (value < 0) { return 1; } fastct = (value + grain - 1)/grain; maxfast = grain*fastct; break; case M_NLBLKS: if (value <= 1) { return 1; } numlblks = value; break; case M_GRAIN: if (value <= 0) { return 1; } /* round grain up to a multiple of ALIGNSZ */ grain = (value + ALIGNSZ - 1)/ALIGNSZ*ALIGNSZ; /* reduce fastct appropriately */ fastct = (fastct + grain - 1)/grain*grain; maxfast = grain*fastct; break; case M_KEEP: minhead = HEADSZ; break; default: return 1; } return 0;}/* mallinfo-provide information about space usage input - max; mallinfo will return the size of the largest block < max. output - a structure containing a description of of space usage, defined in malloc.h*/struct mallinfomallinfo(){ struct header *blk, *next; /* ptr to ordinary blocks */ struct holdblk *hblk; /* ptr to holding blocks */ struct mallinfo inf; /* return value */ register i; /* the ubiquitous counter */ int size; /* size of a block */ int fsp; /* free space in 1 hold block */ (void)memset (&inf, 0, sizeof(struct mallinfo)); blk = CLRBUSY(arena[1].nextblk); /* return total space used */ inf.arena = (char *)arenaend - (char *)blk; /* loop through arena, counting # of blocks, and and space used by blocks */ next = CLRBUSY(blk->nextblk); while (next != &(arena[1])) { inf.ordblks++; size = (char *)next - (char *)blk; if (TESTBUSY(blk->nextblk)) { inf.uordblks += size; inf.keepcost += HEADSZ-MINHEAD; } else { inf.fordblks += size; } blk = next; next = CLRBUSY(blk->nextblk); } /* examine space in holding blks */ for (i=fastct; i>0; i--) { /* loop thru ea. chain */ hblk = holdhead[i]; size = hblk->blksz + sizeof(struct lblk) - sizeof(int); if (hblk != HGROUND) { /* do only if chain not empty */ do { /* loop thru 1 hold blk chain */ inf.hblks++; fsp = freespace(hblk); inf.fsmblks += fsp; inf.usmblks += numlblks*size - fsp; inf.smblks += numlblks; hblk = hblk->nexthblk; } while (hblk != holdhead[i]); } } inf.hblkhd = (inf.smblks/numlblks)*sizeof(struct holdblk); /* holding block were counted in ordblks, so subtract off */ inf.ordblks -= inf.hblks; inf.uordblks -= inf.hblkhd + inf.usmblks + inf.fsmblks; inf.keepcost -= inf.hblks*(HEADSZ - MINHEAD); return inf;}/* freespace - calc. how much space is used in the free small blocks in a given holding block input - hblk = given holding block returns space used in free small blocks of hblk*/freespace(holdblk) register struct holdblk *holdblk;{ register struct lblk *lblk; register int space = 0; register int size; register struct lblk *unused; lblk = CLRSMAL(holdblk->lfreeq); size = holdblk->blksz + sizeof(struct lblk) - sizeof(int); unused = CLRSMAL(holdblk->unused); /* follow free chain */ while ((lblk != LGROUND) && (lblk != unused)) { space += size; lblk = CLRSMAL(lblk->header.nextfree); } space += ((char *)holdblk + HOLDSZ(size)) - (char *)unused; return space;}#ifdef RSTALLOC/* rstalloc - reset alloc routines description - return allocated memory and reset allocation pointers. Warning - This is for debugging purposes only. It will return all memory allocated after the first call to malloc, even if some of it was fetched by a user's sbrk().*/rstalloc(){ struct header *temp; temp = arena; minhead = MINHEAD; grain = ALIGNSZ; numlblks = NUMLBLKS; fastct = FASTCT; maxfast = MAXFAST; change = 0; if(freeptr->nextfree == GROUND) return; brk(CLRBUSY(arena[1].nextblk)); freeptr->nextfree = GROUND;}#endif /*RSTALLOC*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -