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

4.115
Last change on this file since c499856 was c499856, checked in by Chris Johns <chrisj@…>, on 03/20/14 at 21:10:47

Change all references of rtems.com to rtems.org.

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