URL
https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk
Subversion Repositories openrisc_me
[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [compat/] [posix/] [v2_0/] [src/] [except.cxx] - Rev 174
Compare with Previous | Blame | View Log
//========================================================================== // // except.cxx // // POSIX exception translation // //========================================================================== //####ECOSGPLCOPYRIGHTBEGIN#### // ------------------------------------------- // This file is part of eCos, the Embedded Configurable Operating System. // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. // // eCos is free software; you can redistribute it and/or modify it under // the terms of the GNU General Public License as published by the Free // Software Foundation; either version 2 or (at your option) any later version. // // eCos is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License // for more details. // // You should have received a copy of the GNU General Public License along // with eCos; if not, write to the Free Software Foundation, Inc., // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. // // As a special exception, if other files instantiate templates or use macros // or inline functions from this file, or you compile this file and link it // with other works to produce a work based on this file, this file does not // by itself cause the resulting work to be covered by the GNU General Public // License. However the source code for this file must still be made available // in accordance with section (3) of the GNU General Public License. // // This exception does not invalidate any other reasons why a work based on // this file might be covered by the GNU General Public License. // // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. // at http://sources.redhat.com/ecos/ecos-license/ // ------------------------------------------- //####ECOSGPLCOPYRIGHTEND#### //========================================================================== //#####DESCRIPTIONBEGIN#### // // Author(s): nickg // Contributors: nickg // Date: 2000-03-27 // Purpose: POSIX exception translation // Description: This file contains code to translate eCos hardware // exceptions into POSIX signals. // // // //####DESCRIPTIONEND#### // //========================================================================== #include <pkgconf/hal.h> #include <pkgconf/kernel.h> #include <pkgconf/posix.h> #include <cyg/kernel/ktypes.h> // base kernel types #include <cyg/infra/cyg_trac.h> // tracing macros #include <cyg/infra/cyg_ass.h> // assertion macros #include <cyg/infra/diag.h> #include "pprivate.h" // POSIX private header #include <signal.h> // our header #include <cyg/kernel/thread.inl> //========================================================================== // Translation table from eCos exceptions to POSIX signals. static const struct { cyg_code exception; int signal; } 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 }; //========================================================================== // POSIX exception handler static void cyg_posix_exception_handler( CYG_ADDRWORD data, // user supplied data == signal number cyg_code exception_number, // exception being raised CYG_ADDRWORD exception_info // any exception specific info ) { int signo = 0; pthread_info *self = pthread_self_info(); if( self == NULL ) { // Not a POSIX thread, just return return; } #ifdef CYGSEM_KERNEL_EXCEPTIONS_DECODE signo = data; #else for( int i = 0; exception_signal_mapping[i].signal != 0; i++ ) { if( exception_signal_mapping[i].exception == exception_number ) { signo = exception_signal_mapping[i].signal; break; } } #endif if( sigismember( &self->sigmask, signo ) ) { // The signal is masked in the current thread. POSIX says that // the behaviour is undefined here. We choose to ignore it. return; } // The kernel exception handler may have disabled interrupts, so // we (re-)enable them here. From this point on we are running in // a context that is effectively just pushed onto the stack of the // current thread. If we return we will unwind and resume // execution from the excepting code. We can also, in theory, // longjump out of the signal handler, and although that is // deprecated, we make sure in cyg_deliver_signals() that it is // possible to do it. HAL_ENABLE_INTERRUPTS(); struct sigevent sev; sev.sigev_notify = SIGEV_SIGNAL; sev.sigev_signo = signo; sev.sigev_value.sival_ptr = (void *)exception_info; // Generate the signal cyg_sigqueue( &sev, SI_EXCEPT ); // And try to deliver it cyg_deliver_signals(); } //========================================================================== // Install all the exception handlers static void install_handlers( Cyg_Thread *thread) { #ifdef CYGSEM_KERNEL_EXCEPTIONS_DECODE // With decoded exceptions, we must install a separate exception // handler for each supported exception. for( int i = 0; exception_signal_mapping[i].signal != 0; i++ ) { thread->register_exception( exception_signal_mapping[i].exception, cyg_posix_exception_handler, exception_signal_mapping[i].signal,, NULL, NULL); } #else // Otherwise there is just one exception handler for all exceptions. thread->register_exception( CYGNUM_HAL_EXCEPTION_MIN, cyg_posix_exception_handler, 0, NULL, NULL); #endif } //========================================================================== // Initialization externC void cyg_posix_exception_start() { #ifdef CYGSEM_KERNEL_EXCEPTIONS_GLOBAL // With global exceptions, we only need to install a single static // set of exception handlers. Note that by this point in system // initialization the idle thread should be installed as the // current thread, so we pass a pointer to that to // install_handlers(). The identity of the thread passed is // actually irrelevant in this case and is just used as a handle // into the thread class. install_handlers( Cyg_Thread::self() ); #endif } //========================================================================== // Per thread exception initialization and destruction externC void cyg_pthread_exception_init(pthread_info *thread) { #ifndef CYGSEM_KERNEL_EXCEPTIONS_GLOBAL // With non-global exceptions we must install a new set of handlers // for each thread. install_handlers( thread->thread ); #endif } externC void cyg_pthread_exception_destroy(pthread_info *thread) { // Nothing to do at present. } // ------------------------------------------------------------------------- // EOF except.cxx