📄 malloc.c
字号:
#endif /* BSD4_2 */}static voidgetpool (){ register int nu; register char *cp = sbrk (0); if ((int) cp & 0x3ff) /* land on 1K boundaries */ sbrk (1024 - ((int) cp & 0x3ff)); /* Record address of start of space allocated by malloc. */ if (_malloc_base == 0) _malloc_base = cp; /* Get 2k of storage */ cp = sbrk (04000); if (cp == (char *) -1) return; /* Divide it into an initial 8-word block plus one block of size 2**nu for nu = 3 ... 10. */ CHAIN (cp) = nextf[0]; nextf[0] = (struct mhead *) cp; ((struct mhead *) cp) -> mh_alloc = ISFREE; ((struct mhead *) cp) -> mh_index = 0; cp += 8; for (nu = 0; nu < 7; nu++) { CHAIN (cp) = nextf[nu]; nextf[nu] = (struct mhead *) cp; ((struct mhead *) cp) -> mh_alloc = ISFREE; ((struct mhead *) cp) -> mh_index = nu; cp += 8 << nu; }}char *malloc (n) /* get a block */ unsigned n;{ register struct mhead *p; register unsigned int nbytes; register int nunits = 0; /* Figure out how many bytes are required, rounding up to the nearest multiple of 4, then figure out which nextf[] area to use */ nbytes = (n + sizeof *p + EXTRA + 3) & ~3; { register unsigned int shiftr = (nbytes - 1) >> 2; while (shiftr >>= 1) nunits++; } /* In case this is reentrant use of malloc from signal handler, pick a block size that no other malloc level is currently trying to allocate. That's the easiest harmless way not to interfere with the other level of execution. */ while (busy[nunits]) nunits++; busy[nunits] = 1; /* If there are no blocks of the appropriate size, go get some */ /* COULD SPLIT UP A LARGER BLOCK HERE ... ACT */ if (nextf[nunits] == 0) morecore (nunits); /* Get one block off the list, and set the new list head */ if ((p = nextf[nunits]) == 0) { busy[nunits] = 0; return 0; } nextf[nunits] = CHAIN (p); busy[nunits] = 0; /* Check for free block clobbered */ /* If not for this check, we would gobble a clobbered free chain ptr */ /* and bomb out on the NEXT allocate of this size block */ if (p -> mh_alloc != ISFREE || p -> mh_index != nunits)#ifdef rcheck botch ("block on free list clobbered");#else /* not rcheck */ abort ();#endif /* not rcheck */ /* Fill in the info, and if range checking, set up the magic numbers */ p -> mh_alloc = ISALLOC;#ifdef rcheck p -> mh_nbytes = n; p -> mh_magic4 = MAGIC4; { register char *m = (char *) (p + 1) + n; *m++ = MAGIC1, *m++ = MAGIC1, *m++ = MAGIC1, *m = MAGIC1; }#else /* not rcheck */ p -> mh_size = n;#endif /* not rcheck */#ifdef MSTATS nmalloc[nunits]++; nmal++;#endif /* MSTATS */ return (char *) (p + 1);}voidfree (mem) char *mem;{ register struct mhead *p; { register char *ap = mem; if (ap == 0) return; p = (struct mhead *) ap - 1; if (p -> mh_alloc == ISMEMALIGN) {#ifdef rcheck ap -= p->mh_nbytes;#endif p = (struct mhead *) ap - 1; }#ifndef rcheck if (p -> mh_alloc != ISALLOC) abort ();#else /* rcheck */ if (p -> mh_alloc != ISALLOC) { if (p -> mh_alloc == ISFREE) botch ("free: Called with already freed block argument\n"); else botch ("free: Called with bad argument\n"); } ASSERT (p -> mh_magic4 == MAGIC4); ap += p -> mh_nbytes; ASSERT (*ap++ == MAGIC1); ASSERT (*ap++ == MAGIC1); ASSERT (*ap++ == MAGIC1); ASSERT (*ap == MAGIC1);#endif /* rcheck */ } { register int nunits = p -> mh_index; ASSERT (nunits <= 29); p -> mh_alloc = ISFREE; /* Protect against signal handlers calling malloc. */ busy[nunits] = 1; /* Put this block on the free list. */ CHAIN (p) = nextf[nunits]; nextf[nunits] = p; busy[nunits] = 0;#ifdef MSTATS nmalloc[nunits]--; nfre++;#endif /* MSTATS */ }}char *realloc (mem, n) char *mem; register unsigned n;{ register struct mhead *p; register unsigned int tocopy; register unsigned int nbytes; register int nunits; if ((p = (struct mhead *) mem) == 0) return malloc (n); p--; nunits = p -> mh_index; ASSERT (p -> mh_alloc == ISALLOC);#ifdef rcheck ASSERT (p -> mh_magic4 == MAGIC4); { register char *m = mem + (tocopy = p -> mh_nbytes); ASSERT (*m++ == MAGIC1); ASSERT (*m++ == MAGIC1); ASSERT (*m++ == MAGIC1); ASSERT (*m == MAGIC1); }#else /* not rcheck */ if (p -> mh_index >= 13) tocopy = (1 << (p -> mh_index + 3)) - sizeof *p; else tocopy = p -> mh_size;#endif /* not rcheck */ /* See if desired size rounds to same power of 2 as actual size. */ nbytes = (n + sizeof *p + EXTRA + 7) & ~7; /* If ok, use the same block, just marking its size as changed. */ if (nbytes > (4 << nunits) && nbytes <= (8 << nunits)) {#ifdef rcheck register char *m = mem + tocopy; *m++ = 0; *m++ = 0; *m++ = 0; *m++ = 0; p-> mh_nbytes = n; m = mem + n; *m++ = MAGIC1; *m++ = MAGIC1; *m++ = MAGIC1; *m++ = MAGIC1;#else /* not rcheck */ p -> mh_size = n;#endif /* not rcheck */ return mem; } if (n < tocopy) tocopy = n; { register char *new; if ((new = malloc (n)) == 0) return 0; bcopy (mem, new, tocopy); free (mem); return new; }}char *memalign (alignment, size) unsigned alignment, size;{ register char *ptr = malloc (size + alignment); register char *aligned; register struct mhead *p; if (ptr == 0) return 0; /* If entire block has the desired alignment, just accept it. */ if (((int) ptr & (alignment - 1)) == 0) return ptr; /* Otherwise, get address of byte in the block that has that alignment. */ aligned = (char *) (((int) ptr + alignment - 1) & -alignment); /* Store a suitable indication of how to free the block, so that free can find the true beginning of it. */ p = (struct mhead *) aligned - 1; p -> mh_size = aligned - ptr; p -> mh_alloc = ISMEMALIGN; return aligned;}#if !defined (HPUX) && !defined (Multimax) && !defined (Multimax32k)/* This runs into trouble with getpagesize on HPUX, and Multimax machines. Patching out seems cleaner than the ugly fix needed. */char *valloc (size){ return memalign (getpagesize (), size);}#endif /* !HPUX && !Multimax && !Multimax32k */#ifdef MSTATS/* Return statistics describing allocation of blocks of size 2**n. */struct mstats_value { int blocksize; int nfree; int nused; };struct mstats_valuemalloc_stats (size) int size;{ struct mstats_value v; register int i; register struct mhead *p; v.nfree = 0; if (size < 0 || size >= 30) { v.blocksize = 0; v.nused = 0; return v; } v.blocksize = 1 << (size + 3); v.nused = nmalloc[size]; for (p = nextf[size]; p; p = CHAIN (p)) v.nfree++; return v;}#endif /* MSTATS *//* * This function returns the total number of bytes that the process * will be allowed to allocate via the sbrk(2) system call. On * BSD systems this is the total space allocatable to stack and * data. On USG systems this is the data space only. */#if !defined (HAVE_RESOURCE)extern long ulimit ();static voidget_lim_data (){ lim_data = ulimit (3, 0); lim_data -= (long) data_space_start;}#else /* HAVE_RESOURCE */static voidget_lim_data (){ struct rlimit XXrlimit; getrlimit (RLIMIT_DATA, &XXrlimit);#ifdef RLIM_INFINITY lim_data = XXrlimit.rlim_cur & RLIM_INFINITY; /* soft limit */#else lim_data = XXrlimit.rlim_cur; /* soft limit */#endif}#endif /* HAVE_RESOURCE */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -