]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/language/c/libc/signals/v2_0/tests/signal2.c
Initial revision
[karo-tx-redboot.git] / packages / language / c / libc / signals / v2_0 / tests / signal2.c
1 //========================================================================
2 //
3 //      signal2.c
4 //
5 //      ISO C signal handling test
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:       Test hardware signal functionality
47 // Description:   This file contains a number of tests for ISO C signal
48 //                handling when used with hardware exceptions
49 // Usage:         
50 //
51 //####DESCRIPTIONEND####
52 //
53 //========================================================================
54
55 // CONFIGURATION
56
57 #include <pkgconf/system.h>
58 #include <pkgconf/libc_signals.h>  // C library signals configuration
59
60 // INCLUDES
61
62 #include <cyg/infra/cyg_type.h>    // Common type definitions and support
63 #include <cyg/infra/testcase.h>    // Test infrastructure
64
65 #ifdef CYGSEM_LIBC_SIGNALS_HWEXCEPTIONS
66
67 #include <cyg/hal/hal_intr.h>      // exception ranges &
68                                    // HAL_VSR_SET_TO_ECOS_HANDLER
69
70 #include <signal.h>                // Signal functions
71 #include <setjmp.h>                // setjmp(), longjmp()
72
73 // STATICS
74
75 static int state;
76 static jmp_buf jbuf;
77 #endif
78
79 // FUNCTIONS
80
81 #ifdef CYGSEM_LIBC_SIGNALS_HWEXCEPTIONS
82
83 static void
84 myhandler(int sig)
85 {
86     __sighandler_t handler1;
87
88     CYG_TEST_INFO("myhandler() called");
89     ++state;
90
91     handler1 = signal(sig, &myhandler);
92
93     CYG_TEST_PASS_FAIL(handler1 == SIG_DFL,
94                        "handler reset itself to default");
95
96     longjmp(jbuf, 1);
97 } // myhandler()
98
99 static void
100 cause_memerror(void)
101 {
102 #ifdef CYGPKG_HAL_I386
103
104     // In the x86 architecture, although we have the DATA_ACCESS
105     // exception available, it is not possible to provoke it using the
106     // normal code of this test. This is because the normal segments we
107     // have installed in the segment registers cover all of memory. Instead we
108     // set GS to a descriptor that does not cover 0xF0000000-0xFFFFFFFF and
109     // poke at that.
110
111     __asm__ ( "movw     $0x20,%%ax\n"
112               "movw     %%ax,%%gs\n"
113               "movl     %%gs:0xF0000000,%%eax\n"
114               :
115               :
116               : "eax"
117             );
118     
119 #else    
120     volatile int x;
121     volatile CYG_ADDRESS p=(CYG_ADDRESS) &state;
122
123     do {
124         // do a read which prevents us accidentally writing over something
125         // important. Make it misaligned to increase the chances of an
126         // exception happening
127         x = *(volatile int *)(p+1);
128         p += (CYG_ADDRESS)0x100000;
129     } while(p != 0);
130 #endif    
131 } // cause_memerror()
132
133 // num must always be 0 - do it this way in case the optimizer tries to
134 // get smart
135 static int
136 cause_fpe(int num)
137 {
138     double a;
139
140     a = 1.0/num;                        // Depending on FPU emulation and/or
141                                         // the FPU architecture, this may
142                                         // cause an exception.
143                                         // (float division by zero)
144
145     return ((int)a)/num;                // This may cause an exception if
146                                         // the architecture supports it.
147                                         // (integer division by zero).
148 } // cause_fpe()
149
150 volatile int tmp;
151
152 #endif
153
154
155 int
156 main( int argc, char *argv[] )
157 {
158 #ifdef CYGSEM_LIBC_SIGNALS_HWEXCEPTIONS
159     __sighandler_t handler1;
160
161     // special callout to request GDB to alter its handling of signals
162     CYG_TEST_GDBCMD("handle SIGBUS nostop");
163     CYG_TEST_GDBCMD("handle SIGSEGV nostop");
164     CYG_TEST_GDBCMD("handle SIGILL nostop");
165     CYG_TEST_GDBCMD("handle SIGFPE nostop");
166     CYG_TEST_GDBCMD("handle SIGSYS nostop");
167 #endif // ifdef CYGSEM_LIBC_SIGNALS_HWEXCEPTIONS
168
169     CYG_TEST_INIT();
170
171 #ifdef CYGSEM_LIBC_SIGNALS_HWEXCEPTIONS
172     // Avoid compiler warnings if tests are not applicable.
173     if (0) cause_memerror();
174     if (0) cause_fpe(0);
175 #endif
176     
177     CYG_TEST_INFO("Starting tests from testcase " __FILE__ " for C "
178                   "library signal functions");
179
180 // Now reset the exception handlers various to eCos handlers so that we
181 // have control; this is the target side equivalent of the CYG_TEST_GDBCMD
182 // lines above:
183 #ifdef HAL_VSR_SET_TO_ECOS_HANDLER
184     // Reclaim the VSR off CygMon possibly
185 #ifdef CYGNUM_HAL_EXCEPTION_DATA_ACCESS
186     HAL_VSR_SET_TO_ECOS_HANDLER( CYGNUM_HAL_EXCEPTION_DATA_ACCESS, NULL );
187 #endif
188 #ifdef CYGNUM_HAL_EXCEPTION_DATA_TLBMISS_ACCESS
189     HAL_VSR_SET_TO_ECOS_HANDLER( CYGNUM_HAL_EXCEPTION_DATA_TLBMISS_ACCESS, NULL );
190 #endif
191 #ifdef CYGNUM_HAL_EXCEPTION_DATA_UNALIGNED_ACCESS
192     HAL_VSR_SET_TO_ECOS_HANDLER( CYGNUM_HAL_EXCEPTION_DATA_UNALIGNED_ACCESS, NULL );
193 #endif
194 #ifdef CYGNUM_HAL_EXCEPTION_ILLEGAL_INSTRUCTION
195     HAL_VSR_SET_TO_ECOS_HANDLER( CYGNUM_HAL_EXCEPTION_ILLEGAL_INSTRUCTION, NULL );
196 #endif
197 #ifdef CYGNUM_HAL_EXCEPTION_DIV_BY_ZERO
198     HAL_VSR_SET_TO_ECOS_HANDLER( CYGNUM_HAL_EXCEPTION_DIV_BY_ZERO, NULL );
199 #endif
200 #ifdef CYGNUM_HAL_EXCEPTION_FPU
201     HAL_VSR_SET_TO_ECOS_HANDLER( CYGNUM_HAL_EXCEPTION_FPU, NULL );
202 #endif
203 #ifdef CYGNUM_HAL_EXCEPTION_FPU_DIV_BY_ZERO
204     HAL_VSR_SET_TO_ECOS_HANDLER( CYGNUM_HAL_EXCEPTION_FPU_DIV_BY_ZERO, NULL );
205 #endif
206 #endif
207
208 #ifdef CYGSEM_LIBC_SIGNALS_HWEXCEPTIONS
209
210
211     // Test 1
212
213     CYG_TEST_INFO("Test 1");
214
215     handler1 = signal(SIGSEGV, &myhandler);
216
217     CYG_TEST_PASS_FAIL(handler1 == SIG_DFL,
218                        "SIGSEGV handler initialized to default");
219
220
221     handler1 = signal(SIGBUS, &myhandler);
222
223     CYG_TEST_PASS_FAIL(handler1 == SIG_DFL,
224                        "SIGBUS handler initialized to default");
225
226
227     handler1 = signal(SIGILL, &myhandler);
228
229     CYG_TEST_PASS_FAIL(handler1 == SIG_DFL,
230                        "SIGILL handler initialized to default");
231
232     handler1 = signal(SIGSYS, &myhandler);
233
234     CYG_TEST_PASS_FAIL(handler1 == SIG_DFL,
235                        "SIGSYS handler initialized to default");
236
237     handler1 = signal(SIGTRAP, &myhandler);
238
239     CYG_TEST_PASS_FAIL(handler1 == SIG_DFL,
240                        "SIGTRAP handler initialized to default");
241
242     handler1 = signal(SIGFPE, &myhandler);
243
244     CYG_TEST_PASS_FAIL(handler1 == SIG_DFL,
245                        "SIGFPE handler initialized to default");
246
247     // Test 2
248
249     CYG_TEST_INFO("Test 2");
250
251     state = 2;
252
253 #if defined(CYGPKG_HAL_POWERPC_SIM)
254     // The exception generated by the SIM is not recognized by GDB.
255     // PR 19945 workaround.
256     CYG_TEST_PASS("Test 2 not applicable to PowerPC SIM");
257 #else
258     if (0==setjmp(jbuf)) {
259         cause_memerror();
260         CYG_TEST_FAIL("Didn't cause exception");
261     }
262     
263     CYG_TEST_PASS_FAIL(3==state, "handler returned correctly");
264 #endif
265
266     // Test 3
267
268     CYG_TEST_INFO("Test 3");
269     
270     state = 3;
271
272 #ifdef CYGNUM_HAL_EXCEPTION_FPU_DIV_BY_ZERO
273
274     if (0==setjmp(jbuf)) {
275         // It is necessary to save the return value in a volatile
276         // variable, or GCC will get rid of the call.
277         tmp = cause_fpe(0);
278         CYG_TEST_FAIL("Didn't cause exception");
279     }
280     
281     CYG_TEST_PASS_FAIL(4==state, "handler returned correctly");
282
283 #else
284
285     CYG_TEST_INFO("Test 3 - provoke FP error - not supported");    
286     
287 #endif    
288
289 #else
290     CYG_TEST_NA("Testing not applicable to this configuration");
291 #endif
292
293     CYG_TEST_FINISH("Finished tests from testcase " __FILE__ " for C "
294                     "library signal functions");
295
296     return 0;
297 } // main()
298
299 // EOF signal2.c