]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/compat/posix/v2_0/tests/sigsetjmp.c
unified MX27, MX25, MX37 trees
[karo-tx-redboot.git] / packages / compat / posix / v2_0 / tests / sigsetjmp.c
1 //==========================================================================
2 //
3 //        sigsetjmp.c
4 //
5 //        POSIX sigsetjmp 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):     nickg
44 // Contributors:  nickg
45 // Date:          2000-04-10
46 // Description:   Tests POSIX sigsetjmp functionality.
47 //
48 //####DESCRIPTIONEND####
49 //==========================================================================
50
51 #include <cyg/infra/testcase.h>
52 #include <pkgconf/posix.h>
53
54 #if !defined(CYGPKG_POSIX_SIGNALS)
55 #define NA_MSG "POSIX signals not enabled"
56 #elif !defined(CYGPKG_POSIX_PTHREAD)
57 #define NA_MSG "POSIX threads not enabled"
58 #elif !defined(CYGPKG_POSIX_SEMAPHORES)
59 #define NA_MSG "POSIX semaphores not enabled"
60 #endif
61
62 #ifdef NA_MSG
63 void
64 cyg_start(void)
65 {
66     CYG_TEST_INIT();
67     CYG_TEST_NA(NA_MSG);
68 }
69 #else
70
71 #include <sys/types.h>
72 #include <pthread.h>
73 #include <signal.h>
74 #include <semaphore.h>
75 #include <time.h>
76 #include <setjmp.h>
77
78 #include <cyg/infra/testcase.h>
79
80 //--------------------------------------------------------------------------
81 // Thread stack.
82
83 char thread1_stack[PTHREAD_STACK_MIN*2];
84 char thread2_stack[PTHREAD_STACK_MIN*2];
85
86 //--------------------------------------------------------------------------
87 // Local variables
88
89 // Sync semaphore
90 sem_t sem;
91
92 // Thread IDs
93 pthread_t thread1;
94 pthread_t thread2;
95
96 timer_t timer1;
97 timer_t timer2;
98
99 volatile int sigusr1_called = 0;
100 volatile int sigusr2_called = 0;
101
102 sigjmp_buf jmpbuf1;
103 sigjmp_buf jmpbuf2;
104
105 //--------------------------------------------------------------------------
106 // Signal handler functions
107
108 static void sigusr1( int signo, siginfo_t *info, void *context )
109 {
110     CYG_TEST_INFO( "sigusr1() handler called" );
111     CYG_TEST_CHECK( signo == SIGUSR1, "Signal not SIGUSR1");
112     CYG_TEST_CHECK( signo == info->si_signo, "Bad signal number in siginfo" );
113     CYG_TEST_CHECK( info->si_code == SI_TIMER, "Siginfo code not SI_TIMER" );
114     CYG_TEST_CHECK( info->si_value.sival_int == 0xABCDEF01, "Siginfo value wrong");
115     CYG_TEST_CHECK( pthread_equal(pthread_self(), thread1), "Not called in thread1");
116
117     sigusr1_called++;
118
119     CYG_TEST_INFO( "sigusr1() handler calling siglongjmp()" );
120     
121     siglongjmp( jmpbuf1, sigusr1_called );
122 }
123
124 static void sigusr2( int signo, siginfo_t *info, void *context )
125 {
126     CYG_TEST_INFO( "sigusr2() handler called" );
127     CYG_TEST_CHECK( signo == SIGUSR2, "Signal not SIGUSR2");
128     CYG_TEST_CHECK( signo == info->si_signo, "Bad signal number in siginfo" );
129     CYG_TEST_CHECK( info->si_code == SI_TIMER, "Siginfo code not SI_TIMER" );
130     CYG_TEST_CHECK( info->si_value.sival_int == 0xABCDEF02, "Siginfo value wrong");
131     CYG_TEST_CHECK( pthread_equal(pthread_self(), thread2), "Not called in thread2");
132
133     sigusr2_called++;
134
135     CYG_TEST_INFO( "sigusr2() handler calling siglongjmp()" );
136     siglongjmp( jmpbuf2, sigusr2_called );    
137 }
138
139 //--------------------------------------------------------------------------
140
141 void *pthread_entry1( void *arg)
142 {
143     sigset_t mask;
144
145     
146     CYG_TEST_INFO( "Thread 1 running" );
147
148     // Make a full set
149     sigfillset( &mask );
150
151     // remove USR1 signal
152     sigdelset( &mask, SIGUSR1 );
153
154     // Set signal mask
155     pthread_sigmask( SIG_SETMASK, &mask, NULL );
156     
157     // Get main thread going again
158     sem_post( &sem );
159
160     do
161     {
162         sigset_t curmask;
163
164         CYG_TEST_INFO( "Thread1: calling sigsetjmp()");                
165         if( sigsetjmp( jmpbuf1, 1 ) != 0 )
166             CYG_TEST_INFO( "Thread1: sigsetjmp() returned non-zero");
167         
168         pthread_sigmask( SIG_SETMASK, NULL, &curmask );
169         CYG_TEST_CHECK( curmask == mask, "Thread1: Signal masks not equal" );
170
171         if ( sigusr1_called >= 1 )
172             break;
173         
174         CYG_TEST_INFO( "Thread1: calling pause()");        
175         pause();
176
177         CYG_TEST_INFO( "Thread1: pause() returned");        
178     } while(1);
179
180     CYG_TEST_INFO( "Thread1: calling pthread_exit()");    
181     pthread_exit( arg );
182 }
183
184 //--------------------------------------------------------------------------
185
186 void *pthread_entry2( void *arg)
187 {
188     sigset_t mask;
189     
190     CYG_TEST_INFO( "Thread 2 running" );
191
192     // Make a full set
193     sigfillset( &mask );
194
195     // remove USR2 signal
196     sigdelset( &mask, SIGUSR2 );
197
198     // Set signal mask
199     pthread_sigmask( SIG_SETMASK, &mask, NULL );
200     
201     // Get main thread going again
202     sem_post( &sem );
203
204     do 
205     {
206         sigset_t curmask;
207
208         CYG_TEST_INFO( "Thread2: calling sigsetjmp()");
209         if( sigsetjmp( jmpbuf2, 1 ) != 0 )
210             CYG_TEST_INFO( "Thread2: sigsetjmp() returned non-zero");
211         
212         pthread_sigmask( SIG_SETMASK, NULL, &curmask );
213         CYG_TEST_CHECK( curmask == mask, "Thread2: Signal masks not equal" );
214
215         if ( sigusr2_called >= 6 )
216             break;
217         
218         CYG_TEST_INFO( "Thread2: calling pause()");        
219         pause();
220
221         CYG_TEST_INFO( "Thread2: pause() returned");
222     } while(1);
223
224     CYG_TEST_INFO( "Thread2: calling pthread_exit()");    
225     pthread_exit( arg );
226 }
227
228 //--------------------------------------------------------------------------
229
230 int main(int argc, char **argv)
231 {
232     int ret;
233     sigset_t mask;
234     pthread_attr_t attr;
235     void *retval;
236     
237     CYG_TEST_INIT();
238
239     // Make a full signal set
240     sigfillset( &mask );
241
242     
243     // Install signal handlers
244     {
245         struct sigaction sa;
246
247         sa.sa_sigaction = sigusr1;
248         sa.sa_mask = mask;
249         sa.sa_flags = SA_SIGINFO;
250
251         ret = sigaction( SIGUSR1, &sa, NULL );
252
253         CYG_TEST_CHECK( ret == 0 , "sigaction returned error");
254     }
255     {
256         struct sigaction sa;
257
258         sa.sa_sigaction = sigusr2;
259         sa.sa_mask = mask;
260         sa.sa_flags = SA_SIGINFO;
261
262         ret = sigaction( SIGUSR2, &sa, NULL );
263
264         CYG_TEST_CHECK( ret == 0 , "sigaction returned error");
265     }
266
267
268     // Create the timers
269
270     {
271         struct sigevent sev;
272         struct itimerspec value;
273         
274         sev.sigev_notify                = SIGEV_SIGNAL;
275         sev.sigev_signo                 = SIGUSR1;
276         sev.sigev_value.sival_int       = 0xABCDEF01;
277
278         value.it_value.tv_sec           = 1;
279         value.it_value.tv_nsec          = 0;
280         value.it_interval.tv_sec        = 0;
281         value.it_interval.tv_nsec       = 0;
282         
283         ret = timer_create( CLOCK_REALTIME, &sev, &timer1 );
284
285         CYG_TEST_CHECK( ret == 0 , "timer_create returned error");
286
287         ret = timer_settime( timer1, 0, &value, NULL );
288
289         CYG_TEST_CHECK( ret == 0 , "timer_settime returned error");
290     }
291
292     {
293         struct sigevent sev;
294         struct itimerspec value;
295         
296         sev.sigev_notify                = SIGEV_SIGNAL;
297         sev.sigev_signo                 = SIGUSR2;
298         sev.sigev_value.sival_int       = 0xABCDEF02;
299
300         value.it_value.tv_sec           = 0;
301         value.it_value.tv_nsec          = 500000000;
302         value.it_interval.tv_sec        = 0;
303         value.it_interval.tv_nsec       = 250000000;
304         
305         ret = timer_create( CLOCK_REALTIME, &sev, &timer2 );
306
307         CYG_TEST_CHECK( ret == 0 , "timer_create returned error");
308
309         ret = timer_settime( timer2, 0, &value, NULL );
310
311         CYG_TEST_CHECK( ret == 0 , "timer_settime returned error");
312     }
313
314     
315     // Mask all signals
316     pthread_sigmask( SIG_SETMASK, &mask, NULL );
317     
318     sem_init( &sem, 0, 0 );
319     
320     // Create test threads
321
322     {
323         pthread_attr_init( &attr );
324
325         pthread_attr_setstackaddr( &attr, (void *)&thread1_stack[sizeof(thread1_stack)] );
326         pthread_attr_setstacksize( &attr, sizeof(thread1_stack) );
327
328         pthread_create( &thread1,
329                         &attr,
330                         pthread_entry1,
331                         (void *)0x12345671);
332     }
333
334     {
335         pthread_attr_init( &attr );
336
337         pthread_attr_setstackaddr( &attr, (void *)&thread2_stack[sizeof(thread2_stack)] );
338         pthread_attr_setstacksize( &attr, sizeof(thread2_stack) );
339
340         pthread_create( &thread2,
341                         &attr,
342                         pthread_entry2,
343                         (void *)0x12345672);
344     }
345     
346     // Wait for other thread to get started
347     CYG_TEST_INFO( "Main: calling sem_wait()");
348     sem_wait( &sem );
349     CYG_TEST_INFO( "Main: calling sem_wait() again");    
350     sem_wait( &sem );
351
352     // Now join with thread1
353     CYG_TEST_INFO( "Main: calling pthread_join(thread1)");
354     pthread_join( thread1, &retval );
355
356     CYG_TEST_CHECK( retval == (void *)0x12345671, "Thread 1 retval wrong");
357     
358     // And thread 2
359     CYG_TEST_INFO( "Main: calling pthread_join(thread2)");
360     pthread_join( thread2, &retval );
361
362     // now delete the timers
363     CYG_TEST_INFO( "Main: calling timer_delete(timer1)");    
364     ret = timer_delete( timer1 );
365
366     CYG_TEST_CHECK( ret == 0 , "timer_delete(timer1) returned error");
367
368     CYG_TEST_INFO( "Main: calling timer_delete(timer2)");    
369     ret = timer_delete( timer2 );
370
371     CYG_TEST_CHECK( ret == 0 , "timer_delete(timer2) returned error");
372
373     
374     CYG_TEST_CHECK( retval == (void *)0x12345672, "Thread 2 retval wrong");
375     
376     CYG_TEST_CHECK( sigusr1_called == 1, "SIGUSR1 signal handler not called once" );
377     CYG_TEST_CHECK( sigusr2_called == 6, "SIGUSR2 signal handler not called six times" );
378
379     CYG_TEST_PASS_FINISH( "sigsetjmp" );
380 }
381
382 #endif
383
384 //--------------------------------------------------------------------------
385 // end of sigsetjmp.c