Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[libc] Enhance debugging output for amalloc and dmalloc #2144

Merged
merged 4 commits into from
Dec 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading