diff --git a/CMakeLists.txt b/CMakeLists.txt index df5a90a..fb19d05 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -106,6 +106,9 @@ set(SOURCES # locale src/libc/locale/setlocale.c src/libc/locale/localeconv.c + # signal + src/libc/signal/signal.c + src/libc/signal/raise.c # stdio src/libc/stdio/vsnprintf.c src/libc/stdio/sprintf.c @@ -121,6 +124,7 @@ set(SOURCES src/libc/stdio/vdprintf.c src/libc/stdio/printf.c # stdlib + src/libc/stdlib/abort.c src/libc/stdlib/abs.c src/libc/stdlib/atof.c src/libc/stdlib/atoi.c diff --git a/STATUS b/STATUS index 4a7db56..3de77b1 100644 --- a/STATUS +++ b/STATUS @@ -34,7 +34,7 @@ TEST: Function/symbol/macro needs to be tested DONE: Function/symbol/macro is defined, builds, links, and is tested 7.2 -! 7.2.1 assert: LDEPS(fprintf,stderr,abort) +! 7.2.1 assert: LDEPS(fprintf,stderr) 7.3 => OpenLibm @@ -72,9 +72,10 @@ DONE: Function/symbol/macro is defined, builds, links, and is tested 7.13.2 longjmp: DONE 7.14 -! 7.14.1 Macros and stuff: TODO -! 7.14.1.1 signal: TODO -! 7.14.1.2 raise: TODO + 7.14 sig_atomic_t SIG_DFL SIG_ERR SIG_IGN: DONE + 7.14 SIGABRT SIGFPE SIGILL SIGINT SIGSEGV SIGTERM: DONE + 7.14.1.1 signal: DONE + 7.14.1.2 raise: DONE 7.15 => GCC @@ -102,7 +103,7 @@ DONE: Function/symbol/macro is defined, builds, links, and is tested 7.20.1.4 strtol, strtoul, strtoll, strtoull: DONE ! 7.20.2 Pseudo-random sequence generation functions: TODO ! 7.20.3 Memory management functions: TODO (check existing code first) -! 7.20.4.1 abort: BDEPS(raise) + 7.20.4.1 abort: DONE ! 7.20.4.2 atexit: TODO 7.20.4.3 exit: DONE (missing stream flushing/closing/etc) 7.20.4.4 _Exit: DONE (gint only) diff --git a/include/signal.h b/include/signal.h index be133bb..17f7405 100644 --- a/include/signal.h +++ b/include/signal.h @@ -3,38 +3,49 @@ #include #include +#include + +/* C99 API. */ + +typedef volatile atomic_int sig_atomic_t; + +/* Type of a signal handler.*/ +typedef void (*__sighandler_t)(int); #include +/* Set the handler for __signum. */ +extern __sighandler_t signal(int __signum, __sighandler_t __handler); + +/* Raise signal __signum. */ +extern int raise(int __signum); + +/* POSIX API (Vhex only). */ + +#ifdef _POSIX_C_SOURCE + /* Type of signal set */ typedef uint32_t sigset_t; typedef uint32_t kernel_sigset_t; -/* Type of a signal handler.*/ -typedef void (*__sighandler_t)(int); -typedef __sighandler_t sighandler_t; - /* ** Get the system-specific definitions of `struct sigaction' and the `SA_*' ** and `SIG_*'. constants. */ #include +#include /* Get and/or change the set of blocked signals. */ -extern int sigprocmask (int how, const sigset_t *restrict set, - sigset_t *restrict oldset); +extern int sigprocmask (int __how, const sigset_t *restrict __set, + sigset_t *restrict __oldset); /* ** Send signal SIG to process number PID. If PID is zero, send SIG to all ** processes in the current process's process group. If PID is < -1, send SIG to ** all processes in process group - PID. */ -extern int kill(pid_t pid, int sig); +extern int kill(pid_t __pid, int __sig); -/* -** Set the handler for the signal SIG to HANDLER, returning the old handler, or -** SIG_ERR on error. By default `signal' has the BSD semantic. -*/ -extern void (*signal(int signum, void (*handler)(int)))(int); +#endif /*_POSIX_C_SOURCE*/ #endif /*__SIGNAL_H__*/ diff --git a/include/stdlib.h b/include/stdlib.h index d13e30b..5f68ab0 100644 --- a/include/stdlib.h +++ b/include/stdlib.h @@ -30,6 +30,9 @@ extern void free(void *__ptr); /* Communication with the environment. */ +/* Abort execution; raises SIGABRT and leaves quickly with _Exit(). */ +void abort(void); + /* Exit; calls handlers, flushes and closes streams and temporary files. */ void exit(int __status); diff --git a/include/target/gint/bits/signum.h b/include/target/gint/bits/signum.h new file mode 100644 index 0000000..a340352 --- /dev/null +++ b/include/target/gint/bits/signum.h @@ -0,0 +1,20 @@ +#ifndef __BITS_SIGNUM_H__ +# define __BITS_SIGNUM_H__ + +// Define the number of signals +#define _NSIG 16 + +/* Fake signal functions. */ +#define SIG_ERR ((__sighandler_t) -1) /* Error return. */ +#define SIG_DFL ((__sighandler_t) 0) /* Default action. */ +#define SIG_IGN ((__sighandler_t) 1) /* Ignore signal. */ + +/* ISO C99 signals. */ +#define SIGINT 2 /* Interactive attention signal. */ +#define SIGILL 4 /* Illegal instruction. */ +#define SIGABRT 6 /* Abnormal termination. */ +#define SIGFPE 8 /* Erroneous arithmetic operation. */ +#define SIGSEGV 11 /* Invalid access to storage. */ +#define SIGTERM 15 /* Termination request. */ + +#endif /*__BITS_SIGNUM_H__*/ diff --git a/include/target/vhex-generic/bits/signum.h b/include/target/vhex-generic/bits/signum.h index 36cdb1e..d3e9fca 100644 --- a/include/target/vhex-generic/bits/signum.h +++ b/include/target/vhex-generic/bits/signum.h @@ -2,7 +2,7 @@ # define __BITS_SIGNUM_H__ // Define the number of signals -#define NSIG 32 +#define _NSIG 32 // Vhex kernel internal define used to indicate // if the signal is implemented or not diff --git a/src/libc/signal/raise.c b/src/libc/signal/raise.c new file mode 100644 index 0000000..573c654 --- /dev/null +++ b/src/libc/signal/raise.c @@ -0,0 +1,35 @@ +#include +#include +#include +#include "signal_p.h" + +#ifndef __SUPPORT_VHEX_KERNEL + +int raise(int sig) +{ + if(sig < 0 || sig >= _NSIG) + return 1; + + /* TODO: libc/signal: support signal masks? */ + __sighandler_t handler = signal(sig, SIG_DFL); + + if(handler == SIG_DFL) { + /* Signals that terminate */ + if(sig == SIGINT || sig == SIGTERM) { + exit(128 + sig); + } + /* Signals that abort */ + if(sig == SIGILL || sig == SIGABRT || sig == SIGFPE || + sig == SIGSEGV) { + _Exit(128 + sig); + } + } + else if(handler != SIG_IGN) { + (*handler)(sig); + } + + signal(sig, handler); + return 0; +} + +#endif /*! __SUPPORT_VHEX_KERNEL*/ diff --git a/src/libc/signal/signal.c b/src/libc/signal/signal.c new file mode 100644 index 0000000..bfb10a2 --- /dev/null +++ b/src/libc/signal/signal.c @@ -0,0 +1,19 @@ +#include +#include +#include "signal_p.h" + +#ifndef __SUPPORT_VHEX_KERNEL + +__sighandler_t __signal_handlers[_NSIG] = { 0 }; + +__sighandler_t signal(int signum, __sighandler_t handler) +{ + if(signum < 0 || signum >= _NSIG) + return SIG_ERR; + + __sighandler_t prev = __signal_handlers[signum]; + __signal_handlers[signum] = handler; + return prev; +} + +#endif /*! __SUPPORT_VHEX_KERNEL*/ diff --git a/src/libc/signal/signal_p.h b/src/libc/signal/signal_p.h new file mode 100644 index 0000000..b2b024c --- /dev/null +++ b/src/libc/signal/signal_p.h @@ -0,0 +1,13 @@ +#ifndef __SIGNAL_P_H__ +# define __SIGNAL_P_H__ + +#ifdef __SUPPORT_VHEX_KERNEL + +#include + +/* Handlers for all signals. */ +extern __sighandler_t __signal_handlers[_NSIG]; + +#endif /*! __SUPPORT_VHEX_KERNEL*/ + +#endif /*__SIGNAL_P_H__*/ diff --git a/src/libc/stdlib/abort.c b/src/libc/stdlib/abort.c index 2191df9..39bc40b 100644 --- a/src/libc/stdlib/abort.c +++ b/src/libc/stdlib/abort.c @@ -1,10 +1,11 @@ #include -#include +#include -void abort(int rc) +void abort(void) { /* TODO: Close BFile handles (essential) */ raise(SIGABRT); + /* If the signal handler ever returns, leave on our own */ _Exit(EXIT_FAILURE); }