2009-09-15 Øyvind Harboe <oyvind.harboe@zylin.com>
[nios2ecos.git] / tools / gcc4libstdxx / ecos / compat / posix / current / src / except.cxx
blob4263e61465300d3a223bb39713bed3593dd5472f
1 //==========================================================================
2 //
3 // except.cxx
4 //
5 // POSIX exception translation
6 //
7 //==========================================================================
8 // ####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
13 // eCos is free software; you can redistribute it and/or modify it under
14 // the terms of the GNU General Public License as published by the Free
15 // Software Foundation; either version 2 or (at your option) any later
16 // version.
18 // eCos is distributed in the hope that it will be useful, but WITHOUT
19 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 // for more details.
23 // You should have received a copy of the GNU General Public License
24 // along with eCos; if not, write to the Free Software Foundation, Inc.,
25 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
27 // As a special exception, if other files instantiate templates or use
28 // macros or inline functions from this file, or you compile this file
29 // and link it with other works to produce a work based on this file,
30 // this file does not by itself cause the resulting work to be covered by
31 // the GNU General Public License. However the source code for this file
32 // must still be made available in accordance with section (3) of the GNU
33 // General Public License v2.
35 // This exception does not invalidate any other reasons why a work based
36 // on this file might be covered by the GNU General Public License.
37 // -------------------------------------------
38 // ####ECOSGPLCOPYRIGHTEND####
39 //==========================================================================
40 //#####DESCRIPTIONBEGIN####
42 // Author(s): nickg
43 // Contributors: nickg
44 // Date: 2000-03-27
45 // Purpose: POSIX exception translation
46 // Description: This file contains code to translate eCos hardware
47 // exceptions into POSIX signals.
48 //
49 //
51 //####DESCRIPTIONEND####
53 //==========================================================================
55 #include <pkgconf/hal.h>
56 #include <pkgconf/kernel.h>
57 #include <pkgconf/posix.h>
59 #include <cyg/kernel/ktypes.h> // base kernel types
60 #include <cyg/infra/cyg_trac.h> // tracing macros
61 #include <cyg/infra/cyg_ass.h> // assertion macros
63 #include <cyg/infra/diag.h>
65 #include "pprivate.h" // POSIX private header
67 #include <signal.h> // our header
69 #include <cyg/kernel/thread.inl>
71 //==========================================================================
72 // Translation table from eCos exceptions to POSIX signals.
74 static const struct
76 cyg_code exception;
77 int signal;
78 } exception_signal_mapping[] =
80 #ifdef CYGNUM_HAL_EXCEPTION_DATA_ACCESS
81 {CYGNUM_HAL_EXCEPTION_DATA_ACCESS, SIGBUS},
82 #endif
83 #ifdef CYGNUM_HAL_EXCEPTION_DATA_WRITE
84 {CYGNUM_HAL_EXCEPTION_DATA_WRITE, SIGBUS},
85 #endif
86 #ifdef CYGNUM_HAL_EXCEPTION_CODE_ACCESS
87 {CYGNUM_HAL_EXCEPTION_CODE_ACCESS, SIGBUS},
88 #endif
89 #ifdef CYGNUM_HAL_EXCEPTION_CODE_WRITE
90 {CYGNUM_HAL_EXCEPTION_CODE_WRITE, SIGBUS},
91 #endif
92 #ifdef CYGNUM_HAL_EXCEPTION_CODE_EXECUTE
93 {CYGNUM_HAL_EXCEPTION_CODE_EXECUTE, SIGBUS},
94 #endif
95 #ifdef CYGNUM_HAL_EXCEPTION_IO_ACCESS
96 {CYGNUM_HAL_EXCEPTION_IO_ACCESS, SIGBUS},
97 #endif
98 #ifdef CYGNUM_HAL_EXCEPTION_IO_WRITE
99 {CYGNUM_HAL_EXCEPTION_IO_ACCESS, SIGBUS},
100 #endif
101 #ifdef CYGNUM_HAL_EXCEPTION_DATA_TLBMISS_ACCESS
102 {CYGNUM_HAL_EXCEPTION_DATA_TLBMISS_ACCESS, SIGSEGV},
103 #endif
104 #ifdef CYGNUM_HAL_EXCEPTION_DATA_TLBMISS_WRITE
105 {CYGNUM_HAL_EXCEPTION_DATA_TLBMISS_WRITE, SIGSEGV},
106 #endif
107 #ifdef CYGNUM_HAL_EXCEPTION_CODE_TLBMISS_ACCESS
108 {CYGNUM_HAL_EXCEPTION_CODE_TLBMISS_ACCESS, SIGSEGV},
109 #endif
110 #ifdef CYGNUM_HAL_EXCEPTION_CODE_TLBMISS_WRITE
111 {CYGNUM_HAL_EXCEPTION_CODE_TLBMISS_WRITE, SIGSEGV},
112 #endif
113 #ifdef CYGNUM_HAL_EXCEPTION_DATA_TLBERROR_ACCESS
114 {CYGNUM_HAL_EXCEPTION_DATA_TLBERROR_ACCESS, SIGSEGV},
115 #endif
116 #ifdef CYGNUM_HAL_EXCEPTION_DATA_TLBERROR_WRITE
117 {CYGNUM_HAL_EXCEPTION_DATA_TLBERROR_WRITE, SIGSEGV},
118 #endif
119 #ifdef CYGNUM_HAL_EXCEPTION_CODE_TLBERROR_ACCESS
120 {CYGNUM_HAL_EXCEPTION_CODE_TLBERROR_ACCESS, SIGSEGV},
121 #endif
122 #ifdef CYGNUM_HAL_EXCEPTION_CODE_TLBERROR_WRITE
123 {CYGNUM_HAL_EXCEPTION_CODE_TLBERROR_WRITE, SIGSEGV},
124 #endif
125 #ifdef CYGNUM_HAL_EXCEPTION_DATA_UNALIGNED_ACCESS
126 {CYGNUM_HAL_EXCEPTION_DATA_UNALIGNED_ACCESS, SIGBUS},
127 #endif
128 #ifdef CYGNUM_HAL_EXCEPTION_DATA_UNALIGNED_WRITE
129 {CYGNUM_HAL_EXCEPTION_DATA_UNALIGNED_WRITE, SIGBUS},
130 #endif
131 #ifdef CYGNUM_HAL_EXCEPTION_IO_UNALIGNED_ACCESS
132 {CYGNUM_HAL_EXCEPTION_IO_UNALIGNED_ACCESS, SIGBUS},
133 #endif
134 #ifdef CYGNUM_HAL_EXCEPTION_IO_UNALIGNED_WRITE
135 {CYGNUM_HAL_EXCEPTION_IO_UNALIGNED_WRITE, SIGBUS},
136 #endif
137 #ifdef CYGNUM_HAL_EXCEPTION_ILLEGAL_INSTRUCTION
138 {CYGNUM_HAL_EXCEPTION_ILLEGAL_INSTRUCTION, SIGILL},
139 #endif
140 #ifdef CYGNUM_HAL_EXCEPTION_INTERRUPT
141 {CYGNUM_HAL_EXCEPTION_INTERRUPT, SIGINT},
142 #endif
143 #ifdef CYGNUM_HAL_EXCEPTION_TRAP
144 {CYGNUM_HAL_EXCEPTION_TRAP, SIGTRAP},
145 #endif
146 #ifdef CYGNUM_HAL_EXCEPTION_DIV_BY_ZERO
147 {CYGNUM_HAL_EXCEPTION_DIV_BY_ZERO, SIGFPE},
148 #endif
149 #ifdef CYGNUM_HAL_EXCEPTION_OVERFLOW
150 {CYGNUM_HAL_EXCEPTION_OVERFLOW, SIGFPE},
151 #endif
152 #ifdef CYGNUM_HAL_EXCEPTION_BOUNDS
153 {CYGNUM_HAL_EXCEPTION_BOUNDS, SIGSEGV},
154 #endif
155 #ifdef CYGNUM_HAL_EXCEPTION_SINGLE_STEP
156 {CYGNUM_HAL_EXCEPTION_SINGLE_STEP, SIGTRAP},
157 #endif
158 #ifdef CYGNUM_HAL_EXCEPTION_INSTRUCTION_BP
159 {CYGNUM_HAL_EXCEPTION_INSTRUCTION_BP, SIGTRAP},
160 #endif
161 #ifdef CYGNUM_HAL_EXCEPTION_PERIPHERAL_BP
162 {CYGNUM_HAL_EXCEPTION_PERIPHERAL_BP, SIGTRAP},
163 #endif
164 #ifdef CYGNUM_HAL_EXCEPTION_DATA_BP
165 {CYGNUM_HAL_EXCEPTION_DATA_BP, SIGTRAP},
166 #endif
167 #ifdef CYGNUM_HAL_EXCEPTION_DEVELOPMENT_BP
168 {CYGNUM_HAL_EXCEPTION_DEVELOPMENT_BP, SIGTRAP},
169 #endif
170 #ifdef CYGNUM_HAL_EXCEPTION_STACK_OVERFLOW
171 {CYGNUM_HAL_EXCEPTION_STACK_OVERFLOW, SIGSEGV},
172 #endif
173 #ifdef CYGNUM_HAL_EXCEPTION_STACK_FAULT
174 {CYGNUM_HAL_EXCEPTION_STACK_FAULT, SIGSEGV},
175 #endif
176 #ifdef CYGNUM_HAL_EXCEPTION_PARITY
177 {CYGNUM_HAL_EXCEPTION_PARITY, SIGBUS},
178 #endif
179 #ifdef CYGNUM_HAL_EXCEPTION_FPU
180 {CYGNUM_HAL_EXCEPTION_FPU, SIGFPE},
181 #endif
182 #ifdef CYGNUM_HAL_EXCEPTION_FPU_NOT_AVAIL
183 {CYGNUM_HAL_EXCEPTION_FPU_NOT_AVAIL, SIGFPE},
184 #endif
185 #ifdef CYGNUM_HAL_EXCEPTION_FPU_OVERFLOW
186 {CYGNUM_HAL_EXCEPTION_FPU_OVERFLOW, SIGFPE},
187 #endif
188 #ifdef CYGNUM_HAL_EXCEPTION_FPU_UNDERFLOW
189 {CYGNUM_HAL_EXCEPTION_FPU_UNDERFLOW, SIGFPE},
190 #endif
191 #ifdef CYGNUM_HAL_EXCEPTION_FPU_DIV_BY_ZERO
192 {CYGNUM_HAL_EXCEPTION_FPU_DIV_BY_ZERO, SIGFPE},
193 #endif
194 #ifdef CYGNUM_HAL_EXCEPTION_SYSTEM_CALL
195 {CYGNUM_HAL_EXCEPTION_SYSTEM_CALL, SIGSYS},
196 #endif
197 {0, 0} // dummy value to ensure compiler is happy
200 //==========================================================================
201 // POSIX exception handler
203 static void cyg_posix_exception_handler(
204 CYG_ADDRWORD data, // user supplied data == signal number
205 cyg_code exception_number, // exception being raised
206 CYG_ADDRWORD exception_info // any exception specific info
209 int signo = 0;
211 pthread_info *self = pthread_self_info();
213 if( self == NULL )
215 // Not a POSIX thread, just return
216 return;
219 #ifdef CYGSEM_KERNEL_EXCEPTIONS_DECODE
221 signo = data;
223 #else
225 for( int i = 0; exception_signal_mapping[i].signal != 0; i++ )
227 if( exception_signal_mapping[i].exception == exception_number )
229 signo = exception_signal_mapping[i].signal;
230 break;
234 #endif
236 if( sigismember( &self->sigmask, signo ) )
238 // The signal is masked in the current thread. POSIX says that
239 // the behaviour is undefined here. We choose to ignore it.
241 return;
244 // The kernel exception handler may have disabled interrupts, so
245 // we (re-)enable them here. From this point on we are running in
246 // a context that is effectively just pushed onto the stack of the
247 // current thread. If we return we will unwind and resume
248 // execution from the excepting code. We can also, in theory,
249 // longjump out of the signal handler, and although that is
250 // deprecated, we make sure in cyg_deliver_signals() that it is
251 // possible to do it.
253 HAL_ENABLE_INTERRUPTS();
255 struct sigevent sev;
257 sev.sigev_notify = SIGEV_SIGNAL;
258 sev.sigev_signo = signo;
259 sev.sigev_value.sival_ptr = (void *)exception_info;
261 // Generate the signal
262 cyg_sigqueue( &sev, SI_EXCEPT );
264 // And try to deliver it
265 cyg_deliver_signals();
268 //==========================================================================
269 // Install all the exception handlers
271 static void install_handlers( Cyg_Thread *thread)
273 #ifdef CYGSEM_KERNEL_EXCEPTIONS_DECODE
275 // With decoded exceptions, we must install a separate exception
276 // handler for each supported exception.
278 for( int i = 0; exception_signal_mapping[i].signal != 0; i++ )
280 thread->register_exception( exception_signal_mapping[i].exception,
281 cyg_posix_exception_handler,
282 exception_signal_mapping[i].signal,
283 NULL,
284 NULL);
287 #else
289 // Otherwise there is just one exception handler for all exceptions.
291 thread->register_exception( CYGNUM_HAL_EXCEPTION_MIN,
292 cyg_posix_exception_handler,
294 NULL,
295 NULL);
297 #endif
301 //==========================================================================
302 // Initialization
304 externC void cyg_posix_exception_start()
306 #ifdef CYGSEM_KERNEL_EXCEPTIONS_GLOBAL
308 // With global exceptions, we only need to install a single static
309 // set of exception handlers. Note that by this point in system
310 // initialization the idle thread should be installed as the
311 // current thread, so we pass a pointer to that to
312 // install_handlers(). The identity of the thread passed is
313 // actually irrelevant in this case and is just used as a handle
314 // into the thread class.
316 install_handlers( Cyg_Thread::self() );
318 #endif
321 //==========================================================================
322 // Per thread exception initialization and destruction
324 externC void cyg_pthread_exception_init(pthread_info *thread)
326 #ifndef CYGSEM_KERNEL_EXCEPTIONS_GLOBAL
328 // With non-global exceptions we must install a new set of handlers
329 // for each thread.
331 install_handlers( thread->thread );
333 #endif
336 externC void cyg_pthread_exception_destroy(pthread_info *thread)
338 // Nothing to do at present.
341 // -------------------------------------------------------------------------
342 // EOF except.cxx