From 88fe2c6718c3c0198edfa785bf66e53b0ffe2a25 Mon Sep 17 00:00:00 2001 From: Liviu Ionescu Date: Fri, 22 Jul 2022 19:48:01 +0300 Subject: [PATCH] #8: move exit() and _sbrk() here --- src/_sbrk.c | 92 +++++++++++++++++++++++++++++++++++ src/exit.c | 136 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 228 insertions(+) create mode 100644 src/_sbrk.c create mode 100644 src/exit.c diff --git a/src/_sbrk.c b/src/_sbrk.c new file mode 100644 index 0000000..8215ff4 --- /dev/null +++ b/src/_sbrk.c @@ -0,0 +1,92 @@ +/* + * This file is part of the µOS++ distribution. + * (https://github.com/micro-os-plus/) + * Copyright (c) 2015 Liviu Ionescu. + * + * Permission to use, copy, modify, and/or distribute this software + * for any purpose is hereby granted, under the terms of the MIT license. + * + * If a copy of the license was not distributed with this file, it can + * be obtained from https://opensource.org/licenses/MIT/. + */ + +#if (!(defined(__APPLE__) || defined(__linux__) || defined(__unix__))) \ + || defined(__DOXYGEN__) + +// ---------------------------------------------------------------------------- + +#if defined(MICRO_OS_PLUS_INCLUDE_CONFIG_H) +#include +#endif // MICRO_OS_PLUS_INCLUDE_CONFIG_H + +#if defined(MICRO_OS_PLUS_INCLUDE_SBRK) + +#include +#include +#include +#include +#include + +// ---------------------------------------------------------------------------- + +void* +_sbrk (ptrdiff_t incr); + +// ---------------------------------------------------------------------------- + +// The definitions used here should be kept in sync with the +// stack definitions in the linker script. + +extern uint32_t __heap_begin__; // Defined by the linker. +extern uint32_t __heap_end__; // Defined by the linker. + +#if defined(MICRO_OS_PLUS_USE_SEMIHOSTING) +// Heap limit returned from SYS_HEAPINFO semihosting call. +char* __heap_limit = (char*)0xCAFEDEAD; +#endif // MICRO_OS_PLUS_USE_SEMIHOSTING + +void* +_sbrk (ptrdiff_t incr) +{ + static char* current_heap_end; // STATIC! Zero after BSS init. + char* current_block_address; + + if (current_heap_end == 0) + { + current_heap_end = (char*)&__heap_begin__; + } + + current_block_address = current_heap_end; + + // Need to align heap to word boundary, for efficiency reasons and + // to possibly avoid hardware faults. + // So we assume that the heap starts on word boundary, + // hence make sure we always add a multiple of 4 to it. + incr = (incr + 3) & (~3); // align value to 4 + if ((current_heap_end + incr > (char*)&__heap_end__) +#if defined(MICRO_OS_PLUS_USE_SEMIHOSTING) + // Honour heap limit if it's valid. + || (__heap_limit != (char*)0xCAFEDEAD + && current_heap_end + incr > __heap_limit) +#endif // MICRO_OS_PLUS_USE_SEMIHOSTING + ) + { + // Some of the libstdc++-v3 tests rely upon detecting 'out of memory' + // errors, so DO NOT abort here, but return error. + + errno = ENOMEM; // Heap has overflowed. + return (caddr_t)-1; + } + + current_heap_end += incr; + + return (caddr_t)current_block_address; +} + +#endif // defined(MICRO_OS_PLUS_INCLUDE_SBRK) + +// ---------------------------------------------------------------------------- + +#endif // !Unix + +// ---------------------------------------------------------------------------- diff --git a/src/exit.c b/src/exit.c new file mode 100644 index 0000000..e126a20 --- /dev/null +++ b/src/exit.c @@ -0,0 +1,136 @@ +/* + * This file is part of the µOS++ distribution. + * (https://github.com/micro-os-plus/) + * Copyright (c) 2015 Liviu Ionescu. + * + * Permission to use, copy, modify, and/or distribute this software + * for any purpose is hereby granted, under the terms of the MIT license. + * + * If a copy of the license was not distributed with this file, it can + * be obtained from https://opensource.org/licenses/MIT/. + */ + +#if (!(defined(__APPLE__) || defined(__linux__) || defined(__unix__))) \ + || defined(__DOXYGEN__) + +// ---------------------------------------------------------------------------- + +#if defined(MICRO_OS_PLUS_INCLUDE_CONFIG_H) +#include +#endif // MICRO_OS_PLUS_INCLUDE_CONFIG_H + +#include +#include +#include + +#include +#include + +extern void +micro_os_plus_run_fini_array (void); + +extern void +__call_exitprocs (int, void*); + +// ---------------------------------------------------------------------------- + +void __attribute__ ((weak, noreturn)) abort (void) +{ + trace_puts ("abort(), exiting..."); + + _Exit (1); + /* NOTREACHED */ +} + +// ---------------------------------------------------------------------------- + +/** + * @details + * `exit()` does several cleanups before ending the application: + * + * - calls all application-defined cleanup functions enrolled with `atexit()`; + * - files and streams are + * cleaned up: any pending output is delivered to the host system, each + * open file or stream is closed, and files created by `tmpfile()` are + * deleted (wishful thinking, not implemented); + * - call the static destructors (in reverse order of constructors) + * + * When all cleanups are done, `_Exit()` is called to perform + * the actual termination. + */ +void __attribute__ ((noreturn)) exit (int code) +{ + trace_printf ("%s(%d)\n", __func__, code); + + // Call the cleanup functions enrolled with atexit(). + __call_exitprocs (code, NULL); + + // Run the C++ static destructors. + micro_os_plus_run_fini_array (); + + // This should normally be the end of it. + _Exit (code); + + // Reset again, in case _Exit() did not kill it. + // This normally should not happen, but since it can be + // overloaded by the application, better safe than sorry. + micro_os_plus_terminate (code); + +#if defined(MICRO_OS_PLUS_DEBUG) + micro_os_plus_architecture_brk (); +#endif // defined(MICRO_OS_PLUS_DEBUG) + // If it does not want to die, loop. + while (true) + { + micro_os_plus_architecture_wfi (); + } + /* NOTREACHED */ +} + +// ---------------------------------------------------------------------------- + +#pragma GCC diagnostic push +//#pragma GCC diagnostic ignored "-Wunused-parameter" +// arm-none-eabi/include/stdlib.h:202:6: note: '_exit' target declared here +// 202 | void _Exit (int __status) _ATTRIBUTE ((__noreturn__)); +#pragma GCC diagnostic ignored "-Wmissing-attributes" + +// On Release, call the hardware reset procedure. +// On Debug, use a breakpoint to notify the debugger. +// +// It can be redefined by the application, if more functionality +// is required. For example, when semihosting is used, this +// function sends the return code to the host. + +void __attribute__ ((weak, noreturn)) _Exit (int code) +{ + trace_printf ("%s(%d)\n", __func__, code); + + // Print some statistics about memory use. + micro_os_plus_terminate_goodbye (); + + // Gracefully terminate the trace session. + trace_flush (); + + // Reset hardware or terminate the semihosting session. + micro_os_plus_terminate (code); + +#if defined(MICRO_OS_PLUS_DEBUG) + micro_os_plus_architecture_brk (); +#endif // defined(MICRO_OS_PLUS_DEBUG) + while (true) + { + micro_os_plus_architecture_wfi (); + } + /* NOTREACHED */ +} + +void __attribute__ ((weak, noreturn, alias ("_Exit"))) _exit (int status); + +#pragma GCC diagnostic pop + +// ---------------------------------------------------------------------------- + +#endif // !Unix + +// ----------------------------------------------------------------------------