source: rtems/testsuites/psxtests/psxtimer01/psxtimer.c @ 698c2e50

4.115
Last change on this file since 698c2e50 was 698c2e50, checked in by Sebastian Huber <sebastian.huber@…>, on 03/25/14 at 07:06:16

tests/psxtests: Use <rtems/test.h>

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