1 //==========================================================================
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.
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.
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
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.
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.
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.
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####
44 // Contributors: nickg
46 // Description: Tests POSIX signal functionality.
48 //####DESCRIPTIONEND####
49 //==========================================================================
51 #include <cyg/infra/testcase.h>
52 #include <pkgconf/posix.h>
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"
71 #include <sys/types.h>
74 #include <semaphore.h>
77 //--------------------------------------------------------------------------
80 char thread_stack[PTHREAD_STACK_MIN*2];
82 //--------------------------------------------------------------------------
91 volatile int sigusr2_called = 0;
92 volatile int sigalrm_called = 0;
94 //--------------------------------------------------------------------------
95 // Signal handler functions
97 static void sigusr2( int signo )
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");
106 static void sigalrm( int signo )
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");
115 //--------------------------------------------------------------------------
117 void *pthread_entry1( void *arg)
121 struct timespec timeout;
124 CYG_TEST_INFO( "Thread 1 running" );
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");
140 // remove USR2 and ALRM signals
141 sigdelset( &mask, SIGUSR2 );
142 sigdelset( &mask, SIGALRM );
145 pthread_sigmask( SIG_SETMASK, &mask, NULL );
147 // Get main thread going again
154 CYG_TEST_INFO( "Thread1: calling sigtimedwait()");
156 // Wait for a signal to be delivered
157 sig = sigtimedwait( &mask, &info, &timeout );
159 sig2 = info.si_signo;
161 CYG_TEST_CHECK( sig == sig2, "sigtimedwait return value not equal");
162 CYG_TEST_CHECK( sig == SIGUSR1, "Signal not delivered");
164 while( sigusr2_called != 2 )
166 CYG_TEST_INFO( "Thread1: calling pause()");
170 errno = 0; // strictly correct to reset errno first
172 // now wait for SIGALRM to be delivered
173 CYG_TEST_INFO( "Thread1: calling pause()");
175 CYG_TEST_CHECK( -1==err, "pause returned -1");
176 CYG_TEST_CHECK( EINTR==errno, "errno set to EINTR");
178 // generate another SIGALRM and wait for it to be delivered too
179 // we need to mask it first though
185 pthread_sigmask( SIG_SETMASK, &mask, NULL );
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");
193 CYG_TEST_INFO( "Thread1: calling pthread_exit()");
194 pthread_exit( (void *)((int)arg+sig2) );
197 //--------------------------------------------------------------------------
199 int main(int argc, char **argv)
209 // Make a full signal set
213 // Install signal handlers
217 sa.sa_handler = sigusr2;
221 ret = sigaction( SIGUSR2, &sa, NULL );
223 CYG_TEST_CHECK( ret == 0 , "sigaction returned error");
229 sa.sa_handler = sigalrm;
233 ret = sigaction( SIGALRM, &sa, NULL );
235 CYG_TEST_CHECK( ret == 0 , "sigaction returned error");
240 pthread_sigmask( SIG_SETMASK, &mask, NULL );
242 sem_init( &sem, 0, 0 );
244 // Create test thread
245 pthread_attr_init( &attr );
247 pthread_attr_setstackaddr( &attr, (void *)&thread_stack[sizeof(thread_stack)] );
248 pthread_attr_setstacksize( &attr, sizeof(thread_stack) );
250 pthread_create( &thread1,
255 // Wait for other thread to get started
256 CYG_TEST_INFO( "Main: calling sem_wait()");
261 // send a signal to the other thread
262 CYG_TEST_INFO( "Main: calling sigqueue(SIGUSR1)");
263 sigqueue( 0, SIGUSR1, value );
265 // Send the signal via kill
266 CYG_TEST_INFO( "Main: calling kill(0, SIGUSR2)");
269 // Wait for thread1 to call pause()
270 CYG_TEST_INFO( "Main: calling sleep(1)");
274 CYG_TEST_INFO( "Main: calling kill(0, SIGUSR2)");
277 // Set up an alarm for 1 second hence
278 CYG_TEST_INFO( "Main: calling alarm(1)");
281 // Wait for alarm signal to be delivered to thread1
282 CYG_TEST_INFO( "Main: calling sleep(2)");
285 // Now join with thread1
286 CYG_TEST_INFO( "Main: calling pthread_join()");
287 pthread_join( thread1, &retval );
289 CYG_TEST_CHECK( sigusr2_called == 2, "SIGUSR2 signal handler not called twice" );
291 CYG_TEST_CHECK( sigalrm_called == 1, "SIGALRM signal handler not called" );
295 if( (long)retval == 0x12345678+SIGUSR1 )
296 CYG_TEST_PASS_FINISH( "signal1" );
298 CYG_TEST_FAIL_FINISH( "signal1" );
303 //--------------------------------------------------------------------------