?? malloc.c
字號(hào):
Both the beginning of the header and the beginning of the
block should be on an eight byte boundary. */
#ifdef SUNOS_LOCALTIME_BUG
if (n < 16)
n = 16;
#endif
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;
DbgPrint("Malloc failing allocation of %d bytes\n", n);
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;
memcpy(new, mem, 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)
memset(mem, 0, num);
return mem;
}
/* This is in case something linked with Emacs calls cfree. */
cfree (mem)
char *mem;
{
return free (mem);
}
#ifndef VMS
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 - ((7 + sizeof (struct mhead)) & ~7));
p -> mh_size = aligned - ptr;
p -> mh_alloc = ISMEMALIGN;
return aligned;
}
#ifndef HPUX
/* This runs into trouble with getpagsz on HPUX.
Patching out seems cleaner than the ugly fix needed. */
char *
valloc (size)
{
return memalign (getpagsz (), 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_value
malloc_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;
}
int
malloc_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 WINDOWSNT
get_lim_data ()
{
lim_data = 0x7fffffff; // this is the MAX...
}
#else /* !WINDOWSNT */
#ifdef USG
get_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 */
#endif /* !WINDOWSNT */
#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 malloc
int 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 = (char*) 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 = (char*) malloc (incr)))
temp = (char *) -1;
}
}
return temp;
}
#endif /* VMS */
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -