source: rtems/testsuites/psxtests/psxtimer01/psxtimer.c @ 17c7533

4.104.11
Last change on this file since 17c7533 was 17c7533, checked in by Ralf Corsepius <ralf.corsepius@…>, on Oct 27, 2009 at 3:57:28 AM

Use %ld to print *.tv_nsec.

  • Property mode set to 100644
File size: 12.4 KB
Line 
1/*
2 *
3 *  This is a simple real-time applications which contains 3 periodic tasks.
4 *
5 *  Task A is an independent task.
6 *
7 *  Task B and C share a data.
8 *
9 *  Tasks are implemented as POSIX threads.
10 *
11 *  The share data is protected with a POSIX mutex.
12 *
13 *  Other POSIX facilities such as timers, condition, .. is also used
14 *
15 *  COPYRIGHT (c) 1989-2009.
16 *  On-Line Applications Research Corporation (OAR).
17 *
18 *  The license and distribution terms for this file may be
19 *  found in the file LICENSE in this distribution or at
20 *  http://www.rtems.com/license/LICENSE.
21 *
22 *  $Id$
23 */
24
25#define CONFIGURE_INIT
26#include "system.h"
27#include <pthread.h>  /* thread facilities */
28#include <signal.h>   /* signal facilities */
29#include <unistd.h>   /* sleep facilities */
30#include <sched.h>    /* schedule facilities */
31#include <time.h>     /* time facilities */
32#include <stdio.h>    /* console facilities */
33#include <rtems/score/timespec.h>
34
35void StopTimer(
36  timer_t  timer_id,
37  struct   itimerspec *timerdata
38);
39
40/* temporal parameters of a task */
41
42struct periodic_params {
43   struct timespec period;
44   int count;       /* Number of iterations to run */
45   int signo;       /* signal number */
46   int id;          /* task identification */
47 };
48
49pthread_attr_t attr;
50
51/* shared datum */
52
53struct shared_data {
54   pthread_mutex_t mutex;
55   pthread_cond_t  sync;
56   int updated;
57 };
58
59struct shared_data data;
60
61void StopTimer(
62  timer_t  timer_id,
63  struct   itimerspec *timerdata
64)
65{
66  static int         firstTime = 1;
67  struct itimerspec *pOld;
68  struct itimerspec  odata;
69
70  /*
71   *  We do not care about the old value.  But we need to exercise
72   *  getting and not getting the return value back.
73   */
74  pOld = (firstTime == 1) ? NULL : &odata;
75  firstTime = 0;
76
77  timerdata->it_value.tv_sec  = 0;
78  timerdata->it_value.tv_nsec  = 0;
79  if (timer_settime(timer_id,POSIX_TIMER_RELATIVE,timerdata,pOld) == -1) {
80    perror ("Error in timer setting\n");
81    rtems_test_exit(0);
82  }
83}
84 
85/* task A  */
86void * task_a (void *arg)
87{
88   struct   timespec my_period;
89   int      my_sig, received_sig;
90   struct   itimerspec timerdata;
91   struct   itimerspec timergetdata;
92   timer_t  timer_id;
93   time_t   clock;
94   struct   sigevent event;
95   sigset_t set;
96   struct periodic_params *params;
97
98   params = arg;
99   my_period = params->period;
100   my_sig    = params->signo;
101
102   /* timer create */
103   event.sigev_notify = SIGEV_SIGNAL;
104   event.sigev_signo = my_sig;
105   if (timer_create (CLOCK_REALTIME, &event, &timer_id) == -1) {
106      perror ("Error in timer creation\n");
107      rtems_test_exit(0);
108    }
109
110   /* block the timer signal */
111   sigemptyset (&set);
112   sigaddset (&set,my_sig);
113   pthread_sigmask(SIG_BLOCK,&set,NULL);
114
115   /* set the timer in periodic mode */
116   timerdata.it_interval = my_period;
117   timerdata.it_value    = my_period;
118   timerdata.it_value.tv_sec *= 2;
119   if (timer_settime(timer_id,POSIX_TIMER_RELATIVE,&timerdata,&timergetdata) == -1) {
120     perror ("Error in timer setting\n");
121     rtems_test_exit(0);
122   }
123   printf(
124    "task A: timer_settime - value=%" PRItime_t ":%ld interval=%" PRItime_t ":%ld\n",
125    timergetdata.it_value.tv_sec, timergetdata.it_value.tv_nsec,
126    timergetdata.it_interval.tv_sec, timergetdata.it_interval.tv_nsec
127  );
128   
129
130   /* periodic activity */
131   while(1) {
132     if (sigwait(&set,&received_sig) == -1) {
133       perror ("Error in sigwait\n");
134     }
135     if (timer_gettime(timer_id, &timerdata) == -1) {
136       perror ("Error in timer_gettime\n");
137       rtems_test_exit(0);
138     }
139     if (! _Timespec_Equal_to( &timerdata.it_value, &my_period )){
140       perror ("Error in Task A timer_gettime\n");
141     }
142     clock = time(NULL);
143     printf("Executing task A with count = %2i %s", params->count, ctime(&clock));
144     params->count--;
145     if (params->count == 0)
146       StopTimer(timer_id, &timerdata);
147   }
148   return NULL;
149}
150
151/* task B  */
152
153void * task_b (void *arg)
154{
155   struct   timespec my_period;
156   struct   timespec now;
157   int      my_sig, received_sig;
158   struct   itimerspec timerdata;
159   timer_t  timer_id;
160   time_t   clock;
161   struct   sigevent event;
162   sigset_t set;
163   struct periodic_params *params;
164
165   params = arg;
166   my_period = params->period;
167   my_sig    = params->signo;
168
169
170   /* timer create */
171   event.sigev_notify = SIGEV_SIGNAL;
172   event.sigev_signo = my_sig;
173   if (timer_create (CLOCK_REALTIME, &event, &timer_id) == -1) {
174      perror ("Error in timer creation\n");
175      rtems_test_exit(0);
176    }
177
178   /* block the timer signal */
179   sigemptyset (&set);
180   sigaddset (&set,my_sig);
181   pthread_sigmask(SIG_BLOCK,&set,NULL);
182
183   /* set the timer in periodic mode */
184   clock_gettime( CLOCK_REALTIME, &now );
185   timerdata.it_interval = my_period;
186   timerdata.it_value = now;
187   _Timespec_Add_to( &timerdata.it_value, &my_period );
188   if (timer_settime(timer_id,TIMER_ABSTIME,&timerdata,NULL) == -1) {
189     perror ("Error in timer setting\n");
190     rtems_test_exit(0);
191   }     
192
193   /* periodic activity */
194   while(1) {
195     if (sigwait(&set,&received_sig) == -1) {
196       perror ("Error in sigwait\n");
197       rtems_test_exit(0);
198     }
199 
200     if (timer_gettime(timer_id, &timerdata) == -1) {
201       perror ("Error in timer_gettime\n");
202       rtems_test_exit(0);
203     }
204
205#if 0
206     /*
207      *  It is not an error if they are not equal.  A clock tick could occur
208      *  and thus they are close but not equal.  Can we test for this?
209      */
210     if ( !_Timespec_Equal_to( &timerdata.it_value, &my_period) ){
211       printf( "NOT EQUAL %d:%d != %d:%d\n",
212          timerdata.it_value.tv_sec,
213          timerdata.it_value.tv_nsec,
214          my_period.tv_sec,
215          my_period.tv_nsec
216       );
217       rtems_test_exit(0);
218     }
219#endif
220
221     pthread_mutex_lock (&data.mutex);
222     clock = time(NULL);
223     printf("Executing task B with count = %2i %s", 
224       params->count, ctime(&clock) 
225     );
226     data.updated = TRUE;
227     pthread_cond_signal  (&data.sync);
228     pthread_mutex_unlock (&data.mutex);
229     params->count--;
230     if (params->count == 0)
231       StopTimer(timer_id, &timerdata);
232   }
233   return NULL;
234}
235
236/* task C */
237
238void * task_c (void *arg)
239{
240   int      count;
241   struct   timespec my_period;
242   int      my_sig, received_sig;
243   struct   itimerspec timerdata;
244   struct   itimerspec timergetdata;
245   timer_t  timer_id;
246   time_t   clock;
247   struct   sigevent event;
248   sigset_t set;
249   struct   periodic_params *params;
250
251   params = arg;
252   my_period = params->period;
253   my_sig    = params->signo;
254
255   /* timer create */
256   event.sigev_notify = SIGEV_SIGNAL;
257   event.sigev_signo = my_sig;
258   if (timer_create (CLOCK_REALTIME, &event, &timer_id) == -1) {
259      perror ("Error in timer creation\n");
260      rtems_test_exit(0);
261    }
262
263   /* block the timer signal */
264   sigemptyset (&set);
265   sigaddset (&set,my_sig);
266   pthread_sigmask(SIG_BLOCK,&set,NULL);
267
268   /* set the timer in periodic mode */
269   timerdata.it_interval = my_period;
270   timerdata.it_value    = my_period;
271   timerdata.it_value.tv_sec *= 2;
272   if (timer_settime(timer_id,POSIX_TIMER_RELATIVE,&timerdata,NULL) == -1) {
273     perror ("Error in timer setting\n");
274     rtems_test_exit(0);
275   }
276
277   /* periodic activity */
278   for (count=0 ; ; count++) {
279      if (sigwait(&set,&received_sig) == -1) {
280       perror ("Error in sigwait\n");
281       rtems_test_exit(0);
282     }
283     if (timer_gettime(timer_id, &timerdata) == -1) {
284       perror ("Error in timer_gettime\n");
285       rtems_test_exit(0);
286     }
287     if (! _Timespec_Equal_to( &timerdata.it_value, &my_period) ){
288       perror ("Error in Task C timer_gettime\n");
289     }
290     pthread_mutex_lock (&data.mutex);
291     while (data.updated == FALSE) {
292       pthread_cond_wait (&data.sync,&data.mutex);
293     }
294     clock = time(NULL);
295     printf("Executing task C with count = %2i %s", 
296       params->count, ctime(&clock) 
297     );
298
299     if ( count && (count % 5) == 0 ) {
300       int overruns = 0;
301       sleep(1);
302       overruns = timer_getoverrun( timer_id );
303       printf( "task C: timer_getoverrun - overruns=%d\n", overruns );
304     
305       if (timer_gettime(timer_id, &timergetdata) == -1) {
306         perror ("Error in timer setting\n");
307         rtems_test_exit(0);
308       }
309       printf(
310         "task C: timer_gettime - %" PRItime_t ":%ld remaining from %" PRItime_t ":%ld\n",
311         timergetdata.it_value.tv_sec, timergetdata.it_value.tv_nsec,
312         timergetdata.it_interval.tv_sec, timergetdata.it_interval.tv_nsec
313       );
314     }
315
316     pthread_mutex_unlock (&data.mutex);
317     params->count--;
318     if (params->count == 0)
319       StopTimer(timer_id, &timerdata);
320   }
321   return NULL;
322}
323
324/* main */
325
326void *POSIX_Init (
327  void *argument
328)
329
330{
331   pthread_mutexattr_t mutexattr;    /* mutex attributes */
332   pthread_condattr_t  condattr;     /* condition attributes */
333   pthread_attr_t attr;              /* task attributes */
334   pthread_t ta,tb,tc, tc1;          /* threads */
335   sigset_t  set;                    /* signals */
336
337   struct sched_param sch_param;     /* schedule parameters */
338   struct periodic_params params_a, params_b, params_c, params_c1;
339
340   puts( "\n\n*** POSIX Timers Test 01 ***" );
341
342   data.updated = FALSE;
343
344   /* mask signal */
345   sigemptyset (&set);
346   sigaddset (&set,SIGALRM);
347   pthread_sigmask (SIG_BLOCK,&set,NULL);
348
349   /* set mutex attributes */
350   if (pthread_mutexattr_init (&mutexattr) != 0) {
351     perror ("Error in mutex attribute init\n");
352   }
353
354   /* init mutex */
355   if (pthread_mutex_init (&data.mutex,&mutexattr) != 0) {
356     perror ("Error in mutex init");
357   }
358
359    /* init condition attributes */
360   if (pthread_condattr_init (&condattr) != 0) {
361     perror ("Error in condition attribute init\n");
362   }
363
364   /* init condition */
365   if (pthread_cond_init (&data.sync,&condattr) != 0) {
366     perror ("Error in condition init");
367   }
368
369   /* init task attributes */
370   if (pthread_attr_init(&attr) != 0) {
371     perror ("Error in attribute init\n");
372   }
373
374   /* set explicit schedule for every task */
375   if (pthread_attr_setinheritsched (&attr, PTHREAD_EXPLICIT_SCHED) != 0) {
376      perror("Error in attribute inheritsched\n");
377   }
378
379   /* set task independent (join will not use) */
380   if (pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED) != 0) {
381      perror ("Error in attribute detachstate\n");
382   }
383
384   /* schedule policy POSIX_FIFO (priority preemtive and FIFO within the same
385      priority) */
386   if (pthread_attr_setschedpolicy (&attr, SCHED_FIFO) != 0) {
387      perror ("Error in attribute setschedpolicy\n");
388    }
389
390   /* set and create thread A with priority 1 */
391
392   sch_param.sched_priority = 1;
393   if (pthread_attr_setschedparam(&attr, &sch_param) != 0) {
394      perror ("Error in attribute schedparam\n");
395    }
396
397   /* Temporal parameters (1 sec. periodicity) */
398
399   params_a.period.tv_sec  = 1;         /* seconds */
400   params_a.period.tv_nsec = 000000000; /* nanoseconds */
401   params_a.count          = 20;
402   params_a.signo = SIGALRM;
403   if (pthread_create (&ta, &attr, task_a, &params_a) != 0 ) {
404     perror ("Error in thread create for task a\n");
405   }
406
407   /* set and create thread B with priority 15 */
408
409   sch_param.sched_priority = 15;
410   if (pthread_attr_setschedparam(&attr, &sch_param) != 0) {
411      perror ("Error in attribute schedparam");
412    }
413
414   /* Temporal parameters (2 sec. periodicity) */
415   params_b.period.tv_sec  = 2;         /* seconds */
416   params_b.period.tv_nsec = 000000000; /* nanoseconds */
417   params_b.count          = 10;
418   params_b.signo = SIGALRM;
419   if (pthread_create (&tb, &attr, task_b, &params_b) != 0) {
420     perror ("Error in thread create for task b\n");
421   }
422
423   /* set and create thread B with priority 14 */
424
425   sch_param.sched_priority = 14;
426   if (pthread_attr_setschedparam(&attr, &sch_param) != 0 ) {
427      perror ("Error in attribute schedparam\n");
428    }
429
430   /* Temporal parameters (3 sec. periodicity) */
431   params_c.period.tv_sec  = 3;         /* seconds */
432   params_c.period.tv_nsec = 000000000; /* nanoseconds */
433   params_c.count          = 6;
434   params_c.signo = SIGALRM;
435   if (pthread_create (&tc, &attr, task_c, &params_c) != 0) {
436     perror ("Error in thread create for task c\n");
437   }
438
439   /* execute 25 seconds and finish */
440   sleep (25);
441
442   puts( "starting C again with 0.5 second periodicity" );
443   /* Temporal parameters (0.5 sec. periodicity) */
444   params_c1.period.tv_sec  = 0;         /* seconds */
445   params_c1.period.tv_nsec = 500000000; /* nanoseconds */
446   params_c1.count          = 6;
447   params_c1.signo = SIGALRM;
448   if (pthread_create (&tc1, &attr, task_c, &params_c1) != 0) {
449     perror ("Error in thread create for task c1\n");
450   }
451
452   sleep(5);
453
454   puts( "*** END OF POSIX Timers Test 01 ***" );
455   rtems_test_exit (0);
456 }
Note: See TracBrowser for help on using the repository browser.