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