clang-format
This commit is contained in:
@@ -37,7 +37,7 @@
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h> // for uintptr_t on non-OS/161 platforms
|
||||
#include <stdint.h> // for uintptr_t on non-OS/161 platforms
|
||||
#include <unistd.h>
|
||||
#include <err.h>
|
||||
#include <assert.h>
|
||||
@@ -74,33 +74,33 @@ struct mheader {
|
||||
#define MBLOCKSIZE 8
|
||||
#define MBLOCKSHIFT 3
|
||||
#define MMAGIC 2
|
||||
/*
|
||||
* 32-bit platform. size_t is 32 bits (4 bytes).
|
||||
* Block size is 8 bytes.
|
||||
*/
|
||||
unsigned mh_prevblock:29;
|
||||
unsigned mh_pad:1;
|
||||
unsigned mh_magic1:2;
|
||||
/*
|
||||
* 32-bit platform. size_t is 32 bits (4 bytes).
|
||||
* Block size is 8 bytes.
|
||||
*/
|
||||
unsigned mh_prevblock : 29;
|
||||
unsigned mh_pad : 1;
|
||||
unsigned mh_magic1 : 2;
|
||||
|
||||
unsigned mh_nextblock:29;
|
||||
unsigned mh_inuse:1;
|
||||
unsigned mh_magic2:2;
|
||||
unsigned mh_nextblock : 29;
|
||||
unsigned mh_inuse : 1;
|
||||
unsigned mh_magic2 : 2;
|
||||
|
||||
#elif defined(MALLOC64)
|
||||
#define MBLOCKSIZE 16
|
||||
#define MBLOCKSHIFT 4
|
||||
#define MMAGIC 6
|
||||
/*
|
||||
* 64-bit platform. size_t is 64 bits (8 bytes)
|
||||
* Block size is 16 bytes.
|
||||
*/
|
||||
unsigned mh_prevblock:60;
|
||||
unsigned mh_pad:1;
|
||||
unsigned mh_magic1:3;
|
||||
/*
|
||||
* 64-bit platform. size_t is 64 bits (8 bytes)
|
||||
* Block size is 16 bytes.
|
||||
*/
|
||||
unsigned mh_prevblock : 60;
|
||||
unsigned mh_pad : 1;
|
||||
unsigned mh_magic1 : 3;
|
||||
|
||||
unsigned mh_nextblock:60;
|
||||
unsigned mh_inuse:1;
|
||||
unsigned mh_magic2:3;
|
||||
unsigned mh_nextblock : 60;
|
||||
unsigned mh_inuse : 1;
|
||||
unsigned mh_magic2 : 3;
|
||||
|
||||
#else
|
||||
#error "please fix me"
|
||||
@@ -122,17 +122,17 @@ struct mheader {
|
||||
* (value should include the header size)
|
||||
*/
|
||||
|
||||
#define M_NEXTOFF(mh) ((size_t)(((size_t)((mh)->mh_nextblock))<<MBLOCKSHIFT))
|
||||
#define M_PREVOFF(mh) ((size_t)(((size_t)((mh)->mh_prevblock))<<MBLOCKSHIFT))
|
||||
#define M_NEXT(mh) ((struct mheader *)(((char*)(mh))+M_NEXTOFF(mh)))
|
||||
#define M_PREV(mh) ((struct mheader *)(((char*)(mh))-M_PREVOFF(mh)))
|
||||
#define M_NEXTOFF(mh) ((size_t)(((size_t)((mh)->mh_nextblock)) << MBLOCKSHIFT))
|
||||
#define M_PREVOFF(mh) ((size_t)(((size_t)((mh)->mh_prevblock)) << MBLOCKSHIFT))
|
||||
#define M_NEXT(mh) ((struct mheader *)(((char *)(mh)) + M_NEXTOFF(mh)))
|
||||
#define M_PREV(mh) ((struct mheader *)(((char *)(mh)) - M_PREVOFF(mh)))
|
||||
|
||||
#define M_DATA(mh) ((void *)((mh)+1))
|
||||
#define M_SIZE(mh) (M_NEXTOFF(mh)-MBLOCKSIZE)
|
||||
#define M_DATA(mh) ((void *)((mh) + 1))
|
||||
#define M_SIZE(mh) (M_NEXTOFF(mh) - MBLOCKSIZE)
|
||||
|
||||
#define M_OK(mh) ((mh)->mh_magic1==MMAGIC && (mh)->mh_magic2==MMAGIC)
|
||||
#define M_OK(mh) ((mh)->mh_magic1 == MMAGIC && (mh)->mh_magic2 == MMAGIC)
|
||||
|
||||
#define M_MKFIELD(off) ((off)>>MBLOCKSHIFT)
|
||||
#define M_MKFIELD(off) ((off) >> MBLOCKSHIFT)
|
||||
|
||||
/*
|
||||
* System page size. In POSIX you're supposed to call
|
||||
@@ -157,68 +157,65 @@ static uintptr_t __heapbase, __heaptop;
|
||||
/*
|
||||
* Setup function.
|
||||
*/
|
||||
static
|
||||
void
|
||||
__malloc_init(void)
|
||||
{
|
||||
void *x;
|
||||
static void __malloc_init(void) {
|
||||
void *x;
|
||||
|
||||
/*
|
||||
* Check various assumed properties of the sizes.
|
||||
*/
|
||||
if (sizeof(struct mheader) != MBLOCKSIZE) {
|
||||
errx(1, "malloc: Internal error - MBLOCKSIZE wrong");
|
||||
}
|
||||
if ((MBLOCKSIZE & (MBLOCKSIZE-1))!=0) {
|
||||
errx(1, "malloc: Internal error - MBLOCKSIZE not power of 2");
|
||||
}
|
||||
if (1<<MBLOCKSHIFT != MBLOCKSIZE) {
|
||||
errx(1, "malloc: Internal error - MBLOCKSHIFT wrong");
|
||||
}
|
||||
/*
|
||||
* Check various assumed properties of the sizes.
|
||||
*/
|
||||
if (sizeof(struct mheader) != MBLOCKSIZE) {
|
||||
errx(1, "malloc: Internal error - MBLOCKSIZE wrong");
|
||||
}
|
||||
if ((MBLOCKSIZE & (MBLOCKSIZE - 1)) != 0) {
|
||||
errx(1, "malloc: Internal error - MBLOCKSIZE not power of 2");
|
||||
}
|
||||
if (1 << MBLOCKSHIFT != MBLOCKSIZE) {
|
||||
errx(1, "malloc: Internal error - MBLOCKSHIFT wrong");
|
||||
}
|
||||
|
||||
/* init should only be called once. */
|
||||
if (__heapbase!=0 || __heaptop!=0) {
|
||||
errx(1, "malloc: Internal error - bad init call");
|
||||
}
|
||||
/* init should only be called once. */
|
||||
if (__heapbase != 0 || __heaptop != 0) {
|
||||
errx(1, "malloc: Internal error - bad init call");
|
||||
}
|
||||
|
||||
/* Get the page size, if needed. */
|
||||
/* Get the page size, if needed. */
|
||||
#ifdef _SC_PAGESIZE
|
||||
__malloc_pagesize = sysconf(_SC_PAGESIZE);
|
||||
__malloc_pagesize = sysconf(_SC_PAGESIZE);
|
||||
#endif
|
||||
|
||||
/* Use sbrk to find the base of the heap. */
|
||||
x = sbrk(0);
|
||||
if (x==(void *)-1) {
|
||||
err(1, "malloc: initial sbrk failed");
|
||||
}
|
||||
if (x==(void *) 0) {
|
||||
errx(1, "malloc: Internal error - heap began at 0");
|
||||
}
|
||||
__heapbase = __heaptop = (uintptr_t)x;
|
||||
/* Use sbrk to find the base of the heap. */
|
||||
x = sbrk(0);
|
||||
if (x == (void *)-1) {
|
||||
err(1, "malloc: initial sbrk failed");
|
||||
}
|
||||
if (x == (void *)0) {
|
||||
errx(1, "malloc: Internal error - heap began at 0");
|
||||
}
|
||||
__heapbase = __heaptop = (uintptr_t)x;
|
||||
|
||||
/*
|
||||
* Make sure the heap base is aligned the way we want it.
|
||||
* (On OS/161, it will begin on a page boundary. But on
|
||||
* an arbitrary Unix, it may not be, as traditionally it
|
||||
* begins at _end.)
|
||||
*/
|
||||
/*
|
||||
* Make sure the heap base is aligned the way we want it.
|
||||
* (On OS/161, it will begin on a page boundary. But on
|
||||
* an arbitrary Unix, it may not be, as traditionally it
|
||||
* begins at _end.)
|
||||
*/
|
||||
|
||||
if (__heapbase % MBLOCKSIZE != 0) {
|
||||
size_t adjust = MBLOCKSIZE - (__heapbase % MBLOCKSIZE);
|
||||
x = sbrk(adjust);
|
||||
if (x==(void *)-1) {
|
||||
err(1, "malloc: sbrk failed aligning heap base");
|
||||
}
|
||||
if ((uintptr_t)x != __heapbase) {
|
||||
err(1, "malloc: heap base moved during init");
|
||||
}
|
||||
if (__heapbase % MBLOCKSIZE != 0) {
|
||||
size_t adjust = MBLOCKSIZE - (__heapbase % MBLOCKSIZE);
|
||||
x = sbrk(adjust);
|
||||
if (x == (void *)-1) {
|
||||
err(1, "malloc: sbrk failed aligning heap base");
|
||||
}
|
||||
if ((uintptr_t)x != __heapbase) {
|
||||
err(1, "malloc: heap base moved during init");
|
||||
}
|
||||
#ifdef MALLOCDEBUG
|
||||
warnx("malloc: adjusted heap base upwards by %lu bytes",
|
||||
(unsigned long) adjust);
|
||||
warnx("malloc: adjusted heap base upwards by %lu bytes",
|
||||
(unsigned long)adjust);
|
||||
#endif
|
||||
__heapbase += adjust;
|
||||
__heaptop = __heapbase;
|
||||
}
|
||||
__heapbase += adjust;
|
||||
__heaptop = __heapbase;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
@@ -228,45 +225,41 @@ __malloc_init(void)
|
||||
/*
|
||||
* Debugging print function to iterate and dump the entire heap.
|
||||
*/
|
||||
static
|
||||
void
|
||||
__malloc_dump(void)
|
||||
{
|
||||
struct mheader *mh;
|
||||
uintptr_t i;
|
||||
size_t rightprevblock;
|
||||
static void __malloc_dump(void) {
|
||||
struct mheader *mh;
|
||||
uintptr_t i;
|
||||
size_t rightprevblock;
|
||||
|
||||
warnx("heap: ************************************************");
|
||||
warnx("heap: ************************************************");
|
||||
|
||||
rightprevblock = 0;
|
||||
for (i=__heapbase; i<__heaptop; i += M_NEXTOFF(mh)) {
|
||||
mh = (struct mheader *) i;
|
||||
if (!M_OK(mh)) {
|
||||
errx(1, "malloc: Heap corrupt; header at 0x%lx"
|
||||
" has bad magic bits",
|
||||
(unsigned long) i);
|
||||
}
|
||||
if (mh->mh_prevblock != rightprevblock) {
|
||||
errx(1, "malloc: Heap corrupt; header at 0x%lx"
|
||||
" has bad previous-block size %lu "
|
||||
"(should be %lu)",
|
||||
(unsigned long) i,
|
||||
(unsigned long) mh->mh_prevblock << MBLOCKSHIFT,
|
||||
(unsigned long) rightprevblock << MBLOCKSHIFT);
|
||||
}
|
||||
rightprevblock = mh->mh_nextblock;
|
||||
rightprevblock = 0;
|
||||
for (i = __heapbase; i < __heaptop; i += M_NEXTOFF(mh)) {
|
||||
mh = (struct mheader *)i;
|
||||
if (!M_OK(mh)) {
|
||||
errx(1,
|
||||
"malloc: Heap corrupt; header at 0x%lx"
|
||||
" has bad magic bits",
|
||||
(unsigned long)i);
|
||||
}
|
||||
if (mh->mh_prevblock != rightprevblock) {
|
||||
errx(1,
|
||||
"malloc: Heap corrupt; header at 0x%lx"
|
||||
" has bad previous-block size %lu "
|
||||
"(should be %lu)",
|
||||
(unsigned long)i, (unsigned long)mh->mh_prevblock << MBLOCKSHIFT,
|
||||
(unsigned long)rightprevblock << MBLOCKSHIFT);
|
||||
}
|
||||
rightprevblock = mh->mh_nextblock;
|
||||
|
||||
warnx("heap: 0x%lx 0x%-6lx (next: 0x%lx) %s",
|
||||
(unsigned long) i + MBLOCKSIZE,
|
||||
(unsigned long) M_SIZE(mh),
|
||||
(unsigned long) (i+M_NEXTOFF(mh)),
|
||||
mh->mh_inuse ? "INUSE" : "FREE");
|
||||
}
|
||||
if (i!=__heaptop) {
|
||||
errx(1, "malloc: Heap corrupt; ran off end");
|
||||
}
|
||||
warnx("heap: 0x%lx 0x%-6lx (next: 0x%lx) %s", (unsigned long)i + MBLOCKSIZE,
|
||||
(unsigned long)M_SIZE(mh), (unsigned long)(i + M_NEXTOFF(mh)),
|
||||
mh->mh_inuse ? "INUSE" : "FREE");
|
||||
}
|
||||
if (i != __heaptop) {
|
||||
errx(1, "malloc: Heap corrupt; ran off end");
|
||||
}
|
||||
|
||||
warnx("heap: ************************************************");
|
||||
warnx("heap: ************************************************");
|
||||
}
|
||||
|
||||
#endif /* MALLOCDEBUG */
|
||||
@@ -277,25 +270,22 @@ __malloc_dump(void)
|
||||
* Get more memory (at the top of the heap) using sbrk, and
|
||||
* return a pointer to it.
|
||||
*/
|
||||
static
|
||||
void *
|
||||
__malloc_sbrk(size_t size)
|
||||
{
|
||||
void *x;
|
||||
static void *__malloc_sbrk(size_t size) {
|
||||
void *x;
|
||||
|
||||
x = sbrk(size);
|
||||
if (x == (void *)-1) {
|
||||
return NULL;
|
||||
}
|
||||
x = sbrk(size);
|
||||
if (x == (void *)-1) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((uintptr_t)x != __heaptop) {
|
||||
errx(1, "malloc: Internal error - "
|
||||
"heap top moved itself from 0x%lx to 0x%lx",
|
||||
(unsigned long) __heaptop,
|
||||
(unsigned long) (uintptr_t) x);
|
||||
}
|
||||
__heaptop += size;
|
||||
return x;
|
||||
if ((uintptr_t)x != __heaptop) {
|
||||
errx(1,
|
||||
"malloc: Internal error - "
|
||||
"heap top moved itself from 0x%lx to 0x%lx",
|
||||
(unsigned long)__heaptop, (unsigned long)(uintptr_t)x);
|
||||
}
|
||||
__heaptop += size;
|
||||
return x;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -306,177 +296,171 @@ __malloc_sbrk(size_t size)
|
||||
* Only split if the excess space is at least twice the blocksize -
|
||||
* one blocksize to hold a header and one for data.
|
||||
*/
|
||||
static
|
||||
void
|
||||
__malloc_split(struct mheader *mh, size_t size)
|
||||
{
|
||||
struct mheader *mhnext, *mhnew;
|
||||
size_t oldsize;
|
||||
static void __malloc_split(struct mheader *mh, size_t size) {
|
||||
struct mheader *mhnext, *mhnew;
|
||||
size_t oldsize;
|
||||
|
||||
if (size % MBLOCKSIZE != 0) {
|
||||
errx(1, "malloc: Internal error (size %lu passed to split)",
|
||||
(unsigned long) size);
|
||||
}
|
||||
if (size % MBLOCKSIZE != 0) {
|
||||
errx(1, "malloc: Internal error (size %lu passed to split)",
|
||||
(unsigned long)size);
|
||||
}
|
||||
|
||||
if (M_SIZE(mh) - size < 2*MBLOCKSIZE) {
|
||||
/* no room */
|
||||
return;
|
||||
}
|
||||
if (M_SIZE(mh) - size < 2 * MBLOCKSIZE) {
|
||||
/* no room */
|
||||
return;
|
||||
}
|
||||
|
||||
mhnext = M_NEXT(mh);
|
||||
mhnext = M_NEXT(mh);
|
||||
|
||||
oldsize = M_SIZE(mh);
|
||||
mh->mh_nextblock = M_MKFIELD(size + MBLOCKSIZE);
|
||||
oldsize = M_SIZE(mh);
|
||||
mh->mh_nextblock = M_MKFIELD(size + MBLOCKSIZE);
|
||||
|
||||
mhnew = M_NEXT(mh);
|
||||
if (mhnew==mhnext) {
|
||||
errx(1, "malloc: Internal error (split screwed up?)");
|
||||
}
|
||||
mhnew = M_NEXT(mh);
|
||||
if (mhnew == mhnext) {
|
||||
errx(1, "malloc: Internal error (split screwed up?)");
|
||||
}
|
||||
|
||||
mhnew->mh_prevblock = M_MKFIELD(size + MBLOCKSIZE);
|
||||
mhnew->mh_pad = 0;
|
||||
mhnew->mh_magic1 = MMAGIC;
|
||||
mhnew->mh_nextblock = M_MKFIELD(oldsize - size);
|
||||
mhnew->mh_inuse = 0;
|
||||
mhnew->mh_magic2 = MMAGIC;
|
||||
mhnew->mh_prevblock = M_MKFIELD(size + MBLOCKSIZE);
|
||||
mhnew->mh_pad = 0;
|
||||
mhnew->mh_magic1 = MMAGIC;
|
||||
mhnew->mh_nextblock = M_MKFIELD(oldsize - size);
|
||||
mhnew->mh_inuse = 0;
|
||||
mhnew->mh_magic2 = MMAGIC;
|
||||
|
||||
if (mhnext != (struct mheader *) __heaptop) {
|
||||
mhnext->mh_prevblock = mhnew->mh_nextblock;
|
||||
}
|
||||
if (mhnext != (struct mheader *)__heaptop) {
|
||||
mhnext->mh_prevblock = mhnew->mh_nextblock;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* malloc itself.
|
||||
*/
|
||||
void *
|
||||
malloc(size_t size)
|
||||
{
|
||||
struct mheader *mh;
|
||||
uintptr_t i;
|
||||
size_t rightprevblock;
|
||||
size_t morespace;
|
||||
void *p;
|
||||
void *malloc(size_t size) {
|
||||
struct mheader *mh;
|
||||
uintptr_t i;
|
||||
size_t rightprevblock;
|
||||
size_t morespace;
|
||||
void *p;
|
||||
|
||||
if (__heapbase==0) {
|
||||
__malloc_init();
|
||||
}
|
||||
if (__heapbase==0 || __heaptop==0 || __heapbase > __heaptop) {
|
||||
warnx("malloc: Internal error - local data corrupt");
|
||||
errx(1, "malloc: heapbase 0x%lx; heaptop 0x%lx",
|
||||
(unsigned long) __heapbase, (unsigned long) __heaptop);
|
||||
}
|
||||
if (__heapbase == 0) {
|
||||
__malloc_init();
|
||||
}
|
||||
if (__heapbase == 0 || __heaptop == 0 || __heapbase > __heaptop) {
|
||||
warnx("malloc: Internal error - local data corrupt");
|
||||
errx(1, "malloc: heapbase 0x%lx; heaptop 0x%lx", (unsigned long)__heapbase,
|
||||
(unsigned long)__heaptop);
|
||||
}
|
||||
|
||||
#ifdef MALLOCDEBUG
|
||||
warnx("malloc: about to allocate %lu (0x%lx) bytes",
|
||||
(unsigned long) size, (unsigned long) size);
|
||||
__malloc_dump();
|
||||
warnx("malloc: about to allocate %lu (0x%lx) bytes", (unsigned long)size,
|
||||
(unsigned long)size);
|
||||
__malloc_dump();
|
||||
#endif
|
||||
|
||||
/* Round size up to an integral number of blocks. */
|
||||
size = ((size + MBLOCKSIZE - 1) & ~(size_t)(MBLOCKSIZE-1));
|
||||
/* Round size up to an integral number of blocks. */
|
||||
size = ((size + MBLOCKSIZE - 1) & ~(size_t)(MBLOCKSIZE - 1));
|
||||
|
||||
/*
|
||||
* First-fit search algorithm for available blocks.
|
||||
* Check to make sure the next/previous sizes all agree.
|
||||
*/
|
||||
rightprevblock = 0;
|
||||
mh = NULL;
|
||||
for (i=__heapbase; i<__heaptop; i += M_NEXTOFF(mh)) {
|
||||
mh = (struct mheader *) i;
|
||||
if (!M_OK(mh)) {
|
||||
errx(1, "malloc: Heap corrupt; header at 0x%lx"
|
||||
" has bad magic bits",
|
||||
(unsigned long) i);
|
||||
}
|
||||
if (mh->mh_prevblock != rightprevblock) {
|
||||
errx(1, "malloc: Heap corrupt; header at 0x%lx"
|
||||
" has bad previous-block size %lu "
|
||||
"(should be %lu)",
|
||||
(unsigned long) i,
|
||||
(unsigned long) mh->mh_prevblock << MBLOCKSHIFT,
|
||||
(unsigned long) rightprevblock << MBLOCKSHIFT);
|
||||
}
|
||||
rightprevblock = mh->mh_nextblock;
|
||||
/*
|
||||
* First-fit search algorithm for available blocks.
|
||||
* Check to make sure the next/previous sizes all agree.
|
||||
*/
|
||||
rightprevblock = 0;
|
||||
mh = NULL;
|
||||
for (i = __heapbase; i < __heaptop; i += M_NEXTOFF(mh)) {
|
||||
mh = (struct mheader *)i;
|
||||
if (!M_OK(mh)) {
|
||||
errx(1,
|
||||
"malloc: Heap corrupt; header at 0x%lx"
|
||||
" has bad magic bits",
|
||||
(unsigned long)i);
|
||||
}
|
||||
if (mh->mh_prevblock != rightprevblock) {
|
||||
errx(1,
|
||||
"malloc: Heap corrupt; header at 0x%lx"
|
||||
" has bad previous-block size %lu "
|
||||
"(should be %lu)",
|
||||
(unsigned long)i, (unsigned long)mh->mh_prevblock << MBLOCKSHIFT,
|
||||
(unsigned long)rightprevblock << MBLOCKSHIFT);
|
||||
}
|
||||
rightprevblock = mh->mh_nextblock;
|
||||
|
||||
/* Can't allocate a block that's in use. */
|
||||
if (mh->mh_inuse) {
|
||||
continue;
|
||||
}
|
||||
/* Can't allocate a block that's in use. */
|
||||
if (mh->mh_inuse) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Can't allocate a block that isn't big enough. */
|
||||
if (M_SIZE(mh) < size) {
|
||||
continue;
|
||||
}
|
||||
/* Can't allocate a block that isn't big enough. */
|
||||
if (M_SIZE(mh) < size) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Try splitting block. */
|
||||
__malloc_split(mh, size);
|
||||
/* Try splitting block. */
|
||||
__malloc_split(mh, size);
|
||||
|
||||
/*
|
||||
* Now, allocate.
|
||||
*/
|
||||
mh->mh_inuse = 1;
|
||||
/*
|
||||
* Now, allocate.
|
||||
*/
|
||||
mh->mh_inuse = 1;
|
||||
|
||||
#ifdef MALLOCDEBUG
|
||||
warnx("malloc: allocating at %p", M_DATA(mh));
|
||||
__malloc_dump();
|
||||
warnx("malloc: allocating at %p", M_DATA(mh));
|
||||
__malloc_dump();
|
||||
#endif
|
||||
return M_DATA(mh);
|
||||
}
|
||||
if (i!=__heaptop) {
|
||||
errx(1, "malloc: Heap corrupt; ran off end");
|
||||
}
|
||||
return M_DATA(mh);
|
||||
}
|
||||
if (i != __heaptop) {
|
||||
errx(1, "malloc: Heap corrupt; ran off end");
|
||||
}
|
||||
|
||||
/*
|
||||
* Didn't find anything. Expand the heap.
|
||||
*
|
||||
* If the heap is nonempty and the top block (the one mh is
|
||||
* left pointing to after the above loop) is free, we can
|
||||
* expand it. Otherwise we need a new block.
|
||||
*/
|
||||
if (mh != NULL && !mh->mh_inuse) {
|
||||
assert(size > M_SIZE(mh));
|
||||
morespace = size - M_SIZE(mh);
|
||||
}
|
||||
else {
|
||||
morespace = MBLOCKSIZE + size;
|
||||
}
|
||||
/*
|
||||
* Didn't find anything. Expand the heap.
|
||||
*
|
||||
* If the heap is nonempty and the top block (the one mh is
|
||||
* left pointing to after the above loop) is free, we can
|
||||
* expand it. Otherwise we need a new block.
|
||||
*/
|
||||
if (mh != NULL && !mh->mh_inuse) {
|
||||
assert(size > M_SIZE(mh));
|
||||
morespace = size - M_SIZE(mh);
|
||||
} else {
|
||||
morespace = MBLOCKSIZE + size;
|
||||
}
|
||||
|
||||
/* Round the amount of space we ask for up to a whole page. */
|
||||
morespace = PAGE_SIZE * ((morespace + PAGE_SIZE - 1) / PAGE_SIZE);
|
||||
/* Round the amount of space we ask for up to a whole page. */
|
||||
morespace = PAGE_SIZE * ((morespace + PAGE_SIZE - 1) / PAGE_SIZE);
|
||||
|
||||
p = __malloc_sbrk(morespace);
|
||||
if (p == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
p = __malloc_sbrk(morespace);
|
||||
if (p == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (mh != NULL && !mh->mh_inuse) {
|
||||
/* update old header */
|
||||
mh->mh_nextblock = M_MKFIELD(M_NEXTOFF(mh) + morespace);
|
||||
mh->mh_inuse = 1;
|
||||
}
|
||||
else {
|
||||
/* fill out new header */
|
||||
mh = p;
|
||||
mh->mh_prevblock = rightprevblock;
|
||||
mh->mh_magic1 = MMAGIC;
|
||||
mh->mh_magic2 = MMAGIC;
|
||||
mh->mh_pad = 0;
|
||||
mh->mh_inuse = 1;
|
||||
mh->mh_nextblock = M_MKFIELD(morespace);
|
||||
}
|
||||
if (mh != NULL && !mh->mh_inuse) {
|
||||
/* update old header */
|
||||
mh->mh_nextblock = M_MKFIELD(M_NEXTOFF(mh) + morespace);
|
||||
mh->mh_inuse = 1;
|
||||
} else {
|
||||
/* fill out new header */
|
||||
mh = p;
|
||||
mh->mh_prevblock = rightprevblock;
|
||||
mh->mh_magic1 = MMAGIC;
|
||||
mh->mh_magic2 = MMAGIC;
|
||||
mh->mh_pad = 0;
|
||||
mh->mh_inuse = 1;
|
||||
mh->mh_nextblock = M_MKFIELD(morespace);
|
||||
}
|
||||
|
||||
/*
|
||||
* Either way, try splitting the block we got as because of
|
||||
* the page rounding it might be quite a bit bigger than we
|
||||
* needed.
|
||||
*/
|
||||
__malloc_split(mh, size);
|
||||
/*
|
||||
* Either way, try splitting the block we got as because of
|
||||
* the page rounding it might be quite a bit bigger than we
|
||||
* needed.
|
||||
*/
|
||||
__malloc_split(mh, size);
|
||||
|
||||
#ifdef MALLOCDEBUG
|
||||
warnx("malloc: allocating at %p", M_DATA(mh));
|
||||
__malloc_dump();
|
||||
warnx("malloc: allocating at %p", M_DATA(mh));
|
||||
__malloc_dump();
|
||||
#endif
|
||||
return M_DATA(mh);
|
||||
return M_DATA(mh);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
@@ -485,107 +469,98 @@ malloc(size_t size)
|
||||
* Clear a range of memory with 0xdeadbeef.
|
||||
* ptr must be suitably aligned.
|
||||
*/
|
||||
static
|
||||
void
|
||||
__malloc_deadbeef(void *ptr, size_t size)
|
||||
{
|
||||
uint32_t *x = ptr;
|
||||
size_t i, n = size/sizeof(uint32_t);
|
||||
for (i=0; i<n; i++) {
|
||||
x[i] = 0xdeadbeef;
|
||||
}
|
||||
static void __malloc_deadbeef(void *ptr, size_t size) {
|
||||
uint32_t *x = ptr;
|
||||
size_t i, n = size / sizeof(uint32_t);
|
||||
for (i = 0; i < n; i++) {
|
||||
x[i] = 0xdeadbeef;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempt to merge two adjacent blocks (mh below mhnext).
|
||||
*/
|
||||
static
|
||||
void
|
||||
__malloc_trymerge(struct mheader *mh, struct mheader *mhnext)
|
||||
{
|
||||
struct mheader *mhnextnext;
|
||||
static void __malloc_trymerge(struct mheader *mh, struct mheader *mhnext) {
|
||||
struct mheader *mhnextnext;
|
||||
|
||||
if (mh->mh_nextblock != mhnext->mh_prevblock) {
|
||||
errx(1, "free: Heap corrupt (%p and %p inconsistent)",
|
||||
mh, mhnext);
|
||||
}
|
||||
if (mh->mh_inuse || mhnext->mh_inuse) {
|
||||
/* can't merge */
|
||||
return;
|
||||
}
|
||||
if (mh->mh_nextblock != mhnext->mh_prevblock) {
|
||||
errx(1, "free: Heap corrupt (%p and %p inconsistent)", mh, mhnext);
|
||||
}
|
||||
if (mh->mh_inuse || mhnext->mh_inuse) {
|
||||
/* can't merge */
|
||||
return;
|
||||
}
|
||||
|
||||
mhnextnext = M_NEXT(mhnext);
|
||||
mhnextnext = M_NEXT(mhnext);
|
||||
|
||||
mh->mh_nextblock = M_MKFIELD(MBLOCKSIZE + M_SIZE(mh) +
|
||||
MBLOCKSIZE + M_SIZE(mhnext));
|
||||
mh->mh_nextblock =
|
||||
M_MKFIELD(MBLOCKSIZE + M_SIZE(mh) + MBLOCKSIZE + M_SIZE(mhnext));
|
||||
|
||||
if (mhnextnext != (struct mheader *)__heaptop) {
|
||||
mhnextnext->mh_prevblock = mh->mh_nextblock;
|
||||
}
|
||||
if (mhnextnext != (struct mheader *)__heaptop) {
|
||||
mhnextnext->mh_prevblock = mh->mh_nextblock;
|
||||
}
|
||||
|
||||
/* Deadbeef out the memory used by the now-obsolete header */
|
||||
__malloc_deadbeef(mhnext, sizeof(struct mheader));
|
||||
/* Deadbeef out the memory used by the now-obsolete header */
|
||||
__malloc_deadbeef(mhnext, sizeof(struct mheader));
|
||||
}
|
||||
|
||||
/*
|
||||
* The actual free() implementation.
|
||||
*/
|
||||
void
|
||||
free(void *x)
|
||||
{
|
||||
struct mheader *mh, *mhnext, *mhprev;
|
||||
void free(void *x) {
|
||||
struct mheader *mh, *mhnext, *mhprev;
|
||||
|
||||
if (x==NULL) {
|
||||
/* safest practice */
|
||||
return;
|
||||
}
|
||||
if (x == NULL) {
|
||||
/* safest practice */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Consistency check. */
|
||||
if (__heapbase==0 || __heaptop==0 || __heapbase > __heaptop) {
|
||||
warnx("free: Internal error - local data corrupt");
|
||||
errx(1, "free: heapbase 0x%lx; heaptop 0x%lx",
|
||||
(unsigned long) __heapbase, (unsigned long) __heaptop);
|
||||
}
|
||||
/* Consistency check. */
|
||||
if (__heapbase == 0 || __heaptop == 0 || __heapbase > __heaptop) {
|
||||
warnx("free: Internal error - local data corrupt");
|
||||
errx(1, "free: heapbase 0x%lx; heaptop 0x%lx", (unsigned long)__heapbase,
|
||||
(unsigned long)__heaptop);
|
||||
}
|
||||
|
||||
/* Don't allow freeing pointers that aren't on the heap. */
|
||||
if ((uintptr_t)x < __heapbase || (uintptr_t)x >= __heaptop) {
|
||||
errx(1, "free: Invalid pointer %p freed (out of range)", x);
|
||||
}
|
||||
/* Don't allow freeing pointers that aren't on the heap. */
|
||||
if ((uintptr_t)x < __heapbase || (uintptr_t)x >= __heaptop) {
|
||||
errx(1, "free: Invalid pointer %p freed (out of range)", x);
|
||||
}
|
||||
|
||||
#ifdef MALLOCDEBUG
|
||||
warnx("free: about to free %p", x);
|
||||
__malloc_dump();
|
||||
warnx("free: about to free %p", x);
|
||||
__malloc_dump();
|
||||
#endif
|
||||
|
||||
mh = ((struct mheader *)x)-1;
|
||||
if (!M_OK(mh)) {
|
||||
errx(1, "free: Invalid pointer %p freed (corrupt header)", x);
|
||||
}
|
||||
mh = ((struct mheader *)x) - 1;
|
||||
if (!M_OK(mh)) {
|
||||
errx(1, "free: Invalid pointer %p freed (corrupt header)", x);
|
||||
}
|
||||
|
||||
if (!mh->mh_inuse) {
|
||||
errx(1, "free: Invalid pointer %p freed (already free)", x);
|
||||
}
|
||||
if (!mh->mh_inuse) {
|
||||
errx(1, "free: Invalid pointer %p freed (already free)", x);
|
||||
}
|
||||
|
||||
/* mark it free */
|
||||
mh->mh_inuse = 0;
|
||||
/* mark it free */
|
||||
mh->mh_inuse = 0;
|
||||
|
||||
/* wipe it */
|
||||
__malloc_deadbeef(M_DATA(mh), M_SIZE(mh));
|
||||
/* wipe it */
|
||||
__malloc_deadbeef(M_DATA(mh), M_SIZE(mh));
|
||||
|
||||
/* Try merging with the block above (but not if we're at the top) */
|
||||
mhnext = M_NEXT(mh);
|
||||
if (mhnext != (struct mheader *)__heaptop) {
|
||||
__malloc_trymerge(mh, mhnext);
|
||||
}
|
||||
/* Try merging with the block above (but not if we're at the top) */
|
||||
mhnext = M_NEXT(mh);
|
||||
if (mhnext != (struct mheader *)__heaptop) {
|
||||
__malloc_trymerge(mh, mhnext);
|
||||
}
|
||||
|
||||
/* Try merging with the block below (but not if we're at the bottom) */
|
||||
if (mh != (struct mheader *)__heapbase) {
|
||||
mhprev = M_PREV(mh);
|
||||
__malloc_trymerge(mhprev, mh);
|
||||
}
|
||||
/* Try merging with the block below (but not if we're at the bottom) */
|
||||
if (mh != (struct mheader *)__heapbase) {
|
||||
mhprev = M_PREV(mh);
|
||||
__malloc_trymerge(mhprev, mh);
|
||||
}
|
||||
|
||||
#ifdef MALLOCDEBUG
|
||||
warnx("free: freed %p", x);
|
||||
__malloc_dump();
|
||||
warnx("free: freed %p", x);
|
||||
__malloc_dump();
|
||||
#endif
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user