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