newlib: Impl sbrk() emulation for malloc/free

- Added malloc test;
- Test sources are now in one dir.

Signed-off-by: Maxim Logaev <maxlogaev@proton.me>
This commit is contained in:
2026-01-02 21:50:17 +03:00
parent d743a7eb35
commit 167b12255f
7 changed files with 134 additions and 43 deletions

View File

@@ -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
)

View File

@@ -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 <maxlogaev@proton.me>
*/
#include <_syslist.h>
#include <errno.h>
#include <kolibrios/syscall.h>
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;
}

View File

@@ -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)

10
tests/hello.c Normal file
View File

@@ -0,0 +1,10 @@
#include <stdio.h>
#include <errno.h>
int
main ()
{
errno = ENOSYS;
puts ("I: Hello KolibriOS from GCC!");
return 0;
}

View File

@@ -1,5 +0,0 @@
cmake_minimum_required(VERSION 3.31)
project(hello)
add_executable(hello hello.c)
install(TARGETS hello DESTINATION tests)

View File

@@ -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++;
}
}

45
tests/malloc.c Normal file
View File

@@ -0,0 +1,45 @@
#include <assert.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <kolibrios/syscall.h>
#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;
}