unified MX27, MX25, MX37 trees
[karo-tx-redboot.git] / packages / language / c / libc / signals / v2_0 / src / siginit.cxx
1 //========================================================================
2 //
3 //      siginit.cxx
4 //
5 //      ISO C and POSIX 1003.1 signals implementation
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 Red Hat, Inc.
12 //
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 version.
16 //
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20 // for more details.
21 //
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25 //
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
32 //
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
35 //
36 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37 // at http://sources.redhat.com/ecos/ecos-license/
38 // -------------------------------------------
39 //####ECOSGPLCOPYRIGHTEND####
40 //========================================================================
41 //#####DESCRIPTIONBEGIN####
42 //
43 // Author(s):     jlarmour
44 // Contributors:  
45 // Date:          2000-04-18
46 // Purpose:       Provide implementation of ISO C and POSIX 1003.1 signals
47 // Description:   This file initializes all hardware exceptions,
48 //                initializes the signal handler table and provides the
49 //                default action function for signals
50 // Usage:         
51 //
52 //####DESCRIPTIONEND####
53 //
54 //========================================================================
55
56 // CONFIGURATION
57
58 #include <pkgconf/libc_signals.h>  // libc signals configuration
59 #include <pkgconf/isoinfra.h>      // isoinfra defs, including CYGINT_ISO_EXIT
60
61 // INCLUDES
62
63 #include <cyg/infra/cyg_type.h>    // Common type definitions and support
64 #include <signal.h>                // Main signals definitions
65 #include <cyg/infra/cyg_ass.h>     // Assertion infrastructure
66 #include <cyg/infra/cyg_trac.h>    // Tracing infrastructure
67 #include <stdlib.h>                // exit()
68
69 #ifdef CYGSEM_LIBC_SIGNALS_HWEXCEPTIONS
70 # include <pkgconf/kernel.h>       // required for kernel includes
71 # include <cyg/kernel/except.hxx>  // Kernel exception API
72 # include <cyg/kernel/thread.hxx>  // Cyg_Thread::self()
73 # include <cyg/kernel/thread.inl>  // inline definitions for above
74 # include <cyg/kernel/intr.hxx>    // Interrupt enable
75 # include <cyg/hal/hal_intr.h>     // HAL interrupt control
76 #endif
77
78 #ifdef CYGSEM_LIBC_SIGNALS_THREAD_SAFE
79 # include <pkgconf/kernel.h>       // required for kernel includes
80 # include <cyg/kernel/mutex.hxx>
81 #endif
82
83 // TYPE DEFINITIONS
84
85 // define dummy class to allow initialization of cyg_libc_signal_handlers
86
87 class Cyg_libc_signals_dummy_init_class {
88 public:
89     Cyg_libc_signals_dummy_init_class();
90 };
91
92 #ifdef CYGSEM_LIBC_SIGNALS_HWEXCEPTIONS
93
94 struct exception_signal_mapping_t {
95     cyg_code exception;
96     int signal;
97 };    
98
99 // EXTERNS
100
101 extern cyg_exception_handler cyg_null_exception_handler;
102
103 #endif // ifdef CYGSEM_LIBC_SIGNALS_HWEXCEPTIONS
104
105 // GLOBALS
106
107 // main signal handlers
108 __sighandler_t cyg_libc_signal_handlers[CYGNUM_LIBC_SIGNALS];
109
110 #ifdef CYGSEM_LIBC_SIGNALS_THREAD_SAFE
111 Cyg_Mutex cyg_libc_signal_handlers_mutex CYG_INIT_PRIORITY(LIBC);
112 #endif
113
114 // STATICS
115
116 // dummy object to invoke constructor
117 static Cyg_libc_signals_dummy_init_class
118 cyg_libc_signals_dummy_init_obj CYG_INIT_PRIORITY(LIBC);
119
120 #ifdef CYGSEM_LIBC_SIGNALS_HWEXCEPTIONS
121
122 # ifdef CYGDBG_USE_TRACING
123 static cyg_uint8 cyg_libc_signals_hwhandler_trace_level =
124   CYGNUM_LIBC_SIGNALS_HWHANDLER_TRACE_LEVEL;
125 # define TL1 (0 < cyg_libc_signals_hwhandler_trace_level)
126 # endif
127
128 # ifdef CYGSEM_LIBC_SIGNALS_CHAIN_HWEXCEPTIONS
129 // old exception info so we can chain
130 // FIXME: consider malloced linked list config option
131 static struct {
132     cyg_exception_handler *old_handler;
133     CYG_ADDRWORD old_data;
134 } exception_chain_data[CYGNUM_HAL_EXCEPTION_COUNT];
135 # endif
136
137 // struct that maps exceptions to signals
138 static const struct exception_signal_mapping_t
139 exception_signal_mapping[] = {
140
141 #ifdef CYGNUM_HAL_EXCEPTION_DATA_ACCESS
142     {CYGNUM_HAL_EXCEPTION_DATA_ACCESS, SIGBUS},
143 #endif
144 #ifdef CYGNUM_HAL_EXCEPTION_DATA_WRITE
145     {CYGNUM_HAL_EXCEPTION_DATA_WRITE, SIGBUS},
146 #endif
147 #ifdef CYGNUM_HAL_EXCEPTION_CODE_ACCESS
148     {CYGNUM_HAL_EXCEPTION_CODE_ACCESS, SIGBUS},
149 #endif    
150 #ifdef CYGNUM_HAL_EXCEPTION_CODE_WRITE
151     {CYGNUM_HAL_EXCEPTION_CODE_WRITE, SIGBUS},
152 #endif    
153 #ifdef CYGNUM_HAL_EXCEPTION_CODE_EXECUTE
154     {CYGNUM_HAL_EXCEPTION_CODE_EXECUTE, SIGBUS},
155 #endif    
156 #ifdef CYGNUM_HAL_EXCEPTION_IO_ACCESS
157     {CYGNUM_HAL_EXCEPTION_IO_ACCESS, SIGBUS},
158 #endif    
159 #ifdef CYGNUM_HAL_EXCEPTION_IO_WRITE
160     {CYGNUM_HAL_EXCEPTION_IO_ACCESS, SIGBUS},
161 #endif    
162 #ifdef CYGNUM_HAL_EXCEPTION_DATA_TLBMISS_ACCESS
163     {CYGNUM_HAL_EXCEPTION_DATA_TLBMISS_ACCESS, SIGSEGV},
164 #endif    
165 #ifdef CYGNUM_HAL_EXCEPTION_DATA_TLBMISS_WRITE
166     {CYGNUM_HAL_EXCEPTION_DATA_TLBMISS_WRITE, SIGSEGV},
167 #endif    
168 #ifdef CYGNUM_HAL_EXCEPTION_CODE_TLBMISS_ACCESS
169     {CYGNUM_HAL_EXCEPTION_CODE_TLBMISS_ACCESS, SIGSEGV},
170 #endif    
171 #ifdef CYGNUM_HAL_EXCEPTION_CODE_TLBMISS_WRITE
172     {CYGNUM_HAL_EXCEPTION_CODE_TLBMISS_WRITE, SIGSEGV},
173 #endif    
174 #ifdef CYGNUM_HAL_EXCEPTION_DATA_TLBERROR_ACCESS
175     {CYGNUM_HAL_EXCEPTION_DATA_TLBERROR_ACCESS, SIGSEGV},
176 #endif    
177 #ifdef CYGNUM_HAL_EXCEPTION_DATA_TLBERROR_WRITE
178     {CYGNUM_HAL_EXCEPTION_DATA_TLBERROR_WRITE, SIGSEGV},
179 #endif    
180 #ifdef CYGNUM_HAL_EXCEPTION_CODE_TLBERROR_ACCESS
181     {CYGNUM_HAL_EXCEPTION_CODE_TLBERROR_ACCESS, SIGSEGV},
182 #endif    
183 #ifdef CYGNUM_HAL_EXCEPTION_CODE_TLBERROR_WRITE
184     {CYGNUM_HAL_EXCEPTION_CODE_TLBERROR_WRITE, SIGSEGV},
185 #endif    
186 #ifdef CYGNUM_HAL_EXCEPTION_DATA_UNALIGNED_ACCESS
187     {CYGNUM_HAL_EXCEPTION_DATA_UNALIGNED_ACCESS, SIGBUS},
188 #endif    
189 #ifdef CYGNUM_HAL_EXCEPTION_DATA_UNALIGNED_WRITE
190     {CYGNUM_HAL_EXCEPTION_DATA_UNALIGNED_WRITE, SIGBUS},
191 #endif    
192 #ifdef CYGNUM_HAL_EXCEPTION_IO_UNALIGNED_ACCESS
193     {CYGNUM_HAL_EXCEPTION_IO_UNALIGNED_ACCESS, SIGBUS},
194 #endif    
195 #ifdef CYGNUM_HAL_EXCEPTION_IO_UNALIGNED_WRITE
196     {CYGNUM_HAL_EXCEPTION_IO_UNALIGNED_WRITE, SIGBUS},
197 #endif    
198 #ifdef CYGNUM_HAL_EXCEPTION_ILLEGAL_INSTRUCTION
199     {CYGNUM_HAL_EXCEPTION_ILLEGAL_INSTRUCTION, SIGILL},
200 #endif    
201 #ifdef CYGNUM_HAL_EXCEPTION_INTERRUPT
202     {CYGNUM_HAL_EXCEPTION_INTERRUPT, SIGINT},
203 #endif    
204 #ifdef CYGNUM_HAL_EXCEPTION_TRAP
205     {CYGNUM_HAL_EXCEPTION_TRAP, SIGTRAP},
206 #endif    
207 #ifdef CYGNUM_HAL_EXCEPTION_DIV_BY_ZERO
208     {CYGNUM_HAL_EXCEPTION_DIV_BY_ZERO, SIGFPE},
209 #endif    
210 #ifdef CYGNUM_HAL_EXCEPTION_OVERFLOW
211     {CYGNUM_HAL_EXCEPTION_OVERFLOW, SIGFPE},
212 #endif    
213 #ifdef CYGNUM_HAL_EXCEPTION_BOUNDS
214     {CYGNUM_HAL_EXCEPTION_BOUNDS, SIGSEGV},
215 #endif
216 #ifdef CYGNUM_HAL_EXCEPTION_SINGLE_STEP
217     {CYGNUM_HAL_EXCEPTION_SINGLE_STEP, SIGTRAP},
218 #endif
219 #ifdef CYGNUM_HAL_EXCEPTION_INSTRUCTION_BP
220     {CYGNUM_HAL_EXCEPTION_INSTRUCTION_BP, SIGTRAP},
221 #endif
222 #ifdef CYGNUM_HAL_EXCEPTION_PERIPHERAL_BP
223     {CYGNUM_HAL_EXCEPTION_PERIPHERAL_BP, SIGTRAP},
224 #endif
225 #ifdef CYGNUM_HAL_EXCEPTION_DATA_BP
226     {CYGNUM_HAL_EXCEPTION_DATA_BP, SIGTRAP},
227 #endif
228 #ifdef CYGNUM_HAL_EXCEPTION_DEVELOPMENT_BP
229     {CYGNUM_HAL_EXCEPTION_DEVELOPMENT_BP, SIGTRAP},
230 #endif
231 #ifdef CYGNUM_HAL_EXCEPTION_STACK_OVERFLOW
232     {CYGNUM_HAL_EXCEPTION_STACK_OVERFLOW, SIGSEGV},
233 #endif
234 #ifdef CYGNUM_HAL_EXCEPTION_STACK_FAULT
235     {CYGNUM_HAL_EXCEPTION_STACK_FAULT, SIGSEGV},
236 #endif
237 #ifdef CYGNUM_HAL_EXCEPTION_PARITY
238     {CYGNUM_HAL_EXCEPTION_PARITY, SIGBUS},
239 #endif
240 #ifdef CYGNUM_HAL_EXCEPTION_FPU
241     {CYGNUM_HAL_EXCEPTION_FPU, SIGFPE},
242 #endif
243 #ifdef CYGNUM_HAL_EXCEPTION_FPU_NOT_AVAIL
244     {CYGNUM_HAL_EXCEPTION_FPU_NOT_AVAIL, SIGFPE},
245 #endif
246 #ifdef CYGNUM_HAL_EXCEPTION_FPU_OVERFLOW
247     {CYGNUM_HAL_EXCEPTION_FPU_OVERFLOW, SIGFPE},
248 #endif
249 #ifdef CYGNUM_HAL_EXCEPTION_FPU_UNDERFLOW
250     {CYGNUM_HAL_EXCEPTION_FPU_UNDERFLOW, SIGFPE},
251 #endif
252 #ifdef CYGNUM_HAL_EXCEPTION_FPU_DIV_BY_ZERO
253     {CYGNUM_HAL_EXCEPTION_FPU_DIV_BY_ZERO, SIGFPE},
254 #endif
255 #ifdef CYGNUM_HAL_EXCEPTION_SYSTEM_CALL
256     {CYGNUM_HAL_EXCEPTION_SYSTEM_CALL, SIGSYS},
257 #endif
258     {0, 0} // dummy value to ensure compiler is happy
259 };
260
261         
262 // FUNCTIONS
263
264 /////////////////////////////////////////
265 // cyg_libc_signals_hwexcept_handler() //
266 /////////////////////////////////////////
267
268 // FIXME: should be able to get this work with
269 // CYGSEM_KERNEL_EXCEPTIONS_DECODE disabled as well as enabled
270 static void
271 cyg_libc_signals_hwexcept_handler( CYG_ADDRWORD data, cyg_code exception,
272                                    CYG_ADDRWORD info)
273 {
274     int signal = (int)data;
275     int ret;
276
277     CYG_REPORT_FUNCNAME("cyg_libc_signals_hwexcept_handler");
278
279     CYG_REPORT_FUNCARG3( "data = %08x, exception = %d, info = %08x",
280                          data, exception, info );
281
282 #ifdef CYGSEM_LIBC_SIGNALS_BAD_SIGNAL_FATAL 
283     CYG_PRECONDITION((signal > 0) && (signal < CYGNUM_LIBC_SIGNALS), 
284                      "Signal number not valid!");
285 #endif
286
287 // chain first as it may be more useful more low-level stuff needed
288 #ifdef CYGSEM_LIBC_SIGNALS_CHAIN_HWEXCEPTIONS
289     // map exception to 0..CYGNUM_HAL_EXCEPTION_COUNT
290     exception -= CYGNUM_HAL_EXCEPTION_MIN;
291
292     // special case for null handler since it is only for uncaught exceptions
293
294     if (exception_chain_data[exception].old_handler != 
295         cyg_null_exception_handler) {
296         (*exception_chain_data[exception].old_handler)(
297             exception_chain_data[exception].old_data, exception, info);
298         CYG_TRACE0(TL1, "Chained exception handler returned");
299     } // if
300 #endif
301
302 #ifndef CYGSEM_LIBC_SIGNALS_BAD_SIGNAL_FATAL
303     // if not fatal, silently return
304     if ((signal <= 0) || (signal >= CYGNUM_LIBC_SIGNALS)) {
305         CYG_REPORT_RETURN();
306         return;
307     }
308 #endif
309
310     CYG_TRACE0(TL1, "Enabling interrupts");
311     HAL_ENABLE_INTERRUPTS();
312
313     CYG_TRACE0(TL1, "Raising signal");
314     ret = raise(signal);
315
316     if (ret) {
317         CYG_TRACE1(TL1, "raise() returned non-zero value %d!!!", ret);
318     } // if
319
320     CYG_REPORT_RETURN();
321 } // cyg_libc_signals_hwexcept_handler()
322
323
324 //////////////////
325 // reg_except() //
326 //////////////////
327
328 static void inline
329 reg_except( cyg_code exception, int signal )
330 {
331     Cyg_Thread::self()->register_exception(
332         exception, &cyg_libc_signals_hwexcept_handler, (CYG_ADDRWORD)signal,
333 #ifdef CYGSEM_LIBC_SIGNALS_CHAIN_HWEXCEPTIONS
334         &exception_chain_data[exception - 
335                              CYGNUM_HAL_EXCEPTION_MIN].old_handler,
336         &exception_chain_data[exception - CYGNUM_HAL_EXCEPTION_MIN].old_data
337 #else
338         NULL, NULL
339 #endif
340         );
341
342 } // reg_except();
343
344 #endif // ifdef CYGSEM_LIBC_SIGNALS_HWEXCEPTIONS
345
346 ///////////////////////////////////////////////////
347 // Cyg_libc_signals_dummy_init_class constructor //
348 ///////////////////////////////////////////////////
349
350 Cyg_libc_signals_dummy_init_class::Cyg_libc_signals_dummy_init_class()
351 {
352     cyg_ucount8 i;
353
354     CYG_REPORT_FUNCNAME("Cyg_libc_signals_dummy_init_class constructor");
355     
356     // FIXME: some should be SIG_IGN?
357     for (i=0; i<CYGNUM_LIBC_SIGNALS; i++)
358         cyg_libc_signal_handlers[i] = SIG_DFL;
359
360 #ifdef CYGSEM_LIBC_SIGNALS_HWEXCEPTIONS
361     // go through the entire array of exceptions, _but_ subtract 1 for
362     // the dummy at the end
363     for (i=0; i < (sizeof(exception_signal_mapping) / 
364                    sizeof(exception_signal_mapping_t) - 1); i++) {
365         CYG_ASSERT( (exception_signal_mapping[i].exception <= 
366                     CYGNUM_HAL_EXCEPTION_MAX) &&
367                     (exception_signal_mapping[i].exception >=
368                     CYGNUM_HAL_EXCEPTION_MIN),
369                     "Asked to register bad exception");
370
371         CYG_ASSERT( (exception_signal_mapping[i].signal > 0) &&
372                     (exception_signal_mapping[i].signal < 
373                      CYGNUM_LIBC_SIGNALS), "Asked to register bad signal" );
374
375         reg_except( exception_signal_mapping[i].exception,
376                     exception_signal_mapping[i].signal);
377     }
378 #endif
379
380     CYG_REPORT_RETURN();
381 } // Cyg_libc_signals_dummy_init_class() constructor
382
383
384 ////////////////////////////////////////
385 // cyg_libc_signals_default_handler() //
386 ////////////////////////////////////////
387
388 // Default signal handler - SIG_DFL
389 externC void
390 cyg_libc_signals_default_handler(int sig)
391 {
392     CYG_REPORT_FUNCNAME( "cyg_libc_signals_default_handler" );
393
394     CYG_REPORT_FUNCARG1( "signal number = %d", sig );
395
396 #if CYGINT_ISO_EXIT
397     exit(1000 + sig); // FIXME
398 #else
399     CYG_FAIL("Default signal handler called - no exit available");
400 #endif
401
402     CYG_REPORT_RETURN();
403 } // cyg_libc_signals_default_handler()
404
405 #ifdef CYGSEM_LIBC_SIGNALS_THREAD_SAFE
406 /////////////////////////////////////
407 // cyg_libc_signals_lock_do_lock() //
408 /////////////////////////////////////
409
410 externC cyg_bool
411 cyg_libc_signals_lock_do_lock(void)
412 {
413     cyg_bool ret;
414     CYG_REPORT_FUNCNAMETYPE("cyg_libc_signals_lock_do_lock", "returning %d");
415
416     ret = cyg_libc_signal_handlers_mutex.lock();
417
418     CYG_REPORT_RETVAL(ret);
419
420     return ret;
421 } // cyg_libc_signals_lock_do_lock()
422
423 ///////////////////////////////////////
424 // cyg_libc_signals_lock_do_unlock() //
425 ///////////////////////////////////////
426
427 externC void
428 cyg_libc_signals_lock_do_unlock(void)
429 {
430     CYG_REPORT_FUNCNAME("cyg_libc_signals_lock_do_unlock");
431
432     cyg_libc_signal_handlers_mutex.unlock();
433
434     CYG_REPORT_RETURN();
435 } // cyg_libc_signals_lock_do_unlock()
436
437 #endif // ifdef CYGSEM_LIBC_SIGNALS_THREAD_SAFE
438
439 // EOF siginit.cxx