Skip to content

Commit

Permalink
#8: move exit() and _sbrk() here
Browse files Browse the repository at this point in the history
  • Loading branch information
ilg-ul committed Jul 22, 2022
1 parent 0ed8089 commit 88fe2c6
Show file tree
Hide file tree
Showing 2 changed files with 228 additions and 0 deletions.
92 changes: 92 additions & 0 deletions src/_sbrk.c
Original file line number Diff line number Diff line change
@@ -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 <micro-os-plus/config.h>
#endif // MICRO_OS_PLUS_INCLUDE_CONFIG_H

#if defined(MICRO_OS_PLUS_INCLUDE_SBRK)

#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <errno.h>
#include <stddef.h>

// ----------------------------------------------------------------------------

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

// ----------------------------------------------------------------------------
136 changes: 136 additions & 0 deletions src/exit.c
Original file line number Diff line number Diff line change
@@ -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 <micro-os-plus/config.h>
#endif // MICRO_OS_PLUS_INCLUDE_CONFIG_H

#include <micro-os-plus/startup/hooks.h>
#include <micro-os-plus/architecture.h>
#include <micro-os-plus/diag/trace.h>

#include <stdlib.h>
#include <stdbool.h>

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

// ----------------------------------------------------------------------------

0 comments on commit 88fe2c6

Please sign in to comment.