source: rtems/testsuites/psxtests/psxtimer01/psxtimer.c @ d2a3b42e

4.104.115
Last change on this file since d2a3b42e was d2a3b42e, checked in by Ralf Corsepius <ralf.corsepius@…>, on 10/26/09 at 09:10:20

Use PRItime_t to print time_t's.

  • Property mode set to 100644
File size: 12.4 KB
RevLine 
[657be8f5]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 *
[2e7e636f]15 *  COPYRIGHT (c) 1989-2009.
[bdd1f5d]16 *  On-Line Applications Research Corporation (OAR).
17 *
[657be8f5]18 *  The license and distribution terms for this file may be
19 *  found in the file LICENSE in this distribution or at
[3c48599]20 *  http://www.rtems.com/license/LICENSE.
[657be8f5]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 */
[0e4232b]33#include <rtems/score/timespec.h>
[657be8f5]34
[2e7e636f]35void StopTimer(
36  timer_t  timer_id,
37  struct   itimerspec *timerdata
38);
[657be8f5]39
40/* temporal parameters of a task */
41
42struct periodic_params {
43   struct timespec period;
[0e4232b]44   int count;       /* Number of iterations to run */
[657be8f5]45   int signo;       /* signal number */
46   int id;          /* task identification */
[1b4f2b30]47 };
[657be8f5]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
[0e4232b]61void StopTimer(
62  timer_t  timer_id,
63  struct   itimerspec *timerdata
64)
65{
[157354e9]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;
[f46fddfc]79  if (timer_settime(timer_id,POSIX_TIMER_RELATIVE,timerdata,pOld) == -1) {
[157354e9]80    perror ("Error in timer setting\n");
81    rtems_test_exit(0);
82  }
[0e4232b]83}
84 
[657be8f5]85/* task A  */
86void * task_a (void *arg)
87{
88   struct   timespec my_period;
89   int      my_sig, received_sig;
90   struct   itimerspec timerdata;
[0e4232b]91   struct   itimerspec timergetdata;
[657be8f5]92   timer_t  timer_id;
93   time_t   clock;
94   struct   sigevent event;
95   sigset_t set;
[0e4232b]96   struct periodic_params *params;
[657be8f5]97
[0e4232b]98   params = arg;
99   my_period = params->period;
100   my_sig    = params->signo;
[657be8f5]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");
[157354e9]107      rtems_test_exit(0);
[657be8f5]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;
[f132a3d8]118   timerdata.it_value.tv_sec *= 2;
[0e4232b]119   if (timer_settime(timer_id,POSIX_TIMER_RELATIVE,&timerdata,&timergetdata) == -1) {
[657be8f5]120     perror ("Error in timer setting\n");
[157354e9]121     rtems_test_exit(0);
[657be8f5]122   }
[0e4232b]123   printf(
[d2a3b42e]124    "task A: timer_settime - value=%" PRItime_t ":%d interval=%" PRItime_t ":%d\n",
[0e4232b]125    timergetdata.it_value.tv_sec, timergetdata.it_value.tv_nsec,
126    timergetdata.it_interval.tv_sec, timergetdata.it_interval.tv_nsec
127  );
128   
[657be8f5]129
130   /* periodic activity */
131   while(1) {
132     if (sigwait(&set,&received_sig) == -1) {
133       perror ("Error in sigwait\n");
134     }
[0e4232b]135     if (timer_gettime(timer_id, &timerdata) == -1) {
136       perror ("Error in timer_gettime\n");
[157354e9]137       rtems_test_exit(0);
[0e4232b]138     }
139     if (! _Timespec_Equal_to( &timerdata.it_value, &my_period )){
140       perror ("Error in Task A timer_gettime\n");
141     }
[657be8f5]142     clock = time(NULL);
[0e4232b]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);
[657be8f5]147   }
[7b64b25b]148   return NULL;
149}
[657be8f5]150
151/* task B  */
152
153void * task_b (void *arg)
154{
155   struct   timespec my_period;
[bdd1f5d]156   struct   timespec now;
[657be8f5]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;
[0e4232b]163   struct periodic_params *params;
[657be8f5]164
[0e4232b]165   params = arg;
166   my_period = params->period;
167   my_sig    = params->signo;
[657be8f5]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");
[157354e9]175      rtems_test_exit(0);
[657be8f5]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 */
[bdd1f5d]184   clock_gettime( CLOCK_REALTIME, &now );
[657be8f5]185   timerdata.it_interval = my_period;
[bdd1f5d]186   timerdata.it_value = now;
187   _Timespec_Add_to( &timerdata.it_value, &my_period );
[0e4232b]188   if (timer_settime(timer_id,TIMER_ABSTIME,&timerdata,NULL) == -1) {
[657be8f5]189     perror ("Error in timer setting\n");
[157354e9]190     rtems_test_exit(0);
[0e4232b]191   }     
[657be8f5]192
193   /* periodic activity */
194   while(1) {
195     if (sigwait(&set,&received_sig) == -1) {
196       perror ("Error in sigwait\n");
[157354e9]197       rtems_test_exit(0);
[657be8f5]198     }
[0e4232b]199 
200     if (timer_gettime(timer_id, &timerdata) == -1) {
201       perror ("Error in timer_gettime\n");
[157354e9]202       rtems_test_exit(0);
[0e4232b]203     }
[c54e6f5]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      */
[157354e9]210     if ( !_Timespec_Equal_to( &timerdata.it_value, &my_period) ){
[c54e6f5]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       );
[157354e9]217       rtems_test_exit(0);
[0e4232b]218     }
[c54e6f5]219#endif
[0e4232b]220
[657be8f5]221     pthread_mutex_lock (&data.mutex);
222     clock = time(NULL);
[f132a3d8]223     printf("Executing task B with count = %2i %s",
[0e4232b]224       params->count, ctime(&clock)
225     );
[657be8f5]226     data.updated = TRUE;
227     pthread_cond_signal  (&data.sync);
228     pthread_mutex_unlock (&data.mutex);
[0e4232b]229     params->count--;
230     if (params->count == 0)
231       StopTimer(timer_id, &timerdata);
[657be8f5]232   }
[7b64b25b]233   return NULL;
[657be8f5]234}
235
236/* task C */
237
238void * task_c (void *arg)
239{
[0e4232b]240   int      count;
[657be8f5]241   struct   timespec my_period;
242   int      my_sig, received_sig;
243   struct   itimerspec timerdata;
[0e4232b]244   struct   itimerspec timergetdata;
[657be8f5]245   timer_t  timer_id;
246   time_t   clock;
247   struct   sigevent event;
248   sigset_t set;
[0e4232b]249   struct   periodic_params *params;
[657be8f5]250
[0e4232b]251   params = arg;
252   my_period = params->period;
253   my_sig    = params->signo;
[657be8f5]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");
[157354e9]260      rtems_test_exit(0);
[657be8f5]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;
[f132a3d8]271   timerdata.it_value.tv_sec *= 2;
[0e4232b]272   if (timer_settime(timer_id,POSIX_TIMER_RELATIVE,&timerdata,NULL) == -1) {
[657be8f5]273     perror ("Error in timer setting\n");
[157354e9]274     rtems_test_exit(0);
[657be8f5]275   }
276
277   /* periodic activity */
[0e4232b]278   for (count=0 ; ; count++) {
[657be8f5]279      if (sigwait(&set,&received_sig) == -1) {
280       perror ("Error in sigwait\n");
[157354e9]281       rtems_test_exit(0);
[1b4f2b30]282     }
[0e4232b]283     if (timer_gettime(timer_id, &timerdata) == -1) {
284       perror ("Error in timer_gettime\n");
[157354e9]285       rtems_test_exit(0);
[0e4232b]286     }
287     if (! _Timespec_Equal_to( &timerdata.it_value, &my_period) ){
288       perror ("Error in Task C timer_gettime\n");
289     }
[657be8f5]290     pthread_mutex_lock (&data.mutex);
291     while (data.updated == FALSE) {
292       pthread_cond_wait (&data.sync,&data.mutex);
293     }
294     clock = time(NULL);
[f132a3d8]295     printf("Executing task C with count = %2i %s",
[0e4232b]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");
[157354e9]307         rtems_test_exit(0);
[0e4232b]308       }
309       printf(
[d2a3b42e]310         "task C: timer_gettime - %" PRItime_t ":%d remaining from %" PRItime_t ":%d\n",
[0e4232b]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
[657be8f5]316     pthread_mutex_unlock (&data.mutex);
[0e4232b]317     params->count--;
318     if (params->count == 0)
319       StopTimer(timer_id, &timerdata);
[657be8f5]320   }
[7b64b25b]321   return NULL;
322}
[657be8f5]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 */
[7a67dfbc]334   pthread_t ta,tb,tc, tc1;          /* threads */
[657be8f5]335   sigset_t  set;                    /* signals */
[1b4f2b30]336
[657be8f5]337   struct sched_param sch_param;     /* schedule parameters */
[7a67dfbc]338   struct periodic_params params_a, params_b, params_c, params_c1;
[1b4f2b30]339
[eed0b96d]340   puts( "\n\n*** POSIX Timers Test 01 ***" );
[657be8f5]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 */
[0e4232b]375   if (pthread_attr_setinheritsched (&attr, PTHREAD_EXPLICIT_SCHED) != 0) {
[657be8f5]376      perror("Error in attribute inheritsched\n");
377   }
378
379   /* set task independent (join will not use) */
[0e4232b]380   if (pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED) != 0) {
[657be8f5]381      perror ("Error in attribute detachstate\n");
382   }
383
384   /* schedule policy POSIX_FIFO (priority preemtive and FIFO within the same
385      priority) */
[0e4232b]386   if (pthread_attr_setschedpolicy (&attr, SCHED_FIFO) != 0) {
[1b4f2b30]387      perror ("Error in attribute setschedpolicy\n");
[657be8f5]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    }
[1b4f2b30]396
[657be8f5]397   /* Temporal parameters (1 sec. periodicity) */
398
399   params_a.period.tv_sec  = 1;         /* seconds */
400   params_a.period.tv_nsec = 000000000; /* nanoseconds */
[0e4232b]401   params_a.count          = 20;
[657be8f5]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 */
[1b4f2b30]408
[657be8f5]409   sch_param.sched_priority = 15;
410   if (pthread_attr_setschedparam(&attr, &sch_param) != 0) {
411      perror ("Error in attribute schedparam");
412    }
[1b4f2b30]413
[657be8f5]414   /* Temporal parameters (2 sec. periodicity) */
415   params_b.period.tv_sec  = 2;         /* seconds */
416   params_b.period.tv_nsec = 000000000; /* nanoseconds */
[0e4232b]417   params_b.count          = 10;
[657be8f5]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 */
[0e4232b]433   params_c.count          = 6;
[657be8f5]434   params_c.signo = SIGALRM;
435   if (pthread_create (&tc, &attr, task_c, &params_c) != 0) {
[3c0c898]436     perror ("Error in thread create for task c\n");
[657be8f5]437   }
438
[0e4232b]439   /* execute 25 seconds and finish */
440   sleep (25);
[7a67dfbc]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
[eed0b96d]454   puts( "*** END OF POSIX Timers Test 01 ***" );
[d802489]455   rtems_test_exit (0);
[657be8f5]456 }
Note: See TracBrowser for help on using the repository browser.