Skip to content

Commit

Permalink
Merge pull request #2144 from ghaerr/debugmalloc
Browse files Browse the repository at this point in the history
[libc] Enhance debugging output for amalloc and dmalloc
  • Loading branch information
ghaerr authored Dec 19, 2024
2 parents afd7ad0 + 71bafc5 commit eae676f
Show file tree
Hide file tree
Showing 6 changed files with 122 additions and 77 deletions.
1 change: 0 additions & 1 deletion libc/malloc/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ OBJS = \
brk.o \
sbrk.o \
fmemalloc.o \
fmemfree.o \
dprintf.o \

# default and debug mallocs available for ia16 and OWC
Expand Down
51 changes: 24 additions & 27 deletions libc/malloc/amalloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@
* Enhancements:
* Minimum BLOCK allocate from kernel sbrk, > BLOCK allocates requested size
* Much improved size and heap overflow handling with errno returns
* Full heap integrity checking and reporting with DEBUG options
* Full heap integrity checking and reporting with debug options
* Use near heap pointers to work with OpenWatcom large model
* Combine free areas at heap start before allocating from free area at end of heap
*/
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/sysctl.h>
#define DEBUG 2 /* =1 heap checking asserts, =2 sysctl, =3 show heap */
#define DEBUG 1 /* =1 use sysctl, =2 debug output, =3 show heap */

/* C storage allocator
* circular first-fit strategy
Expand All @@ -41,7 +41,7 @@
#define ALIGN int
#define NALIGN 1
#define BUSY 1
#define BLOCK 34 /* min+WORD amount to sbrk */
#define BLOCK 34 /* min+WORD amount to sbrk (was 514) */
#define MINALLOC 14 /* minimum actual malloc size */
#define GRANULE 0 /* sbrk granularity */

Expand Down Expand Up @@ -70,22 +70,18 @@ static NPTR allocp; /*search ptr*/
static NPTR alloct; /*arena top*/
static NPTR allocx; /*for benefit of realloc*/

static int debug_level = DEBUG;
#if DEBUG
#define ASSERT(p) if(!(p))malloc_assert_fail(#p);else {}
static void malloc_assert_fail(char *s);
static int malloc_check_heap(void);
#else
#define ASSERT(p)
#endif

#if DEBUG > 1
#define ASSERT(p) if(!(p))malloc_assert_fail(#p,__LINE__);else {}
#define debug(...) do { if (debug_level > 1) __dprintf(__VA_ARGS__); } while (0)
#define debug2(...) do { if (debug_level > 2) __dprintf(__VA_ARGS__); } while (0)
int __dprintf(const char *fmt, ...);
static void malloc_assert_fail(char *s, int);
static void malloc_show_heap(void);
static int debug_level = DEBUG;
static int malloc_check_heap(void);
#else
#define ASSERT(p)
#define debug(...)
#define debug2(...)
#define malloc_show_heap()
#endif

Expand All @@ -96,7 +92,7 @@ int __amalloc_add_heap(char __far *start, size_t size)
allocs = (FPTR)start;
allocseg = FP_SEG(start);
allocsize = size / sizeof(union store);
debug("Adding %04x %04x size %d DS %04x %04x\n", start, size, &size);
debug("Adding SEG %04x size %d DS %04x\n", FP_SEG(start), size, FP_SEG(&size));

allocs[0].ptr = setbusy(&allocs[1]);
allocs[1].ptr = (NPTR)&allocs[allocsize-2];
Expand All @@ -113,11 +109,11 @@ __amalloc(size_t nbytes)
NPTR p, q;
unsigned int nw, temp;

#if DEBUG == 2
#if DEBUG == 1
sysctl(CTL_GET, "malloc.debug", &debug_level);
#endif

debug("(%d)malloc(%u) ", getpid(), nbytes);
debug("(%d)malloc(%5u) ", getpid(), nbytes);
if (!allocs)
return NULL;
errno = 0;
Expand Down Expand Up @@ -147,7 +143,7 @@ __amalloc(size_t nbytes)
if (debug_level > 2) malloc_show_heap();
ASSERT(q>p);
ASSERT(q<alloct);
debug("(combine %u and %u) ",
debug2("(combine %u and %u) ",
(next(p) - p) * sizeof(union store),
(next(q) - q) * sizeof(union store));
next(p) = next(q);
Expand Down Expand Up @@ -182,7 +178,7 @@ __amalloc(size_t nbytes)
temp = nw + 1; /* NOTE always allocates full req w/o looking at free at top */

if (debug_level > 2) malloc_show_heap();
debug("sbrk(%d) ", temp*WORD);
debug2("sbrk(%d) ", temp*WORD);
#if 0 /* not required and slow, initial break always even */
q = (NPTR)sbrk(0);
if((INT)q & (sizeof(union store) - 1))
Expand All @@ -208,7 +204,7 @@ __amalloc(size_t nbytes)
if(q!=alloct+1) /* mark any gap as permanently allocated*/
next(alloct) = setbusy(next(alloct));
alloct = next(q) = q+temp-1;
debug("(TOTAL %u) ",
debug2("(TOTAL %u) ",
sizeof(union store) +
(clearbusy(alloct) - clearbusy(allocs[allocsize-1].ptr)) * sizeof(union store));
next(alloct) = setbusy(allocs);
Expand All @@ -222,7 +218,7 @@ __amalloc(size_t nbytes)
next(allocp) = next(p);
}
next(p) = setbusy(allocp);
debug("= %04x\n", (unsigned)p);
debug2("= %04x\n", (unsigned)p);
malloc_show_heap();
return MK_FPTR(allocseg, p+1);
}
Expand All @@ -236,8 +232,8 @@ __afree(void *ptr)

if (p == NULL)
return;
debug("(%d) free(%d) = %04x\n", getpid(),
(unsigned)(next(p-1) - p) * sizeof(union store), p-1);
debug("(%d) free(%5u) ", getpid(), (unsigned)(next(p-1) - p) * sizeof(union store));
debug2("= %04x\n", p-1);
ASSERT(FP_SEG(ptr)==allocseg);
ASSERT(p>clearbusy(allocs[allocsize-1].ptr)&&p<=alloct);
ASSERT(malloc_check_heap());
Expand Down Expand Up @@ -307,9 +303,9 @@ __arealloc(void *ptr, size_t nbytes)
#endif

#if DEBUG
static void malloc_assert_fail(char *s)
static void malloc_assert_fail(char *s, int line)
{
__dprintf("malloc assert fail: %s\n", s);
__dprintf("amalloc assert fail: %s (line %d)\n", s, line);
abort();
}

Expand All @@ -330,16 +326,16 @@ malloc_check_heap(void)
ASSERT(p==alloct);
return((x==1)|(p==allocp));
}
#endif

#if DEBUG > 1
static void
malloc_show_heap(void)
{
NPTR p;
int n = 1;
unsigned int size, alloc = 0, free = 0;
static unsigned int maxalloc;

if (!debug_level) return;
debug2("--- heap size ---\n");
malloc_check_heap();
for(p = (NPTR)&allocs[0]; clearbusy(next(p)) > p; p=clearbusy(next(p))) {
Expand All @@ -357,7 +353,8 @@ malloc_show_heap(void)
debug2("\n");
}
alloc += sizeof(union store);
if (alloc > maxalloc) maxalloc = alloc;
debug2("%2d: %04x %4u (top) ", n, (unsigned)alloct, 2);
debug("alloc %u, free %u, total %u\n", alloc, free, alloc+free);
debug("alloc %5u, free %5u, arena %5u/%5u\n", alloc, free, maxalloc, alloc+free);
}
#endif
38 changes: 30 additions & 8 deletions libc/malloc/dprintf.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,21 @@
#include <paths.h>
#include <fcntl.h>

static char *uitostr(unsigned int val, int radix, int width)
static char *fmtultostr(unsigned long val, int radix, int width)
{
static char buf[6];
static char buf[34];
char *p = buf + sizeof(buf) - 1;
unsigned int c;

*p = '\0';
do {
#ifdef _M_I86
c = radix;
val = __divmod(val, &c);
#else
c = val % radix;
val = val / radix;
#endif
if (c > 9)
*--p = 'a' - 10 + c;
else
Expand All @@ -28,47 +33,64 @@ static char *uitostr(unsigned int val, int radix, int width)
/*
* Very tiny printf to console.
* Supports:
* %{0-9} width
* %{0-9} field width
* %l{u,d,x,p}
* %u unsigned decimal
* %d decimal (positive numbers only)
* %p zero-fill hexadecimal width 4
* %p pointer (zero-filled hexadecimal)
* %x hexadecimal
* %s string
*/
int __dprintf(const char *fmt, ...)
{
unsigned int n;
unsigned long val;
int radix, width;
char *p;
va_list va;
int lval;
char b[80];
static int fd = -1;

if (fd < 0)
fd = open(_PATH_CONSOLE, O_WRONLY);
if (fd < 0) {
if (!isatty(STDERR_FILENO))
fd = STDERR_FILENO;
else
fd = open(_PATH_CONSOLE, O_WRONLY);
}
va_start(va, fmt);
for (n = 0; *fmt; fmt++) {
if (*fmt == '%') {
++fmt;
width = 0;
lval = 0;
while (*fmt >= '0' && *fmt <= '9') {
width = width * 10 + *fmt - '0';
fmt++;
}
again:
switch (*fmt) {
case 'l':
lval = 1;
fmt++;
goto again;
case 's':
p = va_arg(va, char *);
goto outstr;
case 'p':
width = 4;
if (sizeof(char *) == sizeof(unsigned long))
lval = 1;
width = lval? 8: 4;
/* fall through */
case 'x':
radix = 16;
goto convert;
case 'd':
case 'u':
radix = 10;
convert:
p = uitostr(va_arg(va, unsigned int), radix, width);
val = lval? va_arg(va, unsigned long): va_arg(va, unsigned int);
p = fmtultostr(val, radix, width);
outstr:
while (*p && n < sizeof(b))
b[n++] = *p++;
Expand Down
47 changes: 43 additions & 4 deletions libc/malloc/fmemalloc.c
Original file line number Diff line number Diff line change
@@ -1,14 +1,53 @@
#include <malloc.h>
#include <unistd.h>
#include <errno.h>
#include <sys/sysctl.h>
/* fmemalloc/fmemfree - allocate/free from main memory */

#define _MK_FP(seg,off) ((void __far *)((((unsigned long)(seg)) << 16) | (off)))
#define DEBUG 1 /* =1 use sysctl, =2 debug output */

#if DEBUG
#define debug(...) do { if (debug_level > 1) __dprintf(__VA_ARGS__); } while (0)
static int debug_level = DEBUG;
static unsigned long total;
static unsigned long maxsize;
#else
#define debug(...)
#endif

#define FP_SEG(fp) ((unsigned)((unsigned long)(void __far *)(fp) >> 16))
#define FP_OFF(fp) ((unsigned)(unsigned long)(void __far *)(fp))
#define MK_FP(seg,off) ((void __far *)((((unsigned long)(seg)) << 16) | \
((unsigned int)(off))))

/* alloc from main memory */
void __far *fmemalloc(unsigned long size)
{
unsigned short seg;
unsigned int paras = (unsigned int)((size + 15) >> 4);

if (_fmemalloc(paras, &seg))
#if DEBUG == 1
sysctl(CTL_GET, "malloc.debug", &debug_level);
#endif
debug("(%d)FMEMALLOC(%5lu) ", getpid(), size);
if (_fmemalloc(paras, &seg)) {
debug("= FAIL\n");
return 0;
return _MK_FP(seg, 0);
}
#if DEBUG
total += size;
if (size > maxsize) maxsize = size;
debug("total %lu, maxsize %lu\n", total, maxsize);
#endif
return MK_FP(seg, 0);
}

int fmemfree(void __far *ptr)
{
debug("(%d) fmemfree()\n", getpid()); // FIXME get size of allocation
if (FP_OFF(ptr)) {
debug(" FAIL (bad pointer)\n"); // FIXME convert to ASSERT
errno = EINVAL;
return -1;
}
return _fmemfree(FP_SEG(ptr));
}
7 changes: 0 additions & 7 deletions libc/malloc/fmemfree.c

This file was deleted.

Loading

0 comments on commit eae676f

Please sign in to comment.