From 167b12255fc69bcf912e460e19d05041c0d8e842 Mon Sep 17 00:00:00 2001 From: Maxim Logaev Date: Fri, 2 Jan 2026 21:50:17 +0300 Subject: [PATCH] newlib: Impl sbrk() emulation for malloc/free - Added malloc test; - Test sources are now in one dir. Signed-off-by: Maxim Logaev --- CMakeLists.txt | 14 +++- .../newlib/newlib/libc/sys/kolibrios/sbrk.c | 69 ++++++++++++++++--- tests/CMakeLists.txt | 21 +++--- tests/hello.c | 10 +++ tests/hello/CMakeLists.txt | 5 -- tests/hello/hello.c | 13 ---- tests/malloc.c | 45 ++++++++++++ 7 files changed, 134 insertions(+), 43 deletions(-) create mode 100644 tests/hello.c delete mode 100644 tests/hello/CMakeLists.txt delete mode 100644 tests/hello/hello.c create mode 100644 tests/malloc.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 4561a60efe..6723a322d0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,4 +26,16 @@ message(STATUS "SDK_SYSROOT_DIR=${KOS_PORTS_DIR}") add_subdirectory(toolchain) add_subdirectory(libraries) -add_subdirectory(tests) + +ExternalProject_Add( + tests + SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/tests + CMAKE_ARGS + -DCMAKE_C_COMPILER=i586-kolibrios-gcc + -DCMAKE_C_COMPILER_WORKS=1 + -DCMAKE_INSTALL_PREFIX=${KOS_PORTS_DIR} + BUILD_ALWAYS TRUE + DEPENDS + gcc + newlib +) diff --git a/libraries/newlib/newlib/libc/sys/kolibrios/sbrk.c b/libraries/newlib/newlib/libc/sys/kolibrios/sbrk.c index 45b24c93d8..508b99f168 100644 --- a/libraries/newlib/newlib/libc/sys/kolibrios/sbrk.c +++ b/libraries/newlib/newlib/libc/sys/kolibrios/sbrk.c @@ -1,20 +1,67 @@ -/* Version of sbrk for no operating system. */ +/* + * SPDX-License-Identifier: GPL-2.0-only + * Copyright (C) 2026 KolibriOS team + * Author: Maxim Logaev + */ #include <_syslist.h> +#include + +#include + +static struct +{ + char *start; + unsigned long brk; + // TODO: Add mutex +} heap; void * -_sbrk (incr) - int incr; +_sbrk (long incr) { - extern char end; /* Set by linker. */ - static char * heap_end; - char * prev_heap_end; + unsigned long new_brk = 0; + void *brk_addr = (void *)-1; - if (heap_end == 0) - heap_end = & end; +#if 0 + fprintf(stderr, "sbrk: start=%p, brk=%lu, incr=%ld\n", heap.start, heap.brk, incr); +#endif - prev_heap_end = heap_end; - heap_end += incr; + // TODO: Mutex lock; - return (void *) prev_heap_end; + if (incr == 0) + { + brk_addr = heap.start + heap.brk; + goto ok; + } + + if (incr < 0) + { + if (__builtin_usubl_overflow (heap.brk, (unsigned long)(-incr), + &new_brk)) + new_brk = 0; + } + else + { + if (__builtin_uaddl_overflow (heap.brk, (unsigned long)incr, &new_brk)) + goto fail; + } + + char *const new_start = (char *)_ksys (SF_SYS_MISC, SSF_MEM_REALLOC, new_brk, + (unsigned long)heap.start); + + if (new_start == NULL && new_brk) + goto fail; + + brk_addr = new_start + heap.brk; + heap.brk = new_brk; + heap.start = new_start; + +ok: + // TODO: Mutex unlock + return brk_addr; + +fail: + // TODO: Mutex unlock + errno = ENOMEM; + return (void *)-1; } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index a305f2bd3c..785a8d6b9a 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,14 +1,9 @@ -# Rules for building tests +cmake_minimum_required(VERSION 3.31) -ExternalProject_Add( - test-hello - SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/hello - CMAKE_ARGS - -DCMAKE_C_COMPILER=i586-kolibrios-gcc - -DCMAKE_C_COMPILER_WORKS=1 - -DCMAKE_INSTALL_PREFIX=${KOS_PORTS_DIR} - BUILD_ALWAYS TRUE - DEPENDS - gcc - newlib -) +project(tests) + +add_executable(hello hello.c) +add_executable(malloc malloc.c) + +install(TARGETS hello DESTINATION tests) +install(TARGETS malloc DESTINATION tests) diff --git a/tests/hello.c b/tests/hello.c new file mode 100644 index 0000000000..f4ff331fc4 --- /dev/null +++ b/tests/hello.c @@ -0,0 +1,10 @@ +#include +#include + +int +main () +{ + errno = ENOSYS; + puts ("I: Hello KolibriOS from GCC!"); + return 0; +} diff --git a/tests/hello/CMakeLists.txt b/tests/hello/CMakeLists.txt deleted file mode 100644 index a6c905a96f..0000000000 --- a/tests/hello/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -cmake_minimum_required(VERSION 3.31) - -project(hello) -add_executable(hello hello.c) -install(TARGETS hello DESTINATION tests) diff --git a/tests/hello/hello.c b/tests/hello/hello.c deleted file mode 100644 index 45cca40854..0000000000 --- a/tests/hello/hello.c +++ /dev/null @@ -1,13 +0,0 @@ -/* - * SPDX-License-Identifier: GPL-2.0 - * Copyright (C) 2025 KolibriOS team -*/ - -int main() -{ - char *hello = "I: Hello KolibriOS from GCC!\n"; - while(*hello) { - __asm__ __inline__("int $0x40" ::"a"(63), "b"(1), "c"(*hello)); - hello++; - } -} diff --git a/tests/malloc.c b/tests/malloc.c new file mode 100644 index 0000000000..689a9438d8 --- /dev/null +++ b/tests/malloc.c @@ -0,0 +1,45 @@ +#include +#include +#include +#include + +#include + +#define MAX_ALLOCS 10000 + +int +main () +{ + void *allocs[MAX_ALLOCS] = { 0 }; + + // Check zero param + void *ptr = malloc (0); + free (ptr); + free (NULL); + + // malloc() and free() + for (size_t i = 0; i < 1000; i++) + { + void *ptr = malloc (9999); + memset (ptr, 0xFF, 9999); + assert (ptr != NULL); + free (ptr); + } + + // malloc() + for (size_t i = 0; i < MAX_ALLOCS; i++) + { + allocs[i] = malloc (9999); + assert (allocs[i] != NULL); + memset (allocs[i], 0xFF, 9999); + } + + // free() + for (size_t i = 0; i < MAX_ALLOCS; i++) + { + free(allocs[i]); + } + + _ksys_dbg_print("I: Malloc test: OK"); + return 0; +}