📄 emacsmalloc.c
字号:
nbytes = (n + ((sizeof *p + 7) & ~7) + EXTRA + 7) & ~7; { 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; { /* Get the location n after the beginning of the user's space. */ register char *m = (char *) p + ((sizeof *p + 7) & ~7) + 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 + ((sizeof *p + 7) & ~7);}free (mem) char *mem;{ register struct mhead *p; { register char *ap = mem; if (ap == 0) return; p = (struct mhead *) (ap - ((sizeof *p + 7) & ~7)); if (p -> mh_alloc == ISMEMALIGN) { ap -= p->mh_size; p = (struct mhead *) (ap - ((sizeof *p + 7) & ~7)); }#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 (mem == 0) return malloc (n); p = (struct mhead *) (mem - ((sizeof *p + 7) & ~7)); 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 + 7) & ~7); 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 + 7) & ~7) + 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; }}/* This is in case something linked with Emacs calls calloc. */char *calloc (num, size) unsigned num, size;{ register char *mem; num *= size; mem = malloc (num); if (mem != 0) bzero (mem, num); return mem;}#ifndef VMSchar *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 - ((7 + sizeof (struct mhead)) & ~7)); p -> mh_size = aligned - ptr; p -> mh_alloc = ISMEMALIGN; return aligned;}#ifndef HPUX/* This runs into trouble with getpagesize on HPUX. Patching out seems cleaner than the ugly fix needed. */char *valloc (size){ return memalign (getpagesize (), size);}#endif /* not HPUX */#endif /* not VMS */#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;}intmalloc_mem_used (){ int i; int size_used; size_used = 0; for (i = 0; i < 30; i++) { int allocation_size = 1 << (i + 3); struct mhead *p; size_used += nmalloc[i] * allocation_size; } return size_used;}int malloc_mem_free (){ int i; int size_unused; size_unused = 0; for (i = 0; i < 30; i++) { int allocation_size = 1 << (i + 3); struct mhead *p; for (p = nextf[i]; p ; p = CHAIN (p)) size_unused += allocation_size; } return size_unused;}#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. */#ifdef USGget_lim_data (){ extern long ulimit (); #ifdef ULIMIT_BREAK_VALUE lim_data = ULIMIT_BREAK_VALUE;#else lim_data = ulimit (3, 0);#endif lim_data -= (long) data_space_start;}#else /* not USG */#if defined (BSD4_1) || defined (VMS)get_lim_data (){ lim_data = vlimit (LIM_DATA, -1);}#else /* not BSD4_1 and not VMS */get_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 /* not BSD4_1 and not VMS */#endif /* not USG */#ifdef VMS/* There is a problem when dumping and restoring things on VMS. Calls * to SBRK don't necessarily result in contiguous allocation. Dumping * doesn't work when it isn't. Therefore, we make the initial * allocation contiguous by allocating a big chunk, and do SBRKs from * there. Once Emacs has dumped there is no reason to continue * contiguous allocation, malloc doesn't depend on it. * * There is a further problem of using brk and sbrk while using VMS C * run time library routines malloc, calloc, etc. The documentation * says that this is a no-no, although I'm not sure why this would be * a problem. In any case, we remove the necessity to call brk and * sbrk, by calling calloc (to assure zero filled data) rather than * sbrk. * * VMS_ALLOCATION_SIZE is the size of the allocation array. This * should be larger than the malloc size before dumping. Making this * too large will result in the startup procedure slowing down since * it will require more space and time to map it in. * * The value for VMS_ALLOCATION_SIZE in the following define was determined * by running emacs linked (and a large allocation) with the debugger and * looking to see how much storage was used. The allocation was 201 pages, * so I rounded it up to a power of two. */#ifndef VMS_ALLOCATION_SIZE#define VMS_ALLOCATION_SIZE (512*256)#endif/* Use VMS RTL definitions */#undef sbrk#undef brk#undef mallocint vms_out_initial = 0;char vms_initial_buffer[VMS_ALLOCATION_SIZE];static char *vms_current_brk = &vms_initial_buffer;static char *vms_end_brk = &vms_initial_buffer[VMS_ALLOCATION_SIZE-1];#include <stdio.h>char *sys_sbrk (incr) int incr;{ char *sbrk(), *temp, *ptr; if (vms_out_initial) { /* out of initial allocation... */ if (!(temp = malloc (incr))) temp = (char *) -1; } else { /* otherwise, go out of our area */ ptr = vms_current_brk + incr; /* new current_brk */ if (ptr <= vms_end_brk) { temp = vms_current_brk; vms_current_brk = ptr; } else { vms_out_initial = 1; /* mark as out of initial allocation */ if (!(temp = malloc (incr))) temp = (char *) -1; } } return temp;}#endif /* VMS */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -