Mercurial > ecos
diff packages/compat/posix/current/src/except.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 | ac086aa3217e |
line wrap: on
line diff
new file mode 100644 --- /dev/null +++ b/packages/compat/posix/current/src/except.cxx @@ -0,0 +1,335 @@ +//========================================================================== +// +// except.cxx +// +// POSIX exception translation +// +//========================================================================== +//####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): 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; +diag_printf("exh %d\n",exception_number); + 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++ ) + { +diag_printf("exm %d -> %d\n",exception_signal_mapping[i].exception,exception_signal_mapping[i].signal); + if( exception_signal_mapping[i].exception == exception_number ) + { + signo = exception_signal_mapping[i].signal; + break; + } + } + +#endif +diag_printf("signo %d %08x\n",signo, self->sigmask); + 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
