From 511fe13c53c56ed6c0803a7b727280fd72feaeb0 Mon Sep 17 00:00:00 2001 From: Stas Sergeev Date: Sat, 17 May 2025 01:15:10 +0300 Subject: [PATCH 1/3] getaddrinfo: fix memory corruption --- src/libc/posix/socket/inet/gaddrinf.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/libc/posix/socket/inet/gaddrinf.c b/src/libc/posix/socket/inet/gaddrinf.c index 292c5cca..b044acfe 100644 --- a/src/libc/posix/socket/inet/gaddrinf.c +++ b/src/libc/posix/socket/inet/gaddrinf.c @@ -28,7 +28,7 @@ int getaddrinfo(const char *restrict host, const char *restrict serv, const struct addrinfo *restrict hint, struct addrinfo **restrict res) { struct addrinfo *ret = malloc(sizeof(*ret)); - struct sockaddr_in *sin = (struct sockaddr_in *)ret->ai_addr; + struct sockaddr_in *sin = malloc(sizeof(*sin)); struct hostent *h = gethostbyname(host); if (!h) @@ -39,6 +39,7 @@ int getaddrinfo(const char *restrict host, const char *restrict serv, ret->ai_protocol = IPPROTO_TCP; ret->ai_addrlen = sizeof(struct sockaddr_in); sin->sin_addr = *(struct in_addr *)h->h_addr; + ret->ai_addr = (struct sockaddr *)sin; ret->ai_canonname = strdup(h->h_name); ret->ai_next = NULL; *res = ret; @@ -48,5 +49,6 @@ int getaddrinfo(const char *restrict host, const char *restrict serv, void freeaddrinfo(struct addrinfo *res) { free(res->ai_canonname); + free(res->ai_addr); free(res); } From a2525790622f2386bd55b19eb69e7b68809f80d1 Mon Sep 17 00:00:00 2001 From: Stas Sergeev Date: Sat, 17 May 2025 01:16:40 +0300 Subject: [PATCH 2/3] dosobj: make it 32bit 16bit dosobj from fdpp doesn't work for 32bit networking code. --- include/crt0.h | 1 - src/libc/dj64/dosobj.c | 76 ++++-------------------------------------- src/libc/dj64/dosobj.h | 10 +++--- src/libc/dj64/plt.S | 5 --- src/libc/dj64/thunks.c | 2 +- 5 files changed, 11 insertions(+), 83 deletions(-) diff --git a/include/crt0.h b/include/crt0.h index b3545f24..a0f95dc9 100644 --- a/include/crt0.h +++ b/include/crt0.h @@ -68,7 +68,6 @@ char **__crt0_glob_function(char *_arg); #ifdef _IN_DJ64 EXTERN ASM(int, _crt0_startup_flags); -EXTERN ASM_ARR(unsigned char, dosobj_page, 4096); #else extern int _crt0_startup_flags; #endif diff --git a/src/libc/dj64/dosobj.c b/src/libc/dj64/dosobj.c index d60ec078..f48962b0 100644 --- a/src/libc/dj64/dosobj.c +++ b/src/libc/dj64/dosobj.c @@ -38,86 +38,29 @@ #include #include #include -#include -#include "smalloc.h" #include "dosobj.h" -struct dost { - smpool pool; - uint32_t base; - int initialized; -}; - -static struct dost *dst; -DJ64_DEFINE_SWAPPABLE_CONTEXT(dost, dst) -#define pool dst->pool -#define base dst->base -#define initialized dst->initialized - -static void err_printf(int prio, const char *fmt, ...) PRINTF(2); -static void err_printf(int prio, const char *fmt, ...) -{ - va_list vl; - - va_start(vl, fmt); - djloudvprintf(fmt, vl); - va_end(vl); -} - -void dosobj_init(void *ptr, int size) -{ - assert(!initialized); - sminit(&pool, ptr, size); - smregister_error_notifier(&pool, err_printf); - base = PTR_DATA(ptr); - initialized = 1; -} - -static void do_free(void) +void dosobj_init(void) { - int leaked; - - assert(initialized); - leaked = smdestroy(&pool); - assert(!leaked); } void dosobj_free(void) { - do_free(); - initialized = 0; } -void dosobj_reinit(void *ptr, int size) +uint32_t mk_dosobj(uint32_t len) { - do_free(); - sminit(&pool, ptr, size); - base = PTR_DATA(ptr); -} - -uint32_t mk_dosobj(uint16_t len) -{ - void *ptr; - uint32_t offs; - - assert(initialized); - ptr = smalloc(&pool, len); - if (!ptr) { - djloudprintf("dosobj: OOM! len=%i\n", len); - abort(); - } - offs = (uintptr_t)ptr - (uintptr_t)smget_base_addr(&pool); - return base + offs; + return malloc32(len); } -void pr_dosobj(uint32_t fa, const void *data, uint16_t len) +void pr_dosobj(uint32_t fa, const void *data, uint32_t len) { void *ptr = DATA_PTR(fa); memcpy(ptr, data, len); } -void cp_dosobj(void *data, uint32_t fa, uint16_t len) +void cp_dosobj(void *data, uint32_t fa, uint32_t len) { void *ptr = DATA_PTR(fa); @@ -126,12 +69,5 @@ void cp_dosobj(void *data, uint32_t fa, uint16_t len) void rm_dosobj(uint32_t fa) { - void *ptr = (char *)smget_base_addr(&pool) + (fa - base); - - smfree(&pool, ptr); -} - -void dosobj_dump(void) -{ - smdump(&pool); + free32(fa); } diff --git a/src/libc/dj64/dosobj.h b/src/libc/dj64/dosobj.h index 2ba04f11..9ffe203c 100644 --- a/src/libc/dj64/dosobj.h +++ b/src/libc/dj64/dosobj.h @@ -24,13 +24,11 @@ #include -void dosobj_init(void *ptr, int size); -void dosobj_reinit(void *ptr, int size); +void dosobj_init(void); void dosobj_free(void); -uint32_t mk_dosobj(uint16_t len); -void pr_dosobj(uint32_t fa, const void *data, uint16_t len); -void cp_dosobj(void *data, uint32_t fa, uint16_t len); +uint32_t mk_dosobj(uint32_t len); +void pr_dosobj(uint32_t fa, const void *data, uint32_t len); +void cp_dosobj(void *data, uint32_t fa, uint32_t len); void rm_dosobj(uint32_t fa); -void dosobj_dump(void); #endif diff --git a/src/libc/dj64/plt.S b/src/libc/dj64/plt.S index 03ae6bae..e97be684 100644 --- a/src/libc/dj64/plt.S +++ b/src/libc/dj64/plt.S @@ -409,8 +409,3 @@ dj64_plt_call: movl $AUX_USER, %ebx call_plt ret - -.bss - -.global _dosobj_page -_dosobj_page: .space 4096 diff --git a/src/libc/dj64/thunks.c b/src/libc/dj64/thunks.c index 4d7fec80..3fe93937 100644 --- a/src/libc/dj64/thunks.c +++ b/src/libc/dj64/thunks.c @@ -670,7 +670,7 @@ void crt1_startup(int handle) assert(handle < MAX_HANDLES); __djgpp_nearptr_enable(); // speeds up things considerably - dosobj_init(dosobj_page, 4096); + dosobj_init(); u = &udisps[handle]; __crt1_startup(u->main); From 559c6fca1faeacd960a6d11af0b582ab98b22ed7 Mon Sep 17 00:00:00 2001 From: Stas Sergeev Date: Sat, 17 May 2025 01:19:12 +0300 Subject: [PATCH 3/3] remove smalloc dj64dev has lots of native allocators these days. --- src/libc/dj64/makefile | 2 +- src/libc/dj64/smalloc.c | 735 ---------------------------------------- src/libc/dj64/smalloc.h | 77 ----- 3 files changed, 1 insertion(+), 813 deletions(-) delete mode 100644 src/libc/dj64/smalloc.c delete mode 100644 src/libc/dj64/smalloc.h diff --git a/src/libc/dj64/makefile b/src/libc/dj64/makefile index 1bba63fb..0ecb463d 100644 --- a/src/libc/dj64/makefile +++ b/src/libc/dj64/makefile @@ -8,7 +8,7 @@ MP = $(P)/mkproto.sh GA = $(P)/gen_asms.sh LIBN = libdj64.so.0.2 LIBS = libdj64_s.a -SOURCES = thunks.c thunks_a.c thunks_c.c thunks_p.c dosobj.c smalloc.c +SOURCES = thunks.c thunks_a.c thunks_c.c thunks_p.c dosobj.c OBJECTS = $(SOURCES:.c=.o) .INTERMEDIATE: thunk_syms.s thunk_syms.ss diff --git a/src/libc/dj64/smalloc.c b/src/libc/dj64/smalloc.c deleted file mode 100644 index 9bffef2a..00000000 --- a/src/libc/dj64/smalloc.c +++ /dev/null @@ -1,735 +0,0 @@ -/* - * dj64 - 64bit djgpp-compatible tool-chain - * Copyright (C) 2021-2024 @stsp - * - * FDPP - freedos port to modern C++ - * Copyright (C) 2018 Stas Sergeev (stsp) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - */ - -/* - * NOTE: this file is a port of smalloc.c file from fdpp project. - * In fdpp project it is distributed under the terms of GNU GPLv3+ - * with an authorship of Stas Sergeev (stsp). - * As an author of the aforementioned smalloc.c, I donate the code - * to dj64dev project, allowing to re-license it under the terms - * of GNU LGPLv3+. - * - * --stsp - */ - -/* - * smalloc - small memory allocator for dosemu. - * - * Author: Stas Sergeev - */ - -#include -#include -#include -#include -#include -#include -#include "smalloc.h" - -#define POOL_USED(p) (p->mn.used || p->mn.next) -#ifndef _min -#define _min(x, y) ((x) < (y) ? (x) : (y)) -#endif -#ifndef PAGE_SIZE -#define PAGE_SIZE 4096 -#endif -#define _PAGE_MASK (~(PAGE_SIZE-1)) -#ifndef PAGE_ALIGN -#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&_PAGE_MASK) -#endif - -static void smerror_dummy(int prio, const char *fmt, ...) FORMAT(printf, 2, 3); - -static void (*smerr)(int prio, const char *fmt, ...) - FORMAT(printf, 2, 3) = smerror_dummy; - -static void smerror_dummy(int prio, const char *fmt, ...) -{ -} - -#define smerror(mp, ...) mp->smerr(3, __VA_ARGS__) - -static int do_dump(struct mempool *mp, char *buf, int len) -{ - int pos = 0; - struct memnode *mn; - -#define DO_PRN(...) do { \ - if (pos >= len) \ - return -1; \ - pos += snprintf(buf + pos, len - pos, __VA_ARGS__); \ -} while (0) - DO_PRN("Total size: %zi\n", mp->size); - DO_PRN("Available space: %zi (%zi used)\n", mp->avail, - mp->size - mp->avail); - DO_PRN("Largest free area: %zi\n", smget_largest_free_area(mp)); - DO_PRN("Memory pool dump:\n"); - for (mn = &mp->mn; mn; mn = mn->next) - DO_PRN("\tarea: %zi bytes, %s\n", - mn->size, mn->used ? "used" : "free"); - return 0; -} - -void smdump(struct mempool *mp) -{ - char buf[16384]; - int err = do_dump(mp, buf, sizeof(buf)); - if (!err) - mp->smerr(0, "%s", buf); - else - mp->smerr(3, "dump buffer overflow\n"); -} - -static FORMAT(printf, 3, 4) -void do_smerror(int prio, struct mempool *mp, const char *fmt, ...) -{ - char buf[16384]; - int err; - size_t pos; - va_list al; - - assert(prio != -1); - va_start(al, fmt); - pos = vsnprintf(buf, sizeof(buf), fmt, al); - va_end(al); - err = -1; - if (pos < sizeof(buf)) - err = do_dump(mp, buf + pos, sizeof(buf) - pos); - if (!err) - mp->smerr(0, "%s", buf); - else - mp->smerr(3, "dump buffer overflow\n"); -} - -static int get_oom_pr(struct mempool *mp, size_t size) -{ - if (size <= smget_largest_free_area(mp)) - return -1; - if (size > mp->size) - return 2; - if (size > mp->avail) - return 1; - return 0; -} - -static void sm_uncommit(struct mempool *mp, void *addr, size_t size) -{ - /* align address up and align down size */ - uintptr_t a = (uintptr_t)addr; - uintptr_t aa = PAGE_ALIGN(a); - size_t aligned_size = (size - (aa - a)) & _PAGE_MASK; - void *aligned_addr = (void *)aa; - mp->avail += size; - assert(mp->avail <= mp->size); - if (!mp->uncommit) - return; - mp->uncommit(aligned_addr, aligned_size); -} - -static int __sm_commit(struct mempool *mp, void *addr, unsigned size, - void *e_addr, size_t e_size) -{ - if (!mp->commit) - return 1; - if (!mp->commit(addr, size)) { - smerror(mp, "SMALLOC: failed to commit %p %i\n", addr, size); - if (e_size) - sm_uncommit(mp, e_addr, e_size); - return 0; - } - return 1; -} - -static int sm_commit(struct mempool *mp, void *addr, size_t size, - void *e_addr, size_t e_size) -{ - /* align address down and align up size */ - uintptr_t a = (uintptr_t)addr; - uintptr_t aa = a & _PAGE_MASK; - size_t aligned_size = PAGE_ALIGN(size + (a - aa)); - void *aligned_addr = (void *)aa; - int ok = __sm_commit(mp, aligned_addr, aligned_size, e_addr, e_size); - if (ok) { - assert(mp->avail >= size); - mp->avail -= size; - } - return ok; -} - -static int sm_commit_simple(struct mempool *mp, void *addr, size_t size) -{ - return sm_commit(mp, addr, size, NULL, 0); -} - -static void mntruncate(struct memnode *pmn, size_t size) -{ - int delta = pmn->size - size; - - if (delta == 0) - return; - /* delta can be < 0 */ - if (pmn->next && !pmn->next->used) { - struct memnode *nmn = pmn->next; - - assert(size > 0 && nmn->size + delta >= 0); - - nmn->size += delta; - nmn->mem_area -= delta; - pmn->size -= delta; - if (nmn->size == 0) { - pmn->next = nmn->next; - free(nmn); - assert(!pmn->next || pmn->next->used); - } - } else { - struct memnode *new_mn; - - assert(size < pmn->size); - - new_mn = (struct memnode *)malloc(sizeof(struct memnode)); - new_mn->next = pmn->next; - new_mn->size = delta; - new_mn->used = 0; - new_mn->mem_area = pmn->mem_area + size; - - pmn->next = new_mn; - pmn->size = size; - } -} - -static struct memnode *find_mn(struct mempool *mp, unsigned char *ptr, - struct memnode **prev) -{ - struct memnode *pmn, *mn; - if (!POOL_USED(mp)) { - smerror(mp, "SMALLOC: unused pool passed\n"); - return NULL; - } - for (pmn = NULL, mn = &mp->mn; mn; pmn = mn, mn = mn->next) { - if (mn->mem_area > ptr) - return NULL; - if (mn->mem_area == ptr) { - if (prev) - *prev = pmn; - return mn; - } - } - return NULL; -} - -static struct memnode *find_mn_at(struct mempool *mp, unsigned char *ptr) -{ - struct memnode *mn; - for (mn = &mp->mn; mn; mn = mn->next) { - if (mn->mem_area > ptr) - return NULL; - if (mn->mem_area + mn->size > ptr) - return mn; - } - return NULL; -} - -static struct memnode *smfind_free_area(struct mempool *mp, size_t size) -{ - struct memnode *mn; - for (mn = &mp->mn; mn; mn = mn->next) { - if (!mn->used && mn->size >= size) - return mn; - } - return NULL; -} - -static struct memnode *smfind_free_area_topdown(struct mempool *mp, - unsigned char *top, size_t size) -{ - struct memnode *mn; - struct memnode *mn1 = NULL; - for (mn = &mp->mn; mn; mn = mn->next) { - if (top && mn->mem_area + size > top) - break; - if (!mn->used && mn->size >= size) - mn1 = mn; - } - return mn1; -} - -static struct memnode *sm_alloc_fixed(struct mempool *mp, void *ptr, - unsigned size) -{ - struct memnode *mn; - ptrdiff_t delta; - if (!size || !ptr) { - smerror(mp, "SMALLOC: zero-sized allocation attempted\n"); - return NULL; - } - if (!(mn = find_mn_at(mp, (unsigned char *)ptr))) { - smerror(mp, "SMALLOC: invalid address %p on alloc_fixed\n", ptr); - return NULL; - } - if (mn->used) { - do_smerror(0, mp, "SMALLOC: address %p already allocated\n", ptr); - return NULL; - } - delta = (uint8_t *)ptr - mn->mem_area; - assert(delta >= 0); - if ((unsigned)(size + delta) > mn->size) { - int pr = get_oom_pr(mp, size); - if (pr < 0) - pr = 0; - do_smerror(pr, mp, "SMALLOC: no space %i at address %p\n", size, ptr); - return NULL; - } - if (delta) { - mntruncate(mn, delta); - mn = mn->next; - assert(!mn->used && mn->size >= size); - } - if (!sm_commit_simple(mp, mn->mem_area, size)) - return NULL; - mn->used = 1; - mntruncate(mn, size); - assert(mn->size == size); - memset(mn->mem_area, 0, size); - return mn; -} - -static struct memnode *sm_alloc_aligned(struct mempool *mp, size_t align, - unsigned size) -{ - struct memnode *mn; - int delta; - uintptr_t iptr; - if (!size) { - smerror(mp, "SMALLOC: zero-sized allocation attempted\n"); - return NULL; - } - /* power of 2 align */ - assert(__builtin_popcount(align) == 1); - align--; - if (!(mn = smfind_free_area(mp, size + align))) { - do_smerror(get_oom_pr(mp, size), mp, - "SMALLOC: Out Of Memory on alloc, requested=%u\n", size); - return NULL; - } - /* insert small node to align the start */ - iptr = (uintptr_t)mn->mem_area; - delta = ((iptr | align) - iptr + 1) & align; - if (delta) { - mntruncate(mn, delta); - mn = mn->next; - assert(!mn->used && mn->size >= size); - } - if (!sm_commit_simple(mp, mn->mem_area, size)) - return NULL; - mn->used = 1; - mntruncate(mn, size); - assert(mn->size == size); - memset(mn->mem_area, 0, size); - return mn; -} - -static struct memnode *sm_alloc_mn(struct mempool *mp, size_t size) -{ - return sm_alloc_aligned(mp, 1, size); -} - -static struct memnode *sm_alloc_aligned_topdown(struct mempool *mp, - unsigned char *top, size_t align, unsigned size) -{ - struct memnode *mn; - int delta; - uintptr_t iptr; - uintptr_t min_top; - uintptr_t iend; - if (!size) { - smerror(mp, "SMALLOC: zero-sized allocation attempted\n"); - return NULL; - } - /* power of 2 align */ - assert(__builtin_popcount(align) == 1); - align--; - if (!(mn = smfind_free_area_topdown(mp, top, size + align))) { - do_smerror(get_oom_pr(mp, size), mp, - "SMALLOC: Out Of Memory on alloc, requested=%u\n", size); - return NULL; - } - /* use top part of the found area */ - min_top = (uintptr_t)mn->mem_area + mn->size; - if (top) - min_top = _min(min_top, (uintptr_t)top); - iptr = (min_top - size) & ~align; - iend = iptr + size; - delta = (uintptr_t)mn->mem_area + mn->size - iend; - if (delta) - mntruncate(mn, mn->size - delta); - assert(iptr >= (uintptr_t)mn->mem_area); - delta = iptr - (uintptr_t)mn->mem_area; - if (delta) { - mntruncate(mn, delta); - mn = mn->next; - assert(!mn->used && mn->size >= size); - } - if (!sm_commit_simple(mp, mn->mem_area, size)) - return NULL; - mn->used = 1; - mntruncate(mn, size); - assert(mn->size == size); - memset(mn->mem_area, 0, size); - return mn; -} - -static struct memnode *sm_alloc_topdown(struct mempool *mp, size_t size) -{ - return sm_alloc_aligned_topdown(mp, NULL, 1, size); -} - -void *smalloc(struct mempool *mp, size_t size) -{ - struct memnode *mn = sm_alloc_mn(mp, size); - if (!mn) - return NULL; - return mn->mem_area; -} - -void *smalloc_fixed(struct mempool *mp, void *ptr, size_t size) -{ - struct memnode *mn = sm_alloc_fixed(mp, ptr, size); - if (!mn) - return NULL; - assert(mn->mem_area == ptr); - return mn->mem_area; -} - -void *smalloc_aligned(struct mempool *mp, size_t align, size_t size) -{ - struct memnode *mn = sm_alloc_aligned(mp, align, size); - if (!mn) - return NULL; - assert(((uintptr_t)mn->mem_area & (align - 1)) == 0); - return mn->mem_area; -} - -void *smalloc_topdown(struct mempool *mp, size_t size) -{ - struct memnode *mn = sm_alloc_topdown(mp, size); - if (!mn) - return NULL; - return mn->mem_area; -} - -void *smalloc_aligned_topdown(struct mempool *mp, unsigned char *top, - size_t align, size_t size) -{ - struct memnode *mn = sm_alloc_aligned_topdown(mp, top, align, size); - if (!mn) - return NULL; - assert(((uintptr_t)mn->mem_area & (align - 1)) == 0); - return mn->mem_area; -} - -int smfree(struct mempool *mp, void *ptr) -{ - struct memnode *mn, *pmn; - if (!ptr) - return -1; - if (!(mn = find_mn(mp, (unsigned char *)ptr, &pmn))) { - smerror(mp, "SMALLOC: bad pointer passed to smfree()\n"); - return -1; - } - if (!mn->used) { - smerror(mp, "SMALLOC: attempt to free the not allocated region (double-free)\n"); - return -1; - } - assert(mn->size > 0); - sm_uncommit(mp, mn->mem_area, mn->size); - mn->used = 0; - if (mn->next && !mn->next->used) { - /* merge with next */ - assert(mn->next->mem_area >= mn->mem_area); - mntruncate(mn, mn->size + mn->next->size); - } - if (pmn && !pmn->used) { - /* merge with prev */ - assert(pmn->mem_area <= mn->mem_area); - mntruncate(pmn, pmn->size + mn->size); - mn = pmn; - } - return 0; -} - -/* part of smrealloc() that covers the cases where the - * extra memnode needs to be allocated for realloc */ -static struct memnode *sm_realloc_alloc_mn(struct mempool *mp, - struct memnode *pmn, struct memnode *mn, - struct memnode *nmn, unsigned size) -{ - struct memnode *new_mn; - if (pmn && !pmn->used && pmn->size + mn->size + - (nmn->used ? 0 : nmn->size) >= size) { - /* move to prev memnode */ - size_t psize = _min(size, pmn->size); - if (!sm_commit_simple(mp, pmn->mem_area, psize)) - return NULL; - if (size > pmn->size + mn->size) { - if (!sm_commit(mp, nmn->mem_area, size - pmn->size - mn->size, - pmn->mem_area, psize)) - return NULL; - } - pmn->used = 1; - memmove(pmn->mem_area, mn->mem_area, mn->size); - memset(pmn->mem_area + mn->size, 0, size - mn->size); - mn->used = 0; - if (size < pmn->size + mn->size) { - size_t overl = size > pmn->size ? size - pmn->size : 0; - sm_uncommit(mp, mn->mem_area + overl, mn->size - overl); - } - if (!nmn->used) // merge with next - mntruncate(mn, mn->size + nmn->size); - mntruncate(pmn, size); - new_mn = pmn; - } else { - /* relocate */ - new_mn = sm_alloc_mn(mp, size); - if (!new_mn) { - do_smerror(get_oom_pr(mp, size), mp, - "SMALLOC: Out Of Memory on realloc, requested=%u\n", size); - return NULL; - } - memcpy(new_mn->mem_area, mn->mem_area, mn->size); - smfree(mp, mn->mem_area); - } - return new_mn; -} - -void *smrealloc(struct mempool *mp, void *ptr, size_t size) -{ - struct memnode *mn, *pmn; - if (!ptr) - return smalloc(mp, size); - if (!(mn = find_mn(mp, (unsigned char *)ptr, &pmn))) { - smerror(mp, "SMALLOC: bad pointer passed to smrealloc()\n"); - return NULL; - } - if (!mn->used) { - smerror(mp, "SMALLOC: attempt to realloc the not allocated region\n"); - return NULL; - } - if (size == 0) { - smfree(mp, ptr); - return NULL; - } - if (size == mn->size) - return ptr; - if (size < mn->size) { - /* shrink */ - sm_uncommit(mp, mn->mem_area + size, mn->size - size); - mntruncate(mn, size); - } else { - /* grow */ - struct memnode *nmn = mn->next; - if (nmn && !nmn->used && mn->size + nmn->size >= size) { - /* expand by shrinking next memnode */ - if (!sm_commit_simple(mp, nmn->mem_area, size - mn->size)) - return NULL; - memset(nmn->mem_area, 0, size - mn->size); - mntruncate(mn, size); - } else { - /* need to allocate new memnode */ - mn = sm_realloc_alloc_mn(mp, pmn, mn, nmn, size); - if (!mn) - return NULL; - } - } - assert(mn->size == size); - return mn->mem_area; -} - -void *smrealloc_aligned(struct mempool *mp, void *ptr, int align, size_t size) -{ - struct memnode *mn, *pmn; - assert(__builtin_popcount(align) == 1); - if (!ptr) - return smalloc_aligned(mp, align, size); - if (!(mn = find_mn(mp, (unsigned char *)ptr, &pmn))) { - smerror(mp, "SMALLOC: bad pointer passed to smrealloc()\n"); - return NULL; - } - if (!mn->used) { - smerror(mp, "SMALLOC: attempt to realloc the not allocated region\n"); - return NULL; - } - if (size == 0) { - smfree(mp, ptr); - return NULL; - } - if (size == mn->size) - return ptr; - if ((uintptr_t)mn->mem_area & (align - 1)) { - smerror(mp, "SMALLOC: unaligned pointer passed to smrealloc_aligned()\n"); - return NULL; - } - if (size < mn->size) { - /* shrink */ - sm_uncommit(mp, mn->mem_area + size, mn->size - size); - mntruncate(mn, size); - } else { - /* grow */ - struct memnode *nmn = mn->next; - if (nmn && !nmn->used && mn->size + nmn->size >= size) { - /* expand by shrinking next memnode */ - if (!sm_commit_simple(mp, nmn->mem_area, size - mn->size)) - return NULL; - memset(nmn->mem_area, 0, size - mn->size); - mntruncate(mn, size); - } else { - /* lazy impl */ - struct memnode *new_mn = sm_alloc_aligned(mp, align, size); - if (!new_mn) - return NULL; - memcpy(new_mn->mem_area, mn->mem_area, mn->size); - smfree(mp, mn->mem_area); - } - } - assert(mn->size == size); - return mn->mem_area; -} - -int sminit(struct mempool *mp, void *start, size_t size) -{ - mp->size = size; - mp->mn.size = size; - mp->mn.used = 0; - mp->mn.next = NULL; - mp->mn.mem_area = (unsigned char *)start; - mp->avail = size; - mp->commit = NULL; - mp->uncommit = NULL; - mp->smerr = smerr; - return 0; -} - -static int do_sminit_com(struct mempool *mp, void *start, size_t size, - int (*commit)(void *area, size_t size), - int (*uncommit)(void *area, size_t size), int do_uncommit) -{ - sminit(mp, start, size); - mp->commit = commit; - mp->uncommit = uncommit; - if (uncommit && do_uncommit) - uncommit(start, size); - return 0; -} - -int sminit_com(struct mempool *mp, void *start, size_t size, - int (*commit)(void *area, size_t size), - int (*uncommit)(void *area, size_t size)) -{ - return do_sminit_com(mp, start, size, commit, uncommit, 1); -} - -int sminit_comu(struct mempool *mp, void *start, size_t size, - int (*commit)(void *area, size_t size), - int (*uncommit)(void *area, size_t size)) -{ - return do_sminit_com(mp, start, size, commit, uncommit, 0); -} - -void smfree_all(struct mempool *mp) -{ - struct memnode *mn; - while (POOL_USED(mp)) { - mn = &mp->mn; - if (!mn->used) - mn = mn->next; - assert(mn && mn->used); - smfree(mp, mn->mem_area); - } - assert(!mp->mn.next); -} - -int smdestroy(struct mempool *mp) -{ - unsigned avail = mp->avail; - - smfree_all(mp); - assert(mp->mn.size >= avail); - /* return leaked size */ - return mp->mn.size - avail; -} - -size_t smget_free_space(struct mempool *mp) -{ - return mp->avail; -} - -size_t smget_free_space_upto(struct mempool *mp, unsigned char *top) -{ - struct memnode *mn; - int cnt = 0; - for (mn = &mp->mn; mn; mn = mn->next) { - if (mn->mem_area + mn->size > top) { - if (!mn->used && mn->mem_area < top) - cnt += top - mn->mem_area; - break; - } - if (!mn->used) - cnt += mn->size; - } - return cnt; -} - -size_t smget_largest_free_area(struct mempool *mp) -{ - struct memnode *mn; - size_t size = 0; - for (mn = &mp->mn; mn; mn = mn->next) { - if (!mn->used && mn->size > size) - size = mn->size; - } - return size; -} - -int smget_area_size(struct mempool *mp, void *ptr) -{ - struct memnode *mn; - if (!(mn = find_mn(mp, (unsigned char *)ptr, NULL))) { - smerror(mp, "SMALLOC: bad pointer passed to smget_area_size()\n"); - return -1; - } - return mn->size; -} - -void *smget_base_addr(struct mempool *mp) -{ - return mp->mn.mem_area; -} - -void smregister_error_notifier(struct mempool *mp, - void (*func)(int prio, const char *fmt, ...) FORMAT(printf, 2, 3)) -{ - mp->smerr = func; -} - -void smregister_default_error_notifier( - void (*func)(int prio, const char *fmt, ...) FORMAT(printf, 2, 3)) -{ - smerr = func; -} diff --git a/src/libc/dj64/smalloc.h b/src/libc/dj64/smalloc.h deleted file mode 100644 index e2e6af18..00000000 --- a/src/libc/dj64/smalloc.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * dj64 - 64bit djgpp-compatible tool-chain - * Copyright (C) 2021-2024 @stsp - * - * FDPP - freedos port to modern C++ - * Copyright (C) 2018 Stas Sergeev (stsp) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - */ - -#ifndef __SMALLOC_H -#define __SMALLOC_H - -#include - -#ifndef FORMAT -#define FORMAT(T,A,B) __attribute__((format(T,A,B))) -#endif - -struct memnode { - struct memnode *next; - size_t size; - int used; - unsigned char *mem_area; -}; - -typedef struct mempool { - size_t size; - size_t avail; - struct memnode mn; - int (*commit)(void *area, size_t size); - int (*uncommit)(void *area, size_t size); - void (*smerr)(int prio, const char *fmt, ...) FORMAT(printf, 2, 3); -} smpool; - -void *smalloc(struct mempool *mp, size_t size); -void *smalloc_fixed(struct mempool *mp, void *ptr, size_t size); -int smfree(struct mempool *mp, void *ptr); -void *smalloc_aligned(struct mempool *mp, size_t align, size_t size); -void *smalloc_topdown(struct mempool *mp, size_t size); -void *smalloc_aligned_topdown(struct mempool *mp, unsigned char *top, - size_t align, size_t size); -void *smrealloc(struct mempool *mp, void *ptr, size_t size); -void *smrealloc_aligned(struct mempool *mp, void *ptr, int align, size_t size); -int sminit(struct mempool *mp, void *start, size_t size); -int sminit_com(struct mempool *mp, void *start, size_t size, - int (*commit)(void *area, size_t size), - int (*uncommit)(void *area, size_t size)); -int sminit_comu(struct mempool *mp, void *start, size_t size, - int (*commit)(void *area, size_t size), - int (*uncommit)(void *area, size_t size)); -void smfree_all(struct mempool *mp); -int smdestroy(struct mempool *mp); -size_t smget_free_space(struct mempool *mp); -size_t smget_free_space_upto(struct mempool *mp, unsigned char *top); -size_t smget_largest_free_area(struct mempool *mp); -int smget_area_size(struct mempool *mp, void *ptr); -void *smget_base_addr(struct mempool *mp); -void smregister_error_notifier(struct mempool *mp, - void (*func)(int prio, const char *fmt, ...) FORMAT(printf, 2, 3)); -void smregister_default_error_notifier( - void (*func)(int prio, const char *fmt, ...) - FORMAT(printf, 2, 3)); -void smdump(struct mempool *mp); - -#endif