/*
- * This module derived from code donated to the FreeBSD Project by
+ * This module derived from code donated to the FreeBSD Project by
* Matthew Dillon <dillon@backplane.com>
*
* Copyright (c) 1998 The FreeBSD Project
__FBSDID("$FreeBSD$");
/*
- * LIB/MEMORY/ZALLOC.C - self contained low-overhead memory pool/allocation
+ * LIB/MEMORY/ZALLOC.C - self contained low-overhead memory pool/allocation
* subsystem
*
- * This subsystem implements memory pools and memory allocation
+ * This subsystem implements memory pools and memory allocation
* routines.
*
* Pools are managed via a linked list of 'free' areas. Allocating
* to allocate the entire pool without incuring any structural overhead.
*
* The system works best when allocating similarly-sized chunks of
- * memory. Care must be taken to avoid fragmentation when
+ * memory. Care must be taken to avoid fragmentation when
* allocating/deallocating dissimilar chunks.
*
* When a memory pool is first allocated, the entire pool is marked as
* available.
*
* z[n]xalloc() works like z[n]alloc() but the allocation is made from
- * within the specified address range. If the segment could not be
+ * within the specified address range. If the segment could not be
* allocated, NULL is returned. WARNING! The address range will be
* aligned to an 8 or 16 byte boundry depending on the cpu so if you
* give an unaligned address range, unexpected results may occur.
void *
znalloc(MemPool *mp, uintptr_t bytes)
{
- /*
- * align according to pool object size (can be 0). This is
- * inclusive of the MEMNODE_SIZE_MASK minimum alignment.
- *
- */
- bytes = (bytes + MEMNODE_SIZE_MASK) & ~MEMNODE_SIZE_MASK;
-
- if (bytes == 0)
- return((void *)-1);
-
- /*
- * locate freelist entry big enough to hold the object. If all objects
- * are the same size, this is a constant-time function.
- */
-
- if (bytes <= mp->mp_Size - mp->mp_Used) {
MemNode **pmn;
MemNode *mn;
- for (pmn = &mp->mp_First; (mn=*pmn) != NULL; pmn = &mn->mr_Next) {
- if (bytes > mn->mr_Bytes)
- continue;
+ /*
+ * align according to pool object size (can be 0). This is
+ * inclusive of the MEMNODE_SIZE_MASK minimum alignment.
+ *
+ */
+ bytes = (bytes + MEMNODE_SIZE_MASK) & ~MEMNODE_SIZE_MASK;
+
+ if (bytes == 0)
+ return ((void *)-1);
+
+ /*
+ * locate freelist entry big enough to hold the object. If all objects
+ * are the same size, this is a constant-time function.
+ */
- /*
- * Cut a chunk of memory out of the beginning of this
- * block and fixup the link appropriately.
- */
+ if (bytes > mp->mp_Size - mp->mp_Used)
+ return (NULL);
- {
+ for (pmn = &mp->mp_First; (mn = *pmn) != NULL; pmn = &mn->mr_Next) {
char *ptr = (char *)mn;
+ if (bytes > mn->mr_Bytes)
+ continue;
+
+ /*
+ * Cut a chunk of memory out of the beginning of this
+ * block and fixup the link appropriately.
+ */
if (mn->mr_Bytes == bytes) {
- *pmn = mn->mr_Next;
+ *pmn = mn->mr_Next;
} else {
- mn = (MemNode *)((char *)mn + bytes);
- mn->mr_Next = ((MemNode *)ptr)->mr_Next;
- mn->mr_Bytes = ((MemNode *)ptr)->mr_Bytes - bytes;
- *pmn = mn;
+ mn = (MemNode *)((char *)mn + bytes);
+ mn->mr_Next = ((MemNode *)ptr)->mr_Next;
+ mn->mr_Bytes = ((MemNode *)ptr)->mr_Bytes - bytes;
+ *pmn = mn;
}
mp->mp_Used += bytes;
return(ptr);
- }
}
- }
- /*
- * Memory pool is full, return NULL.
- */
+ /*
+ * Memory pool is full, return NULL.
+ */
- return(NULL);
+ return (NULL);
}
/*
void
zfree(MemPool *mp, void *ptr, uintptr_t bytes)
{
- /*
- * align according to pool object size (can be 0). This is
- * inclusive of the MEMNODE_SIZE_MASK minimum alignment.
- */
- bytes = (bytes + MEMNODE_SIZE_MASK) & ~MEMNODE_SIZE_MASK;
-
- if (bytes == 0)
- return;
+ MemNode **pmn;
+ MemNode *mn;
- /*
- * panic if illegal pointer
- */
+ /*
+ * align according to pool object size (can be 0). This is
+ * inclusive of the MEMNODE_SIZE_MASK minimum alignment.
+ */
+ bytes = (bytes + MEMNODE_SIZE_MASK) & ~MEMNODE_SIZE_MASK;
- if ((char *)ptr < (char *)mp->mp_Base ||
- (char *)ptr + bytes > (char *)mp->mp_End ||
- ((uintptr_t)ptr & MEMNODE_SIZE_MASK) != 0)
- panic("zfree(%p,%ju): wild pointer", ptr, (uintmax_t)bytes);
+ if (bytes == 0)
+ return;
- /*
- * free the segment
- */
+ /*
+ * panic if illegal pointer
+ */
- {
- MemNode **pmn;
- MemNode *mn;
+ if ((char *)ptr < (char *)mp->mp_Base ||
+ (char *)ptr + bytes > (char *)mp->mp_End ||
+ ((uintptr_t)ptr & MEMNODE_SIZE_MASK) != 0)
+ panic("zfree(%p,%ju): wild pointer", ptr, (uintmax_t)bytes);
+ /*
+ * free the segment
+ */
mp->mp_Used -= bytes;
for (pmn = &mp->mp_First; (mn = *pmn) != NULL; pmn = &mn->mr_Next) {
- /*
- * If area between last node and current node
- * - check range
- * - check merge with next area
- * - check merge with previous area
- */
- if ((char *)ptr <= (char *)mn) {
/*
- * range check
+ * If area between last node and current node
+ * - check range
+ * - check merge with next area
+ * - check merge with previous area
*/
- if ((char *)ptr + bytes > (char *)mn) {
- panic("zfree(%p,%ju): corrupt memlist1", ptr,
- (uintmax_t)bytes);
+ if ((char *)ptr <= (char *)mn) {
+ /*
+ * range check
+ */
+ if ((char *)ptr + bytes > (char *)mn) {
+ panic("zfree(%p,%ju): corrupt memlist1", ptr,
+ (uintmax_t)bytes);
+ }
+
+ /*
+ * merge against next area or create independant area
+ */
+
+ if ((char *)ptr + bytes == (char *)mn) {
+ ((MemNode *)ptr)->mr_Next = mn->mr_Next;
+ ((MemNode *)ptr)->mr_Bytes =
+ bytes + mn->mr_Bytes;
+ } else {
+ ((MemNode *)ptr)->mr_Next = mn;
+ ((MemNode *)ptr)->mr_Bytes = bytes;
+ }
+ *pmn = mn = (MemNode *)ptr;
+
+ /*
+ * merge against previous area (if there is a previous
+ * area).
+ */
+
+ if (pmn != &mp->mp_First) {
+ if ((char *)pmn + ((MemNode*)pmn)->mr_Bytes ==
+ (char *)ptr) {
+ ((MemNode *)pmn)->mr_Next = mn->mr_Next;
+ ((MemNode *)pmn)->mr_Bytes +=
+ mn->mr_Bytes;
+ mn = (MemNode *)pmn;
+ }
+ }
+ return;
}
-
- /*
- * merge against next area or create independant area
- */
-
- if ((char *)ptr + bytes == (char *)mn) {
- ((MemNode *)ptr)->mr_Next = mn->mr_Next;
- ((MemNode *)ptr)->mr_Bytes= bytes + mn->mr_Bytes;
- } else {
- ((MemNode *)ptr)->mr_Next = mn;
- ((MemNode *)ptr)->mr_Bytes= bytes;
- }
- *pmn = mn = (MemNode *)ptr;
-
- /*
- * merge against previous area (if there is a previous
- * area).
- */
-
- if (pmn != &mp->mp_First) {
- if ((char*)pmn + ((MemNode*)pmn)->mr_Bytes == (char*)ptr) {
- ((MemNode *)pmn)->mr_Next = mn->mr_Next;
- ((MemNode *)pmn)->mr_Bytes += mn->mr_Bytes;
- mn = (MemNode *)pmn;
- }
+ if ((char *)ptr < (char *)mn + mn->mr_Bytes) {
+ panic("zfree(%p,%ju): corrupt memlist2", ptr,
+ (uintmax_t)bytes);
}
- return;
- /* NOT REACHED */
- }
- if ((char *)ptr < (char *)mn + mn->mr_Bytes) {
- panic("zfree(%p,%ju): corrupt memlist2", ptr,
- (uintmax_t)bytes);
- }
}
/*
* We are beyond the last MemNode, append new MemNode. Merge against
* previous area if possible.
*/
- if (pmn == &mp->mp_First ||
- (char *)pmn + ((MemNode *)pmn)->mr_Bytes != (char *)ptr
- ) {
- ((MemNode *)ptr)->mr_Next = NULL;
- ((MemNode *)ptr)->mr_Bytes = bytes;
- *pmn = (MemNode *)ptr;
- mn = (MemNode *)ptr;
+ if (pmn == &mp->mp_First ||
+ (char *)pmn + ((MemNode *)pmn)->mr_Bytes != (char *)ptr) {
+ ((MemNode *)ptr)->mr_Next = NULL;
+ ((MemNode *)ptr)->mr_Bytes = bytes;
+ *pmn = (MemNode *)ptr;
+ mn = (MemNode *)ptr;
} else {
- ((MemNode *)pmn)->mr_Bytes += bytes;
- mn = (MemNode *)pmn;
+ ((MemNode *)pmn)->mr_Bytes += bytes;
+ mn = (MemNode *)pmn;
}
- }
}
/*
void
zextendPool(MemPool *mp, void *base, uintptr_t bytes)
{
- if (mp->mp_Size == 0) {
- mp->mp_Base = base;
- mp->mp_Used = bytes;
- mp->mp_End = (char *)base + bytes;
- mp->mp_Size = bytes;
- } else {
- void *pend = (char *)mp->mp_Base + mp->mp_Size;
-
- if (base < mp->mp_Base) {
- mp->mp_Size += (char *)mp->mp_Base - (char *)base;
- mp->mp_Used += (char *)mp->mp_Base - (char *)base;
- mp->mp_Base = base;
- }
- base = (char *)base + bytes;
- if (base > pend) {
- mp->mp_Size += (char *)base - (char *)pend;
- mp->mp_Used += (char *)base - (char *)pend;
- mp->mp_End = (char *)base;
+ if (mp->mp_Size == 0) {
+ mp->mp_Base = base;
+ mp->mp_Used = bytes;
+ mp->mp_End = (char *)base + bytes;
+ mp->mp_Size = bytes;
+ } else {
+ void *pend = (char *)mp->mp_Base + mp->mp_Size;
+
+ if (base < mp->mp_Base) {
+ mp->mp_Size += (char *)mp->mp_Base - (char *)base;
+ mp->mp_Used += (char *)mp->mp_Base - (char *)base;
+ mp->mp_Base = base;
+ }
+ base = (char *)base + bytes;
+ if (base > pend) {
+ mp->mp_Size += (char *)base - (char *)pend;
+ mp->mp_Used += (char *)base - (char *)pend;
+ mp->mp_End = (char *)base;
+ }
}
- }
}
#ifdef ZALLOCDEBUG
void
zallocstats(MemPool *mp)
{
- int abytes = 0;
- int hbytes = 0;
- int fcount = 0;
- MemNode *mn;
+ int abytes = 0;
+ int hbytes = 0;
+ int fcount = 0;
+ MemNode *mn;
- printf("%d bytes reserved", (int) mp->mp_Size);
+ printf("%d bytes reserved", (int)mp->mp_Size);
- mn = mp->mp_First;
+ mn = mp->mp_First;
- if ((void *)mn != (void *)mp->mp_Base) {
- abytes += (char *)mn - (char *)mp->mp_Base;
- }
+ if ((void *)mn != (void *)mp->mp_Base) {
+ abytes += (char *)mn - (char *)mp->mp_Base;
+ }
- while (mn) {
- if ((char *)mn + mn->mr_Bytes != mp->mp_End) {
- hbytes += mn->mr_Bytes;
- ++fcount;
+ while (mn != NULL) {
+ if ((char *)mn + mn->mr_Bytes != mp->mp_End) {
+ hbytes += mn->mr_Bytes;
+ ++fcount;
+ }
+ if (mn->mr_Next != NULL) {
+ abytes += (char *)mn->mr_Next -
+ ((char *)mn + mn->mr_Bytes);
+ }
+ mn = mn->mr_Next;
}
- if (mn->mr_Next)
- abytes += (char *)mn->mr_Next - ((char *)mn + mn->mr_Bytes);
- mn = mn->mr_Next;
- }
- printf(" %d bytes allocated\n%d fragments (%d bytes fragmented)\n",
- abytes,
- fcount,
- hbytes
- );
+ printf(" %d bytes allocated\n%d fragments (%d bytes fragmented)\n",
+ abytes, fcount, hbytes);
}
#endif
-
/*
- * This module derived from code donated to the FreeBSD Project by
+ * This module derived from code donated to the FreeBSD Project by
* Matthew Dillon <dillon@backplane.com>
*
* Copyright (c) 1998 The FreeBSD Project
void *
Malloc(size_t bytes, const char *file, int line)
{
- Guard *res;
+ Guard *res;
- if (bytes == 0)
- return (NULL);
+ if (bytes == 0)
+ return (NULL);
#ifdef USEENDGUARD
- bytes += MALLOCALIGN + 1;
+ bytes += MALLOCALIGN + 1;
#else
- bytes += MALLOCALIGN;
+ bytes += MALLOCALIGN;
#endif
- while ((res = znalloc(&MallocPool, bytes)) == NULL) {
- int incr = (bytes + BLKEXTENDMASK) & ~BLKEXTENDMASK;
- char *base;
+ while ((res = znalloc(&MallocPool, bytes)) == NULL) {
+ int incr = (bytes + BLKEXTENDMASK) & ~BLKEXTENDMASK;
+ char *base;
- if ((base = sbrk(incr)) == (char *)-1)
- return(NULL);
- zextendPool(&MallocPool, base, incr);
- zfree(&MallocPool, base, incr);
- }
+ if ((base = sbrk(incr)) == (char *)-1)
+ return (NULL);
+ zextendPool(&MallocPool, base, incr);
+ zfree(&MallocPool, base, incr);
+ }
#ifdef DMALLOCDEBUG
- if (++MallocCount > MallocMax)
- MallocMax = MallocCount;
+ if (++MallocCount > MallocMax)
+ MallocMax = MallocCount;
#endif
#ifdef USEGUARD
- res->ga_Magic = GAMAGIC;
+ res->ga_Magic = GAMAGIC;
#endif
- res->ga_Bytes = bytes;
+ res->ga_Bytes = bytes;
#ifdef USEENDGUARD
- *((signed char *)res + bytes - 1) = -2;
+ *((signed char *)res + bytes - 1) = -2;
#endif
- return((char *)res + MALLOCALIGN);
+ return ((char *)res + MALLOCALIGN);
}
void
Free(void *ptr, const char *file, int line)
{
- size_t bytes;
+ size_t bytes;
- if (ptr != NULL) {
- Guard *res = (void *)((char *)ptr - MALLOCALIGN);
+ if (ptr != NULL) {
+ Guard *res = (void *)((char *)ptr - MALLOCALIGN);
- if (file == NULL)
- file = "unknown";
+ if (file == NULL)
+ file = "unknown";
#ifdef USEGUARD
- if (res->ga_Magic == GAFREE) {
- printf("free: duplicate free @ %p from %s:%d\n", ptr, file, line);
- return;
- }
- if (res->ga_Magic != GAMAGIC)
- panic("free: guard1 fail @ %p from %s:%d", ptr, file, line);
- res->ga_Magic = GAFREE;
+ if (res->ga_Magic == GAFREE) {
+ printf("free: duplicate free @ %p from %s:%d\n",
+ ptr, file, line);
+ return;
+ }
+ if (res->ga_Magic != GAMAGIC)
+ panic("free: guard1 fail @ %p from %s:%d",
+ ptr, file, line);
+ res->ga_Magic = GAFREE;
#endif
#ifdef USEENDGUARD
- if (*((signed char *)res + res->ga_Bytes - 1) == -1) {
- printf("free: duplicate2 free @ %p from %s:%d\n", ptr, file, line);
- return;
- }
- if (*((signed char *)res + res->ga_Bytes - 1) != -2)
- panic("free: guard2 fail @ %p + %zu from %s:%d", ptr, res->ga_Bytes - MALLOCALIGN, file, line);
- *((signed char *)res + res->ga_Bytes - 1) = -1;
+ if (*((signed char *)res + res->ga_Bytes - 1) == -1) {
+ printf("free: duplicate2 free @ %p from %s:%d\n",
+ ptr, file, line);
+ return;
+ }
+ if (*((signed char *)res + res->ga_Bytes - 1) != -2)
+ panic("free: guard2 fail @ %p + %zu from %s:%d",
+ ptr, res->ga_Bytes - MALLOCALIGN, file, line);
+ *((signed char *)res + res->ga_Bytes - 1) = -1;
#endif
- bytes = res->ga_Bytes;
- zfree(&MallocPool, res, bytes);
+ bytes = res->ga_Bytes;
+ zfree(&MallocPool, res, bytes);
#ifdef DMALLOCDEBUG
- --MallocCount;
+ --MallocCount;
#endif
- }
+ }
}
void *
Calloc(size_t n1, size_t n2, const char *file, int line)
{
- uintptr_t bytes = (uintptr_t)n1 * (uintptr_t)n2;
- void *res;
+ uintptr_t bytes = (uintptr_t)n1 * (uintptr_t)n2;
+ void *res;
- if ((res = Malloc(bytes, file, line)) != NULL) {
- bzero(res, bytes);
+ if ((res = Malloc(bytes, file, line)) != NULL) {
+ bzero(res, bytes);
#ifdef DMALLOCDEBUG
- if (++MallocCount > MallocMax)
- MallocMax = MallocCount;
+ if (++MallocCount > MallocMax)
+ MallocMax = MallocCount;
#endif
- }
- return(res);
+ }
+ return (res);
}
/*
* realloc() - I could be fancier here and free the old buffer before
- * allocating the new one (saving potential fragmentation
+ * allocating the new one (saving potential fragmentation
* and potential buffer copies). But I don't bother.
*/
void *
Realloc(void *ptr, size_t size, const char *file, int line)
{
- void *res;
- size_t old;
-
- if ((res = Malloc(size, file, line)) != NULL) {
- if (ptr) {
- Guard *g = (Guard *)((char *)ptr - MALLOCALIGN);
-
- old = g->ga_Bytes - MALLOCALIGN;
- if (old < size)
- bcopy(ptr, res, old);
- else
- bcopy(ptr, res, size);
- Free(ptr, file, line);
- } else {
+ void *res;
+ size_t old;
+
+ if ((res = Malloc(size, file, line)) != NULL) {
+ if (ptr != NULL) {
+ Guard *g = (Guard *)((char *)ptr - MALLOCALIGN);
+
+ old = g->ga_Bytes - MALLOCALIGN;
+ if (old < size)
+ bcopy(ptr, res, old);
+ else
+ bcopy(ptr, res, size);
+ Free(ptr, file, line);
+ } else {
#ifdef DMALLOCDEBUG
- if (++MallocCount > MallocMax)
- MallocMax = MallocCount;
+ if (++MallocCount > MallocMax)
+ MallocMax = MallocCount;
#ifdef EXITSTATS
- if (DidAtExit == 0) {
- DidAtExit = 1;
- atexit(mallocstats);
- }
+ if (DidAtExit == 0) {
+ DidAtExit = 1;
+ atexit(mallocstats);
+ }
#endif
#endif
+ }
}
- }
- return(res);
+ return (res);
}
void *
Reallocf(void *ptr, size_t size, const char *file, int line)
{
- void *res;
+ void *res;
- if ((res = Realloc(ptr, size, file, line)) == NULL)
- Free(ptr, file, line);
- return(res);
+ if ((res = Realloc(ptr, size, file, line)) == NULL)
+ Free(ptr, file, line);
+ return (res);
}
#ifdef DMALLOCDEBUG
void
mallocstats(void)
{
- printf("Active Allocations: %d/%d\n", MallocCount, MallocMax);
+ printf("Active Allocations: %d/%d\n", MallocCount, MallocMax);
#ifdef ZALLOCDEBUG
- zallocstats(&MallocPool);
+ zallocstats(&MallocPool);
#endif
}
#endif
-