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