Skip to content

Commit

Permalink
Merge pull request #2129 from ghaerr/malloc
Browse files Browse the repository at this point in the history
[libc] Create debug version of malloc, fix near->far malloc conversion bug
  • Loading branch information
ghaerr authored Dec 12, 2024
2 parents c364a15 + f902d2b commit 0ff03dd
Show file tree
Hide file tree
Showing 8 changed files with 123 additions and 68 deletions.
13 changes: 9 additions & 4 deletions elks/arch/i86/mm/malloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -272,9 +272,11 @@ int sys_sbrk(int increment, segoff_t *pbrk)
segoff_t brk = current->t_endbrk; /* always return start of old break*/
int err;

if (increment)
dprintk("(%P)SBRK %d, curbreak %u, SP %u\n",
increment, current->t_endbrk, current->t_regs.sp);
if (increment) {
dprintk("(%P)SBRK %d\n", increment);
/*dprintk("(%P)SBRK %d, curbreak %u, SP %u\n",
increment, current->t_endbrk, current->t_regs.sp);*/
}
err = verify_area(VERIFY_WRITE, pbrk, sizeof(*pbrk));
if (err)
return err;
Expand All @@ -296,8 +298,11 @@ int sys_fmemalloc(int paras, unsigned short *pseg)
if (err)
return err;
seg = seg_alloc((segext_t)paras, SEG_FLAG_FDAT);
if (!seg)
if (!seg) {
dprintk("(%P)FMEMALLOC %ld FAIL\n", (unsigned long)paras << 4);
return -ENOMEM;
}
dprintk("(%P)FMEMALLOC %ld\n", (unsigned long)paras << 4);
seg->pid = current->pid;
put_user(seg->base, pseg);
return 0;
Expand Down
3 changes: 2 additions & 1 deletion libc/malloc/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ include $(TOPDIR)/libc/$(COMPILER).inc
CFLAGS += -DMCHUNK=16
#CFLAGS += -DMINALLOC
#CFLAGS += -DLAZY_FREE
#CFLAGS += -DVERBOSE
CFLAGS += -DVERBOSE=1
#CFLAGS += -DL_alloca

# use V7 malloc for heap integrity checking
Expand All @@ -25,6 +25,7 @@ OBJS = \
free.o \
malloc.o \
noise.o \
dprintf.o \
realloc.o \
sbrk.o \
fmemalloc.o \
Expand Down
10 changes: 5 additions & 5 deletions libc/malloc/__mini_malloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ __mini_malloc(size_t size)
{
mem __wcnear *ptr;

#if 0
#if 0 /* not required and slow, initial break always even */
size_t sz;
/* First time round this _might_ be odd, But we won't do that! */
sz = (size_t)sbrk(0);
Expand All @@ -28,11 +28,11 @@ __mini_malloc(size_t size)

size /= sizeof(mem);
ptr = (mem __wcnear *) sbrk(size * sizeof(mem));
/*if((uintptr_t)ptr == (intptr_t)-1)*/ /* this is better only when not __wcnear */
if ((int)ptr == -1)
if ((int)ptr == -1) {
debug("SBRK FAIL", 0);
return 0;

}
m_size(ptr) = size;
__noise("CREATE", ptr);
debug("SBRK", ptr);
return ptr + 1;
}
13 changes: 11 additions & 2 deletions libc/malloc/_malloc.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,19 @@ typedef union mem_cell
char __wcnear *depth; /* For the alloca hack */
} mem;

#ifdef VERBOSE
void __noise(char *y, mem __wcnear *x);
int __dprintf(const char *fmt, ...);
extern int __debug_level;

#if !VERBOSE
#define dprintf(...)
#define debug(str,ptr)
#elif VERBOSE == 1
#define dprintf __dprintf
#define debug(str,ptr)
#else
#define __noise(y,x)
#define dprintf(...)
#define debug(str,ptr) __noise(str,ptr)
#endif

#define m_deep(p) ((p) [0].depth) /* For alloca */
Expand Down
41 changes: 41 additions & 0 deletions libc/malloc/dprintf.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#if VERBOSE
#include <stdarg.h>
#include <stdlib.h>
#include <unistd.h>

int __debug_level = 1;

/*
* Very tiny printf to stderr.
* Supports:
* %u unsigned int
*/
int __dprintf(const char *fmt, ...)
{
unsigned int n = 0;
char *p;
va_list va;
char b[128];

if (__debug_level == 0)
return 0;
va_start(va, fmt);
for (; *fmt; fmt++) {
if (*fmt == '%') {
switch (*++fmt) {
case 'u':
p = uitoa(va_arg(va, unsigned int));
while (*p && n < sizeof(b))
b[n++] = *p++;
break;
}
continue;
} else {
if (n < sizeof(b))
b[n++] = *fmt;
}
}
va_end(va);
return write(2, b, n);
}
#endif
4 changes: 2 additions & 2 deletions libc/malloc/free.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ free(void * ptr)
#endif
top = (mem __wcnear *) sbrk(0);
if (chk + m_size(chk) == top) {
__noise("FREE brk", chk);
debug("BRK (releasing top chunk)", chk);
brk(top - m_size(chk));
/*
* Adding this code allow free to release blocks in any order; they
Expand Down Expand Up @@ -49,6 +49,6 @@ free(void * ptr)
m_next(chk) = (union mem_cell __wcnear *)__freed_list;
__freed_list = chk;
#endif
__noise("ADD LIST", chk);
debug("ADD LIST", chk);
}
}
85 changes: 45 additions & 40 deletions libc/malloc/malloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@
#include <malloc.h>
#include <unistd.h>
#include <errno.h>
#include <sys/sysctl.h>

#include "_malloc.h"

#undef malloc
#define MAX_INT ((int)(((unsigned)-1)>>1))

/*
Expand All @@ -37,7 +37,7 @@ __insert_chunk(mem __wcnear *mem_chunk)
{
chunk_list = mem_chunk;
m_next(mem_chunk) = (union mem_cell __wcnear *)mem_chunk;
__noise("FIRST CHUNK", mem_chunk);
debug("FIRST CHUNK", mem_chunk);
return;
}
p1 = mem_chunk;
Expand All @@ -53,16 +53,16 @@ __insert_chunk(mem __wcnear *mem_chunk)

if (p2 + m_size(p2) == p1)
{ /* Good, stick 'em together */
__noise("INSERT CHUNK", mem_chunk);
debug("INSERT CHUNK", mem_chunk);
m_size(p2) += m_size(p1);
__noise("JOIN 1", p2);
debug("JOIN 1", p2);
}
else
{
m_next(p1) = m_next(p2);
m_next(p2) = (union mem_cell __wcnear *)p1;
__noise("INSERT CHUNK", mem_chunk);
__noise("FROM", p2);
debug("INSERT CHUNK", mem_chunk);
debug("FROM", p2);
}
return;
}
Expand All @@ -72,22 +72,22 @@ __insert_chunk(mem __wcnear *mem_chunk)

m_next(p1) = m_next(p2);
m_next(p2) = (union mem_cell __wcnear *)p1;
__noise("INSERT CHUNK", mem_chunk);
__noise("FROM", p2);
debug("INSERT CHUNK", mem_chunk);
debug("FROM", p2);

/* Try to join above */
if (p1 + m_size(p1) == m_next(p1))
{
m_size(p1) += m_size(m_next(p1));
m_next(p1) = m_next(m_next(p1));
__noise("JOIN 2", p1);
debug("JOIN 2", p1);
}
/* Try to join below */
if (p2 + m_size(p2) == p1)
{
m_size(p2) += m_size(p1);
m_next(p2) = m_next(p1);
__noise("JOIN 3", p2);
debug("JOIN 3", p2);
}
chunk_list = p2; /* Make sure it's valid */
return;
Expand All @@ -101,8 +101,8 @@ __insert_chunk(mem __wcnear *mem_chunk)

m_next(p1) = m_next(p2);
m_next(p2) = (union mem_cell __wcnear *)p1;
__noise("INSERT CHUNK", mem_chunk);
__noise("FROM", p2);
debug("INSERT CHUNK", mem_chunk);
debug("FROM", p2);
chunk_list = p2;

if (p1 + m_size(p1) == m_next(p1))
Expand All @@ -111,7 +111,7 @@ __insert_chunk(mem __wcnear *mem_chunk)
chunk_list = p1;
m_size(p1) += m_size(m_next(p1));
m_next(p1) = m_next(m_next(p1));
__noise("JOIN 4", p1);
debug("JOIN 4", p1);
}
return;
}
Expand All @@ -122,7 +122,7 @@ __insert_chunk(mem __wcnear *mem_chunk)
while (p2 != chunk_list);

/* If we get here we have a problem, ignore it, maybe it'll go away */
__noise("DROPPED CHUNK", mem_chunk);
debug("DROPPED CHUNK", mem_chunk);
}

/*
Expand All @@ -142,7 +142,7 @@ __search_chunk(unsigned int mem_size)
p2 = chunk_list;
do
{
__noise("CHECKED", p1);
debug("CHECKED", p1);
if (m_size(p1) >= mem_size)
break;

Expand All @@ -158,14 +158,14 @@ __search_chunk(unsigned int mem_size)
/* If it's exactly right remove it */
if (m_size(p1) < mem_size + 2)
{
__noise("FOUND RIGHT", p1);
debug("FOUND RIGHT", p1);
chunk_list = m_next(p2) = m_next(p1);
if (chunk_list == p1)
chunk_list = 0;
return p1;
}

__noise("SPLIT", p1);
debug("SPLIT", p1);
/* Otherwise split it */
m_next(p2) = (union mem_cell __wcnear *)(p1 + mem_size);
chunk_list = p2;
Expand All @@ -176,12 +176,11 @@ __search_chunk(unsigned int mem_size)
m_size(p1) = mem_size;
if (chunk_list == p1)
chunk_list = p2;
#ifdef VERBOSE
p1[1].size = (unsigned int)0xAAAAAAAA;
#endif
__noise("INSERT CHUNK", p2);
__noise("FOUND CHUNK", p1);
__noise("LIST IS", chunk_list);

p1[1].size = (unsigned int)0xAAAA; /* canary, not required */
debug("INSERT CHUNK", p2);
debug("FOUND CHUNK", p1);
debug("LIST IS", chunk_list);
return p1;
}

Expand All @@ -191,6 +190,13 @@ malloc(size_t size)
register mem __wcnear *ptr = 0;
register unsigned int sz;

#if VERBOSE == 1
if (chunk_list == 0)
{
sysctl(CTL_GET, "kern.debug", &__debug_level);
}
#endif

errno = 0;
if (size == 0)
return 0; /* ANSI STD, no error */
Expand All @@ -210,11 +216,12 @@ malloc(size_t size)
sz = MINALLOC;
#endif

#ifdef VERBOSE
dprintf("MALLOC %u\n", sz * sizeof(mem));
#if VERBOSE > 1
{
static mem arr[2];
m_size(arr) = sz;
__noise("WANTED", arr);
debug("WANTED", arr);
}
#endif

Expand All @@ -236,10 +243,9 @@ malloc(size_t size)
ptr = __freed_list;
__freed_list = m_next(__freed_list);

if (m_size(ptr) == sz) /* Oh! Well that's lucky ain't it
* :-) */
if (m_size(ptr) == sz) /* Oh! Well that's lucky ain't it :-) */
{
__noise("LUCKY MALLOC", ptr);
debug("RETURN (exact from freelist)", ptr);
return ptr + 1;
}

Expand Down Expand Up @@ -294,23 +300,22 @@ malloc(size_t size)
#ifndef MCHUNK
ptr = __mini_malloc(size);
#endif
if( ptr == 0) errno = ENOMEM;
#ifdef VERBOSE
if( ptr == 0 )
__noise("MALLOC FAIL", 0);
else
__noise("MALLOC NOW", ptr - 1);
#endif
return ptr;
if (ptr == 0)
{
errno = ENOMEM;
dprintf("FAIL\n");
debug("FAIL", 0);
return 0; /* don't far-extend near ptr in large model */
}
debug("RETURN (new chunk)", ptr - 1);
return ptr;
}
}
#ifdef LAZY_FREE
}
#endif

#ifdef VERBOSE
ptr[1].size = (unsigned int)0x55555555;
#endif
__noise("MALLOC RET", ptr);
ptr[1].size = (unsigned int)0x5555; /* canary, not required */
debug("RETURN", ptr);
return ptr + 1;
}
Loading

0 comments on commit 0ff03dd

Please sign in to comment.