]> git.karo-electronics.de Git - karo-tx-redboot.git/blob - packages/compat/posix/v2_0/tests/signal1.c
f414c28a85dfd60075b54140d137c1d427305be1
[karo-tx-redboot.git] / packages / compat / posix / v2_0 / tests / signal1.c
1 //==========================================================================
2 //
3 //        signal1.cxx
4 //
5 //        POSIX signal test 1
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 signal 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 #endif
59
60 #ifdef NA_MSG
61 void
62 cyg_start(void)
63 {
64     CYG_TEST_INIT();
65     CYG_TEST_NA(NA_MSG);
66 }
67 #else
68
69 #include <sys/types.h>
70 #include <pthread.h>
71 #include <signal.h>
72 #include <semaphore.h>
73 #include <errno.h>
74
75 //--------------------------------------------------------------------------
76 // Thread stack.
77
78 char thread_stack[PTHREAD_STACK_MIN*2];
79
80 //--------------------------------------------------------------------------
81 // Local variables
82
83 // Sync semaphore
84 sem_t sem;
85
86 // Thread ID
87 pthread_t thread1;
88
89 volatile int sigusr2_called = 0;
90 volatile int sigalrm_called = 0;
91
92 //--------------------------------------------------------------------------
93 // Signal handler functions
94
95 static void sigusr2( int signo )
96 {
97     CYG_TEST_INFO( "sigusr2() handler called" );
98     CYG_TEST_CHECK( signo == SIGUSR2, "Signal not SIGUSR2");
99     CYG_TEST_CHECK( pthread_equal(pthread_self(), thread1), "Not called in thread1");
100
101     sigusr2_called++;
102 }
103
104 static void sigalrm( int signo )
105 {
106     CYG_TEST_INFO( "sigalrm() handler called" );
107     CYG_TEST_CHECK( signo == SIGALRM, "Signal not SIGALRM");
108     CYG_TEST_CHECK( pthread_equal(pthread_self(), thread1), "Not called in thread1");
109
110     sigalrm_called++;
111 }
112
113 //--------------------------------------------------------------------------
114
115 void *pthread_entry1( void *arg)
116 {
117     sigset_t mask;
118     siginfo_t info;
119     struct timespec timeout;
120     int sig, sig2, err;
121     
122     CYG_TEST_INFO( "Thread 1 running" );
123
124     // Should have inherited parent's signal mask
125     pthread_sigmask( 0, NULL, &mask );
126     CYG_TEST_CHECK( sigismember( &mask, SIGALRM),
127                                  "SIGALRM mask inherited");
128     CYG_TEST_CHECK( sigismember( &mask, SIGUSR1),
129                                  "SIGUSR1 mask inherited");
130     CYG_TEST_CHECK( sigismember( &mask, SIGUSR2),
131                                  "SIGUSR2 mask inherited");
132     CYG_TEST_CHECK( sigismember( &mask, SIGSEGV),
133                                  "SIGSEGV mask inherited");
134
135     // Make a full set
136     sigfillset( &mask );
137
138     // remove USR2 and ALRM signals
139     sigdelset( &mask, SIGUSR2 );
140     sigdelset( &mask, SIGALRM );
141
142     // Set signal mask
143     pthread_sigmask( SIG_SETMASK, &mask, NULL );
144     
145     // Get main thread going again
146     sem_post( &sem );
147
148     // set up timeout
149     timeout.tv_sec = 10;
150     timeout.tv_nsec = 0;
151
152     CYG_TEST_INFO( "Thread1: calling sigtimedwait()");
153     
154     // Wait for a signal to be delivered
155     sig = sigtimedwait( &mask, &info, &timeout );
156
157     sig2 = info.si_signo;
158     
159     CYG_TEST_CHECK( sig == sig2, "sigtimedwait return value not equal");
160     CYG_TEST_CHECK( sig == SIGUSR1, "Signal not delivered");
161
162     while( sigusr2_called != 2 )
163     {
164         CYG_TEST_INFO( "Thread1: calling pause()");        
165         pause();
166     }
167
168     errno = 0; // strictly correct to reset errno first
169
170     // now wait for SIGALRM to be delivered
171     CYG_TEST_INFO( "Thread1: calling pause()");            
172     err = pause();
173     CYG_TEST_CHECK( -1==err, "pause returned -1");
174     CYG_TEST_CHECK( EINTR==errno, "errno set to EINTR");
175
176     // generate another SIGALRM and wait for it to be delivered too
177     // we need to mask it first though
178
179     // Make a full set
180     sigfillset( &mask );
181
182     // Set signal mask
183     pthread_sigmask( SIG_SETMASK, &mask, NULL );
184     
185     alarm(1);
186     CYG_TEST_INFO( "Thread1: calling sigwait()");            
187     err = sigwait( &mask, &sig);
188     CYG_TEST_CHECK( 0==err, "sigwait returned -1");
189     CYG_TEST_CHECK( sig==SIGALRM, "sigwait caught alarm");
190
191     CYG_TEST_INFO( "Thread1: calling pthread_exit()");    
192     pthread_exit( (void *)((int)arg+sig2) );
193 }
194
195 //--------------------------------------------------------------------------
196
197 int main(int argc, char **argv)
198 {
199     int ret;
200     sigset_t mask;
201     pthread_attr_t attr;
202     void *retval;
203     union sigval value;
204     
205     CYG_TEST_INIT();
206
207     // Make a full signal set
208     sigfillset( &mask );
209
210     
211     // Install signal handlers
212     {
213         struct sigaction sa;
214
215         sa.sa_handler = sigusr2;
216         sa.sa_mask = mask;
217         sa.sa_flags = 0;
218
219         ret = sigaction( SIGUSR2, &sa, NULL );
220
221         CYG_TEST_CHECK( ret == 0 , "sigaction returned error");
222     }
223
224     {
225         struct sigaction sa;
226
227         sa.sa_handler = sigalrm;
228         sa.sa_mask = mask;
229         sa.sa_flags = 0;
230
231         ret = sigaction( SIGALRM, &sa, NULL );
232
233         CYG_TEST_CHECK( ret == 0 , "sigaction returned error");
234     }
235     
236     
237     // Mask all signals
238     pthread_sigmask( SIG_SETMASK, &mask, NULL );
239     
240     sem_init( &sem, 0, 0 );
241     
242     // Create test thread
243     pthread_attr_init( &attr );
244
245     pthread_attr_setstackaddr( &attr, (void *)&thread_stack[sizeof(thread_stack)] );
246     pthread_attr_setstacksize( &attr, sizeof(thread_stack) );
247
248     pthread_create( &thread1,
249                     &attr,
250                     pthread_entry1,
251                     (void *)0x12345678);
252
253     // Wait for other thread to get started
254     CYG_TEST_INFO( "Main: calling sem_wait()");
255     sem_wait( &sem );
256
257     value.sival_int = 0;
258
259     // send a signal to the other thread
260     CYG_TEST_INFO( "Main: calling sigqueue(SIGUSR1)");
261     sigqueue( 0, SIGUSR1, value );
262
263     // Send the signal via kill
264     CYG_TEST_INFO( "Main: calling kill(0, SIGUSR2)");
265     kill( 0, SIGUSR2 );
266
267     // Wait for thread1 to call pause()
268     CYG_TEST_INFO( "Main: calling sleep(1)");
269     sleep(1);
270
271     // And again
272     CYG_TEST_INFO( "Main: calling kill(0, SIGUSR2)");
273     kill( 0, SIGUSR2 );
274
275     // Set up an alarm for 1 second hence
276     CYG_TEST_INFO( "Main: calling alarm(1)");
277     alarm(1);
278     
279     // Wait for alarm signal to be delivered to thread1
280     CYG_TEST_INFO( "Main: calling sleep(2)");
281     sleep(2);
282     
283     // Now join with thread1
284     CYG_TEST_INFO( "Main: calling pthread_join()");
285     pthread_join( thread1, &retval );
286
287     CYG_TEST_CHECK( sigusr2_called == 2, "SIGUSR2 signal handler not called twice" );
288
289     CYG_TEST_CHECK( sigalrm_called == 1, "SIGALRM signal handler not called" );    
290     
291     // check retval
292     
293     if( (long)retval == 0x12345678+SIGUSR1 )
294         CYG_TEST_PASS_FINISH( "signal1" );
295     else
296         CYG_TEST_FAIL_FINISH( "signal1" );
297 }
298
299 #endif
300
301 //--------------------------------------------------------------------------
302 // end of signal1.c