Mercurial > ecos-v2_0-branch
diff packages/language/c/libc/signals/current/src/siginit.cxx @ 115:6ed91473a1cd ecos-sw-2000-08-21
Merge from eCos master repository on 2000-08-21-22:40:54-BST
| author | jlarmour |
|---|---|
| date | Fri, 25 Aug 2000 17:32:38 +0000 |
| parents | |
| children | e0c0827131d1 |
line wrap: on
line diff
new file mode 100644 --- /dev/null +++ b/packages/language/c/libc/signals/current/src/siginit.cxx @@ -0,0 +1,425 @@ +//======================================================================== +// +// siginit.cxx +// +// ISO C and POSIX 1003.1 signals implementation +// +//======================================================================== +//####COPYRIGHTBEGIN#### +// +// ------------------------------------------- +// The contents of this file are subject to the Red Hat eCos Public License +// Version 1.1 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://www.redhat.com/ +// +// Software distributed under the License is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations under +// the License. +// +// The Original Code is eCos - Embedded Configurable Operating System, +// released September 30, 1998. +// +// The Initial Developer of the Original Code is Red Hat. +// Portions created by Red Hat are +// Copyright (C) 1998, 1999, 2000 Red Hat, Inc. +// All Rights Reserved. +// ------------------------------------------- +// +//####COPYRIGHTEND#### +//======================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): jlarmour +// Contributors: +// Date: 2000-04-18 +// Purpose: Provide implementation of ISO C and POSIX 1003.1 signals +// Description: This file initializes all hardware exceptions, +// initializes the signal handler table and provides the +// default action function for signals +// Usage: +// +//####DESCRIPTIONEND#### +// +//======================================================================== + +// CONFIGURATION + +#include <pkgconf/libc_signals.h> // libc signals configuration + +// INCLUDES + +#include <cyg/infra/cyg_type.h> // Common type definitions and support +#include <signal.h> // Main signals definitions +#include <cyg/infra/cyg_ass.h> // Assertion infrastructure +#include <cyg/infra/cyg_trac.h> // Tracing infrastructure +#include <stdlib.h> // exit() + +#ifdef CYGSEM_LIBC_SIGNALS_HWEXCEPTIONS +# include <pkgconf/kernel.h> // required for kernel includes +# include <cyg/kernel/except.hxx> // Kernel exception API +# include <cyg/kernel/thread.hxx> // Cyg_Thread::self() +# include <cyg/kernel/thread.inl> // inline definitions for above +# include <cyg/kernel/intr.hxx> // Interrupt enable +# include <cyg/hal/hal_intr.h> // HAL interrupt control +#endif + +#ifdef CYGSEM_LIBC_SIGNALS_THREAD_SAFE +# include <pkgconf/kernel.h> // required for kernel includes +# include <cyg/kernel/mutex.hxx> +#endif + +// TYPE DEFINITIONS + +// define dummy class to allow initialization of cyg_libc_signal_handlers + +class Cyg_libc_signals_dummy_init_class { +public: + Cyg_libc_signals_dummy_init_class(); +}; + +#ifdef CYGSEM_LIBC_SIGNALS_HWEXCEPTIONS + +struct exception_signal_mapping_t { + cyg_code exception; + int signal; +}; + +// EXTERNS + +extern cyg_exception_handler cyg_null_exception_handler; + +#endif // ifdef CYGSEM_LIBC_SIGNALS_HWEXCEPTIONS + +// GLOBALS + +// main signal handlers +__sighandler_t cyg_libc_signal_handlers[CYGNUM_LIBC_SIGNALS]; + +#ifdef CYGSEM_LIBC_SIGNALS_THREAD_SAFE +Cyg_Mutex cyg_libc_signal_handlers_mutex CYG_INIT_PRIORITY(LIBC); +#endif + +// STATICS + +// dummy object to invoke constructor +static Cyg_libc_signals_dummy_init_class +cyg_libc_signals_dummy_init_obj CYG_INIT_PRIORITY(LIBC); + +#ifdef CYGSEM_LIBC_SIGNALS_HWEXCEPTIONS + +# ifdef CYGDBG_USE_TRACING +static cyg_uint8 cyg_libc_signals_hwhandler_trace_level = + CYGNUM_LIBC_SIGNALS_HWHANDLER_TRACE_LEVEL; +# define TL1 (0 < cyg_libc_signals_hwhandler_trace_level) +# endif + +# ifdef CYGSEM_LIBC_SIGNALS_CHAIN_HWEXCEPTIONS +// old exception info so we can chain +// FIXME: consider malloced linked list config option +static struct { + cyg_exception_handler *old_handler; + CYG_ADDRWORD old_data; +} exception_chain_data[CYGNUM_HAL_EXCEPTION_COUNT]; +# endif + +// struct that maps exceptions to signals +static const struct exception_signal_mapping_t +exception_signal_mapping[] = { + +#ifdef CYGNUM_HAL_EXCEPTION_DATA_ACCESS + {CYGNUM_HAL_EXCEPTION_DATA_ACCESS, SIGBUS}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_DATA_WRITE + {CYGNUM_HAL_EXCEPTION_DATA_WRITE, SIGBUS}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_CODE_ACCESS + {CYGNUM_HAL_EXCEPTION_CODE_ACCESS, SIGBUS}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_CODE_WRITE + {CYGNUM_HAL_EXCEPTION_CODE_WRITE, SIGBUS}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_CODE_EXECUTE + {CYGNUM_HAL_EXCEPTION_CODE_EXECUTE, SIGBUS}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_IO_ACCESS + {CYGNUM_HAL_EXCEPTION_IO_ACCESS, SIGBUS}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_IO_WRITE + {CYGNUM_HAL_EXCEPTION_IO_ACCESS, SIGBUS}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_DATA_TLBMISS_ACCESS + {CYGNUM_HAL_EXCEPTION_DATA_TLBMISS_ACCESS, SIGSEGV}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_DATA_TLBMISS_WRITE + {CYGNUM_HAL_EXCEPTION_DATA_TLBMISS_WRITE, SIGSEGV}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_CODE_TLBMISS_ACCESS + {CYGNUM_HAL_EXCEPTION_CODE_TLBMISS_ACCESS, SIGSEGV}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_CODE_TLBMISS_WRITE + {CYGNUM_HAL_EXCEPTION_CODE_TLBMISS_WRITE, SIGSEGV}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_DATA_TLBERROR_ACCESS + {CYGNUM_HAL_EXCEPTION_DATA_TLBERROR_ACCESS, SIGSEGV}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_DATA_TLBERROR_WRITE + {CYGNUM_HAL_EXCEPTION_DATA_TLBERROR_WRITE, SIGSEGV}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_CODE_TLBERROR_ACCESS + {CYGNUM_HAL_EXCEPTION_CODE_TLBERROR_ACCESS, SIGSEGV}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_CODE_TLBERROR_WRITE + {CYGNUM_HAL_EXCEPTION_CODE_TLBERROR_WRITE, SIGSEGV}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_DATA_UNALIGNED_ACCESS + {CYGNUM_HAL_EXCEPTION_DATA_UNALIGNED_ACCESS, SIGBUS}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_DATA_UNALIGNED_WRITE + {CYGNUM_HAL_EXCEPTION_DATA_UNALIGNED_WRITE, SIGBUS}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_IO_UNALIGNED_ACCESS + {CYGNUM_HAL_EXCEPTION_IO_UNALIGNED_ACCESS, SIGBUS}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_IO_UNALIGNED_WRITE + {CYGNUM_HAL_EXCEPTION_IO_UNALIGNED_WRITE, SIGBUS}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_ILLEGAL_INSTRUCTION + {CYGNUM_HAL_EXCEPTION_ILLEGAL_INSTRUCTION, SIGILL}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_INTERRUPT + {CYGNUM_HAL_EXCEPTION_INTERRUPT, SIGINT}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_TRAP + {CYGNUM_HAL_EXCEPTION_TRAP, SIGTRAP}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_DIV_BY_ZERO + {CYGNUM_HAL_EXCEPTION_DIV_BY_ZERO, SIGFPE}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_OVERFLOW + {CYGNUM_HAL_EXCEPTION_OVERFLOW, SIGFPE}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_BOUNDS + {CYGNUM_HAL_EXCEPTION_BOUNDS, SIGSEGV}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_SINGLE_STEP + {CYGNUM_HAL_EXCEPTION_SINGLE_STEP, SIGTRAP}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_INSTRUCTION_BP + {CYGNUM_HAL_EXCEPTION_INSTRUCTION_BP, SIGTRAP}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_PERIPHERAL_BP + {CYGNUM_HAL_EXCEPTION_PERIPHERAL_BP, SIGTRAP}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_DATA_BP + {CYGNUM_HAL_EXCEPTION_DATA_BP, SIGTRAP}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_DEVELOPMENT_BP + {CYGNUM_HAL_EXCEPTION_DEVELOPMENT_BP, SIGTRAP}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_STACK_OVERFLOW + {CYGNUM_HAL_EXCEPTION_STACK_OVERFLOW, SIGSEGV}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_STACK_FAULT + {CYGNUM_HAL_EXCEPTION_STACK_FAULT, SIGSEGV}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_PARITY + {CYGNUM_HAL_EXCEPTION_PARITY, SIGBUS}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_FPU + {CYGNUM_HAL_EXCEPTION_FPU, SIGFPE}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_FPU_NOT_AVAIL + {CYGNUM_HAL_EXCEPTION_FPU_NOT_AVAIL, SIGFPE}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_FPU_OVERFLOW + {CYGNUM_HAL_EXCEPTION_FPU_OVERFLOW, SIGFPE}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_FPU_UNDERFLOW + {CYGNUM_HAL_EXCEPTION_FPU_UNDERFLOW, SIGFPE}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_FPU_DIV_BY_ZERO + {CYGNUM_HAL_EXCEPTION_FPU_DIV_BY_ZERO, SIGFPE}, +#endif +#ifdef CYGNUM_HAL_EXCEPTION_SYSTEM_CALL + {CYGNUM_HAL_EXCEPTION_SYSTEM_CALL, SIGSYS}, +#endif + {0, 0} // dummy value to ensure compiler is happy +}; + + +// FUNCTIONS + +///////////////////////////////////////// +// cyg_libc_signals_hwexcept_handler() // +///////////////////////////////////////// + +// FIXME: should be able to get this work with +// CYGSEM_KERNEL_EXCEPTIONS_DECODE disabled as well as enabled +static void +cyg_libc_signals_hwexcept_handler( CYG_ADDRWORD data, cyg_code exception, + CYG_ADDRWORD info) +{ + int signal = (int)data; + int ret; + + CYG_REPORT_FUNCNAME("cyg_libc_signals_hwexcept_handler"); + + CYG_REPORT_FUNCARG3( "data = %08x, exception = %d, info = %08x", + data, exception, info ); + +#ifdef CYGSEM_LIBC_SIGNALS_BAD_SIGNAL_FATAL + CYG_PRECONDITION((signal > 0) && (signal < CYGNUM_LIBC_SIGNALS), + "Signal number not valid!"); +#endif + +// chain first as it may be more useful more low-level stuff needed +#ifdef CYGSEM_LIBC_SIGNALS_CHAIN_HWEXCEPTIONS + // map exception to 0..CYGNUM_HAL_EXCEPTION_COUNT + exception -= CYGNUM_HAL_EXCEPTION_MIN; + + // special case for null handler since it is only for uncaught exceptions + + if (exception_chain_data[exception].old_handler != + cyg_null_exception_handler) { + (*exception_chain_data[exception].old_handler)( + exception_chain_data[exception].old_data, exception, info); + CYG_TRACE0(TL1, "Chained exception handler returned"); + } // if +#endif + +#ifndef CYGSEM_LIBC_SIGNALS_BAD_SIGNAL_FATAL + // if not fatal, silently return + if ((signal <= 0) || (signal >= CYGNUM_LIBC_SIGNALS)) { + CYG_REPORT_RETURN(); + return; + } +#endif + + CYG_TRACE0(TL1, "Enabling interrupts"); + HAL_ENABLE_INTERRUPTS(); + + CYG_TRACE0(TL1, "Raising signal"); + ret = raise(signal); + + if (ret) { + CYG_TRACE1(TL1, "raise() returned non-zero value %d!!!", ret); + } // if + + CYG_REPORT_RETURN(); +} // cyg_libc_signals_hwexcept_handler() + + +////////////////// +// reg_except() // +////////////////// + +static void inline +reg_except( cyg_code exception, int signal ) +{ + Cyg_Thread::self()->register_exception( + exception, &cyg_libc_signals_hwexcept_handler, (CYG_ADDRWORD)signal, +#ifdef CYGSEM_LIBC_SIGNALS_CHAIN_HWEXCEPTIONS + &exception_chain_data[exception - + CYGNUM_HAL_EXCEPTION_MIN].old_handler, + &exception_chain_data[exception - CYGNUM_HAL_EXCEPTION_MIN].old_data +#else + NULL, NULL +#endif + ); + +} // reg_except(); + +#endif // ifdef CYGSEM_LIBC_SIGNALS_HWEXCEPTIONS + +/////////////////////////////////////////////////// +// Cyg_libc_signals_dummy_init_class constructor // +/////////////////////////////////////////////////// + +Cyg_libc_signals_dummy_init_class::Cyg_libc_signals_dummy_init_class() +{ + cyg_ucount8 i; + + CYG_REPORT_FUNCNAME("Cyg_libc_signals_dummy_init_class constructor"); + + // FIXME: some should be SIG_IGN? + for (i=0; i<CYGNUM_LIBC_SIGNALS; i++) + cyg_libc_signal_handlers[i] = SIG_DFL; + +#ifdef CYGSEM_LIBC_SIGNALS_HWEXCEPTIONS + // go through the entire array of exceptions, _but_ subtract 1 for + // the dummy at the end + for (i=0; i < (sizeof(exception_signal_mapping) / + sizeof(exception_signal_mapping_t) - 1); i++) { + CYG_ASSERT( (exception_signal_mapping[i].exception <= + CYGNUM_HAL_EXCEPTION_MAX) && + (exception_signal_mapping[i].exception >= + CYGNUM_HAL_EXCEPTION_MIN), + "Asked to register bad exception"); + + CYG_ASSERT( (exception_signal_mapping[i].signal > 0) && + (exception_signal_mapping[i].signal < + CYGNUM_LIBC_SIGNALS), "Asked to register bad signal" ); + + reg_except( exception_signal_mapping[i].exception, + exception_signal_mapping[i].signal); + } +#endif + + CYG_REPORT_RETURN(); +} // Cyg_libc_signals_dummy_init_class() constructor + + +//////////////////////////////////////// +// cyg_libc_signals_default_handler() // +//////////////////////////////////////// + +// Default signal handler - SIG_DFL +externC void +cyg_libc_signals_default_handler(int sig) +{ + CYG_REPORT_FUNCNAME( "cyg_libc_signals_default_handler" ); + + CYG_REPORT_FUNCARG1( "signal number = %d", sig ); + + exit(1000 + sig); // FIXME + + CYG_REPORT_RETURN(); +} // cyg_libc_signals_default_handler() + +#ifdef CYGSEM_LIBC_SIGNALS_THREAD_SAFE +///////////////////////////////////// +// cyg_libc_signals_lock_do_lock() // +///////////////////////////////////// + +externC cyg_bool +cyg_libc_signals_lock_do_lock(void) +{ + cyg_bool ret; + CYG_REPORT_FUNCNAMETYPE("cyg_libc_signals_lock_do_lock", "returning %d"); + + ret = cyg_libc_signal_handlers_mutex.lock(); + + CYG_REPORT_RETVAL(ret); + + return ret; +} // cyg_libc_signals_lock_do_lock() + +/////////////////////////////////////// +// cyg_libc_signals_lock_do_unlock() // +/////////////////////////////////////// + +externC void +cyg_libc_signals_lock_do_unlock(void) +{ + CYG_REPORT_FUNCNAME("cyg_libc_signals_lock_do_unlock"); + + cyg_libc_signal_handlers_mutex.unlock(); + + CYG_REPORT_RETURN(); +} // cyg_libc_signals_lock_do_unlock() + +#endif // ifdef CYGSEM_LIBC_SIGNALS_THREAD_SAFE + +// EOF siginit.cxx
