source: rtems/testsuites/psxtests/psxtimer01/psxtimer.c @ 4562dd8

4.115
Last change on this file since 4562dd8 was 4562dd8, checked in by Ralf Corsepius <ralf.corsepius@…>, on 09/30/11 at 02:53:32

2011-09-30 Ralf Corsépius <ralf.corsepius@…>

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