source: rtems/cpukit/posix/src/ptimer.c @ 0747e2d

4.104.114.84.95
Last change on this file since 0747e2d was 0747e2d, checked in by Joel Sherrill <joel.sherrill@…>, on 02/03/99 at 16:22:18

POSIX Timers submitted by Juan Zamorano Flores
<jzamora@…>.

  • Property mode set to 100644
File size: 26.2 KB
Line 
1/*
2 *  ptimer.c,v 1.1 1996/06/03 16:29:58 joel Exp
3 */
4 
5#include <assert.h>
6#include <time.h>
7#include <errno.h>
8
9#include <rtems/system.h>
10#include <rtems/score/isr.h>
11#include <rtems/score/thread.h>
12#include <rtems/score/tod.h>
13
14#include <rtems/posix/time.h>
15
16/************************************/
17/* These includes are now necessary */
18/************************************/
19
20#include <sys/features.h>
21#include <rtems/rtems/status.h>
22#include <rtems/rtems/types.h>
23#include <rtems/rtems/timer.h>
24#include <rtems/rtems/clock.h>
25#include <rtems/posix/psignal.h>
26#include <rtems/score/wkspace.h>
27#include <pthread.h>
28#include <stdio.h>
29#include <signal.h>
30
31/*****************************/
32/* End of necessary includes */
33/*****************************/
34
35/* ************
36 * Constants
37 * ************/
38
39#define STATE_FREE_C        0x01 /* Free position of the table of timers   */
40#define STATE_CREATE_NEW_C  0x02 /* Created timer but not running          */
41#define STATE_CREATE_RUN_C  0x03 /* Created timer and running              */
42#define STATE_CREATE_STOP_C 0x04 /* Created, ran and stopped timer         */
43#define MAX_NSEC_C    1000000000 /* Maximum number of nsec allowed         */
44#define MIN_NSEC_C             0 /* Minimum number of nsec allowew         */
45#define TIMER_RELATIVE_C       0 /* Indicates that the fire time is       
46                                  * relative to the current one            */
47#define SEC_TO_TICKS_C _TOD_Ticks_per_second /* Number of ticks in a second*/
48#define NSEC_PER_SEC_C 1000000000 /* Nanoseconds in a second               */
49
50#define NO_MORE_TIMERS_C      11 /* There is not available timers          */
51#define BAD_TIMER_C           11 /* The timer does not exist in the table  */
52
53#define SECONDS_PER_YEAR_C    ( 360 * 24 * 60 * 60 )
54#define SECONDS_PER_MONTH_C    ( 30 * 24 * 60 * 60 )
55#define SECONDS_PER_DAY_C           ( 24 * 60 * 60 )
56#define SECONDS_PER_HOUR_C               ( 60 * 60 )
57#define SECONDS_PER_MINUTE_C                  ( 60 )
58
59/*
60#define DEBUG_MESSAGES
61 */
62
63/* *********************************************************
64 * Types that will store the created timers and their data
65 * *********************************************************/
66
67/*
68 * Data for a timer
69 */
70
71typedef struct {
72  pthread_t         thread_id;  /* Thread identifier                     */
73  char              state;      /* State of the timer                    */
74  struct sigevent   inf;        /* Information associated to the timer   */
75  timer_t           timer_id;   /* Created timer identifier              */
76  struct itimerspec timer_data; /* Timing data of the timer              */
77  unsigned32        ticks;      /* Number of ticks of the initialization */
78  unsigned32        overrun;    /* Number of expirations of the timer    */
79  rtems_time_of_day time;       /* Time in which the timer was started   */
80} timer_alive_t;
81
82/*
83 * Array of Timers
84 */
85
86int timer_max;
87timer_alive_t *timer_struct;
88
89/*
90 * Data for the signals
91 */
92
93struct sigaction signal_inf[SIGRTMAX];
94
95/***********************************
96 * Definition of Internal Functions
97 ***********************************/
98
99/* ***************************************************************************
100 * PRINT_MSG_S
101 *
102 *  Description: This function write a message in the display.
103 *               It is used for debugging and all the calls must be deleted
104 *               when the tests finish
105 * ***************************************************************************/
106
107static void PRINT_MSG_S ( char *msg )
108{
109
110#ifdef DEBUG_MESSAGES
111   printf("%s\n", msg);
112#endif
113
114}
115
116/* ***************************************************************************
117 * PRINT_ERRNO_S
118 *
119 *  Description: Print the value of the global variable errno in the display
120 * ***************************************************************************/
121
122static void PRINT_ERRNO_S ()
123{
124#ifdef DEBUG_MESSAGES
125  switch (errno)
126  {
127     case EINVAL:
128       PRINT_MSG_S ( "errno EINVAL"); break;
129     case EPERM:
130       PRINT_MSG_S ( "errno EPERM"); break;
131     case ESRCH:
132       PRINT_MSG_S ( "errno ESRCH"); break;
133     case EAGAIN:
134       PRINT_MSG_S ( "errno EAGAIN"); break;
135     default :
136       printf ("errno: %d\n", errno);
137       break;
138  }
139#endif
140}
141 
142/* ***************************************************************************
143 * TIMER_INITIALIZE_S
144 *
145 *  Description: Initialize the data of a timer
146 * ***************************************************************************/
147
148void TIMER_INITIALIZE_S ( int timer_pos )
149{
150
151   /*
152    * Indicates that the position in the table is free
153    */
154
155    timer_struct[timer_pos].state = STATE_FREE_C;
156
157   /*
158    * The initial data of timing are set with null value
159    */
160
161    timer_struct[timer_pos].timer_data.it_value.tv_sec     = 0;
162    timer_struct[timer_pos].timer_data.it_value.tv_nsec    = 0;
163    timer_struct[timer_pos].timer_data.it_interval.tv_sec  = 0;
164    timer_struct[timer_pos].timer_data.it_interval.tv_nsec = 0;
165
166   /*
167    * The count of expirations is 0
168    */
169
170    timer_struct[timer_pos].overrun = 0;
171
172}
173
174/* ***************************************************************************
175 * _POSIX_Timer_Manager_initialization
176 *
177 *  Description: Initialize the internal structure in which the data of all
178 *               the timers are stored
179 * ***************************************************************************/
180
181void _POSIX_Timer_Manager_initialization ( int max_timers )
182{
183   int index;
184
185   timer_struct = _Workspace_Allocate_or_fatal_error(
186      max_timers * sizeof(timer_alive_t) );
187
188   /*
189    *  Initialize all the timers
190    */
191
192   for (index=0; index<max_timers; index++)
193     TIMER_INITIALIZE_S( index );
194}
195
196/* ***************************************************************************
197 * FIRST_FREE_POSITION_F
198 *
199 *  Description: Returns the first free position in the table of timers.
200 *               If there is not a free position, it returns NO_MORE_TIMERS_C
201 * ***************************************************************************/
202
203int FIRST_FREE_POSITION_F ()
204{
205   int index;
206
207   for (index=0; index<timer_max; index++) {
208      if ( timer_struct[index].state == STATE_FREE_C ) {
209         return index;
210      }
211   }
212   
213   /* The function reaches this point only if all the position are occupied */
214
215   return NO_MORE_TIMERS_C;
216}
217
218/* ***************************************************************************
219 * TIMER_POSITION_F
220 *
221 *  Description: Returns the position in the table of timers in which the
222 *               data of the timer are stored.
223 *               If the timer identifier does not exist, it returns
224 *               BAD_TIMER_C
225 * ***************************************************************************/
226
227int TIMER_POSITION_F ( timer_t timer_id )
228{
229  int index;
230
231  for (index=0; index<timer_max; index++ ) {
232
233     /* Looks for the position of the timer. The timer must exist and the
234      * position can not be free */
235     if ( ( timer_struct[index].timer_id == timer_id ) &&
236          ( timer_struct[index].state != STATE_FREE_C ) ) {
237        return index;
238     }
239  }
240
241  /* If the function reaches this point is because the timer identifier
242   * is not correct */
243
244   return BAD_TIMER_C;
245
246}
247
248/* ***************************************************************************
249 * COPY_ITIMERSPEC_S
250 *
251 *  Description: Does a copy of a variable of type struct itimerspec 
252 * ***************************************************************************/
253
254void COPY_ITIMERSPEC_S ( const struct itimerspec *source,
255                         struct itimerspec *target )
256{
257
258   target->it_value.tv_sec     = source->it_value.tv_sec;
259   target->it_value.tv_nsec    = source->it_value.tv_nsec;
260   target->it_interval.tv_sec  = source->it_interval.tv_sec;
261   target->it_interval.tv_nsec = source->it_interval.tv_nsec;
262
263}
264
265/* ***************************************************************************
266 * ITIMERSPEC_TO_RTEMS_TIME_OF_DAY_S
267 *
268 *  Description: This function converts the data of a structure itimerspec
269 *               into structure rtems_time_of_day
270 * ***************************************************************************/
271
272void ITIMERSPEC_TO_RTEMS_TIME_OF_DAY_S
273   ( const struct itimerspec *itimer, rtems_time_of_day *rtems_time )
274{
275   unsigned long int seconds;
276
277   /* The leap years and the months with 28, 29 or 31 days have not been
278    * considerated. It will be made in the future */
279
280   seconds            = itimer->it_value.tv_sec;
281
282   rtems_time->year   = seconds / SECONDS_PER_YEAR_C;
283   seconds            = seconds % SECONDS_PER_YEAR_C;
284
285   rtems_time->month  = seconds / SECONDS_PER_MONTH_C;
286   seconds            = seconds % SECONDS_PER_MONTH_C;
287
288   rtems_time->day    = seconds / SECONDS_PER_DAY_C;
289   seconds            = seconds % SECONDS_PER_DAY_C;
290
291   rtems_time->hour   = seconds / SECONDS_PER_HOUR_C;
292   seconds            = seconds % SECONDS_PER_HOUR_C;
293
294   rtems_time->minute = seconds / SECONDS_PER_MINUTE_C;
295   seconds            = seconds % SECONDS_PER_MINUTE_C;
296
297   rtems_time->second = seconds;
298
299   rtems_time->ticks  = ( itimer->it_value.tv_nsec * SEC_TO_TICKS_C ) /
300                        NSEC_PER_SEC_C;
301
302}
303
304
305/* ***************************************************************************
306 * FIRE_TIMER_S
307 *
308 *  Description: This is the operation that is ran when a timer expires
309 * ***************************************************************************/
310
311
312rtems_timer_service_routine FIRE_TIMER_S (rtems_id timer, void *data)
313{
314  int               timer_pos;  /* Position in the table of the timer that   
315                                 *  has expirated                            */
316  rtems_status_code return_v;   /* Return value of rtems_timer_fire_after    */
317  int               sig_number; /* Number of the signal to send              */
318
319 
320  /* The position of the table of timers that contains the data of the
321   * expired timer will be stored in "timer_pos". In theory a timer can not
322   * expire if it has not been created or has been deleted */
323
324  PRINT_MSG_S ("FIRE_TIMER_S");
325
326  timer_pos = TIMER_POSITION_F(timer);
327
328  /* Increases the number of expiration of the timer in one unit. */
329  timer_struct[timer_pos].overrun = timer_struct[timer_pos].overrun + 1;
330
331
332  if ( ( timer_struct[timer_pos].timer_data.it_interval.tv_sec  != 0 ) ||
333       ( timer_struct[timer_pos].timer_data.it_interval.tv_nsec != 0 ) ) {
334
335     /* The timer must be reprogrammed */
336
337     return_v = rtems_timer_fire_after ( timer,
338                                        timer_struct[timer_pos].ticks,
339                                        FIRE_TIMER_S,
340                                        NULL );
341
342     /* Stores the time when the timer was started again */
343
344     return_v = rtems_clock_get ( RTEMS_CLOCK_GET_TOD,
345                                 &timer_struct[timer_pos].time );
346     
347     /* The state has not to be actualized, because nothing modifies it */
348
349     timer_struct[timer_pos].state = STATE_CREATE_RUN_C;
350
351  } else {
352     /* Indicates that the timer is stopped */
353 
354     timer_struct[timer_pos].state = STATE_CREATE_STOP_C;
355
356  }
357
358  /*
359   * The sending of the signal to the process running the handling function
360   * specified for that signal is simulated
361   */
362
363  sig_number = timer_struct[timer_pos].inf.sigev_signo;
364
365  if( pthread_kill ( timer_struct[timer_pos].thread_id ,
366                     timer_struct[timer_pos].inf.sigev_signo ) ) {
367     PRINT_MSG_S ("ERROR_PTHREAD_KILL");
368  } else {
369     PRINT_MSG_S ("SUCCESS_PTHREAD_KILL");
370  }
371
372  /*
373   * After the signal handler returns, the count of expirations of the
374   * timer must be set to 0.
375   */
376
377  timer_struct[timer_pos].overrun = 0;
378
379}
380
381/* *********************************************************************
382 *  14.2.2 Create a Per-Process Timer, P1003.1b-1993, p. 264
383 * ********************************************************************/
384
385/* **************
386 * timer_create
387 * **************/
388
389int timer_create(
390  clockid_t        clock_id,
391  struct sigevent *evp,
392  timer_t         *timerid
393)
394{
395
396  rtems_status_code return_v;  /* return value of the operation    */
397  rtems_id          timer_id;  /* created timer identifier         */
398  int               timer_pos; /* Position in the table of timers  */
399
400 /*
401  * The data of the structure evp are checked in order to verify if they
402  * are coherent.
403  */
404
405  if (evp != NULL) {
406     /* The structure has data */
407
408     if ( ( evp->sigev_notify != SIGEV_NONE ) &&
409          ( evp->sigev_notify != SIGEV_SIGNAL ) ) {
410       /* The value of the field sigev_notify is not valid */
411
412       return (-1);
413
414     }
415  }
416 
417 /*
418  * A timer is created using the primitive rtems_timer_create
419  */
420
421  return_v = rtems_timer_create ( clock_id, &timer_id );
422
423  switch (return_v) {
424     case RTEMS_SUCCESSFUL :
425
426       PRINT_MSG_S("SUCCESS: rtems create timer RTEMS_SUCCESSFUL");
427     
428       /*
429        * The timer has been created properly
430        */
431 
432        /* Obtains the first free position in the table of timers */
433
434        timer_pos = FIRST_FREE_POSITION_F();
435
436        if ( timer_pos == NO_MORE_TIMERS_C ) {
437           /* There is not position for another timers in spite of RTEMS
438            * supports it. It will necessaty to increase the structure used */
439
440           errno = EAGAIN;
441
442           return -1;
443        }
444
445        /* Exit parameter */
446
447        *timerid  = timer_id;
448
449        /* The data of the created timer are stored to use them later */
450
451        timer_struct[timer_pos].state     = STATE_CREATE_NEW_C;
452
453        /* NEW VERSION*/
454        timer_struct[timer_pos].thread_id = pthread_self ();
455       
456
457        if ( evp != NULL ) {
458
459           timer_struct[timer_pos].inf.sigev_notify = evp->sigev_notify;
460           timer_struct[timer_pos].inf.sigev_signo  = evp->sigev_signo;
461           timer_struct[timer_pos].inf.sigev_value  = evp->sigev_value;
462
463        }
464
465
466        timer_struct[timer_pos].timer_id = timer_id;
467
468        timer_struct[timer_pos].overrun  = 0;
469
470        timer_struct[timer_pos].timer_data.it_value.tv_sec     = 0;
471        timer_struct[timer_pos].timer_data.it_value.tv_nsec    = 0;
472        timer_struct[timer_pos].timer_data.it_interval.tv_sec  = 0;
473        timer_struct[timer_pos].timer_data.it_interval.tv_nsec = 0;
474
475        return 0;
476   
477
478     case RTEMS_INVALID_NAME : /* The assigned name is not valid*/
479
480       PRINT_MSG_S ("ERROR: rtems create timer RTEMS_INVALID_NAME");
481
482       errno = EINVAL;
483
484       return (-1);
485
486
487     case RTEMS_TOO_MANY :
488
489       PRINT_MSG_S ("ERROR: rtems create timer RTEMS_TOO_MANY ");
490 
491       /* There has been created too much timers for the same process */
492
493       errno = EAGAIN;
494
495       return (-1);
496     
497     default :
498
499       /*
500        * Does nothing. It only returns the error without assigning a value
501        * to errno. In theory, it can not happen because the call to
502        * rtems_timer_create can not return other different value.
503        */
504
505       return (-1);
506
507  }
508
509  /*
510   * The next sentence is used to avoid singular situations
511   */
512
513  return (-1);
514
515}
516
517/*
518 *  14.2.3 Delete a Per_process Timer, P1003.1b-1993, p. 266
519 */
520
521int timer_delete(
522  timer_t timerid
523)
524{
525 
526 /*
527  * IDEA: This function must probably stop the timer first and then delete it
528  *
529  *       It will have to do a call to rtems_timer_cancel and then another
530  *       call to rtems_timer_delete.
531  *       The call to rtems_timer_delete will be probably unnecessary,
532  *       because rtems_timer_delete stops the timer before deleting it.
533  */
534
535  int               timer_pos;
536  rtems_status_code status;
537
538
539   /* First the position in the table of timers is obtained */
540
541   timer_pos = TIMER_POSITION_F ( timerid );
542
543   if ( timer_pos == BAD_TIMER_C ) {
544      /* The timer identifier is erroneus */
545
546      errno = EINVAL;
547      return -1;
548   }
549
550   /* The timer is deleted */
551
552   status = rtems_timer_delete ( timerid );
553
554   if ( status == RTEMS_INVALID_ID ) {
555      /* The timer identifier is erroneus */
556
557      errno = EINVAL;
558      return -1;
559   }
560
561   /* Initializes the data of the timer */
562
563   TIMER_INITIALIZE_S ( timer_pos );
564
565   return 0;
566}
567
568/*
569 *  14.2.4 Per-Process Timers, P1003.1b-1993, p. 267
570 */
571
572/* **************
573 * timer_settime
574 * **************/
575
576
577int timer_settime(
578  timer_t                  timerid,
579  int                      flags,
580  const struct itimerspec *value,
581  struct itimerspec       *ovalue
582)
583{
584
585   rtems_status_code return_v;   /* Return of the calls to RTEMS        */
586   int               timer_pos;  /* Position of the timer in the table  */
587   rtems_time_of_day rtems_time; /* Time in RTEMS                       */
588
589   /* First the position in the table of timers is obtained */
590
591   timer_pos = TIMER_POSITION_F ( timerid );
592
593   if ( timer_pos == BAD_TIMER_C ) {
594      /* The timer identifier is erroneus */
595
596      errno = EINVAL;
597      return -1;
598   }
599
600   if ( value == NULL ) {
601     /* The stucture of times of the timer is free, and then returns an
602        error but the variable errno is not actualized */
603
604     /* errno = ?????? */
605
606     return -1;
607   }
608
609   /* If the function reaches this point, then it will be necessary to do
610    * something with the structure of times of the timer: to stop, start
611    * or start it again */
612
613   /* First, it verifies if the timer must be stopped */
614
615   if ( value->it_value.tv_sec == 0 && value->it_value.tv_nsec == 0 ) {
616      /* The timer is stopped */
617
618      return_v = rtems_timer_cancel ( timerid );
619
620      /* The old data of the timer are returned */
621
622      COPY_ITIMERSPEC_S ( &timer_struct[timer_pos].timer_data, ovalue );
623
624      /* The new data are set */
625
626      COPY_ITIMERSPEC_S ( value, &timer_struct[timer_pos].timer_data );
627
628      /* Indicates that the timer is created and stopped */
629 
630      timer_struct[timer_pos].state = STATE_CREATE_STOP_C;
631
632      /* Returns with success */
633
634      return 0;
635   }
636
637   /*
638    * If the function reaches this point, then the timer will have to be
639    * initialized with new values: to start it or start it again
640    */
641 
642   /* First, it verifies if the structure "value" is correct */
643
644    if ( ( value->it_value.tv_nsec > MAX_NSEC_C ) ||
645         ( value->it_value.tv_nsec < MIN_NSEC_C ) ) {
646       /* The number of nanoseconds is not correct */
647
648       errno = EINVAL;
649
650       return -1;
651    }
652
653   /* Then, "value" must be converted from seconds and nanoseconds to clock
654    * ticks, to use it in the calls to RTEMS */
655
656   /* It is also necessary to take in account if the time is absolute
657    * or relative */
658
659   switch (flags) {
660      case TIMER_ABSTIME:
661
662        /* The fire time is absolute:
663         * It has to use "rtems_time_fire_when" */
664
665        /* First, it converts from struct itimerspec to rtems_time_of_day */
666
667        ITIMERSPEC_TO_RTEMS_TIME_OF_DAY_S ( value, &rtems_time );
668
669        return_v = rtems_timer_fire_when ( timerid, &rtems_time, FIRE_TIMER_S, NULL);
670
671        switch ( return_v ) {
672           case RTEMS_SUCCESSFUL:
673
674              PRINT_MSG_S ("SUCCESS: timer_settime RTEMS_SUCCESSFUL");
675
676              /* The timer has been started and is running */
677
678              /* Actualizes the data of the structure and
679               * returns the old ones in "ovalue" */
680
681              COPY_ITIMERSPEC_S ( &timer_struct[timer_pos].timer_data, ovalue );
682
683              COPY_ITIMERSPEC_S ( value, &timer_struct[timer_pos].timer_data );
684 
685              /* It indicates that the time is running */
686
687              timer_struct[timer_pos].state = STATE_CREATE_RUN_C;
688
689              /* Stores the time in which the timer was started again */
690
691              return_v = rtems_clock_get ( RTEMS_CLOCK_GET_TOD,
692                                          &timer_struct[timer_pos].time );
693
694              return 0;
695
696              break;
697
698           case RTEMS_INVALID_ID:
699
700              PRINT_MSG_S ("ERROR: timer_settime RTEMS_INVALID_ID");
701              break;
702
703           case RTEMS_NOT_DEFINED:
704
705              PRINT_MSG_S ("ERROR: timer_settime RTEMS_NOT_DEFINED");
706              break;
707
708           case RTEMS_INVALID_CLOCK:
709
710              PRINT_MSG_S ("ERROR: timer_settime RTEMS_INVALID_CLOCK");
711              break;
712
713           default:
714
715       
716        }
717     
718        break;
719
720      case TIMER_RELATIVE_C:
721
722        /* The fire time is relative:
723         * It has to use "rtems_time_fire_after" */
724
725        /* First, it converts from seconds and nanoseconds to ticks */
726
727        /* The form in which this operation is done can produce a lost
728         * of precision of 1 second */
729 
730/*      This is the process to convert from nanoseconds to ticks
731 *
732 *      There is a tick every 10 miliseconds, then the nanoseconds are
733 *      divided between 10**7. The result of this operation will be the
734 *      number of ticks
735 */
736
737        timer_struct[timer_pos].ticks =
738             ( SEC_TO_TICKS_C * value->it_value.tv_sec ) +
739             ( value->it_value.tv_nsec / ( 1000 * 1000 * 10 ) );
740
741        return_v = rtems_timer_fire_after ( timerid,
742                                           timer_struct[timer_pos].ticks,
743                                           FIRE_TIMER_S,
744                                           NULL );
745
746        switch (return_v) {
747           case RTEMS_SUCCESSFUL:
748
749              PRINT_MSG_S ( "SUCCESS: timer_settime RTEMS_SUCCESSFUL");
750             
751              /* The timer has been started and is running */
752
753              /* Actualizes the data of the structure and
754               * returns the old ones in "ovalue" */
755
756              COPY_ITIMERSPEC_S ( &timer_struct[timer_pos].timer_data, ovalue );
757
758              COPY_ITIMERSPEC_S ( value, &timer_struct[timer_pos].timer_data );
759 
760              /* It indicates that the time is running */
761
762              timer_struct[timer_pos].state = STATE_CREATE_RUN_C;
763
764              /* Stores the time in which the timer was started again */
765
766              return_v = rtems_clock_get ( RTEMS_CLOCK_GET_TOD,
767                                          &timer_struct[timer_pos].time );
768 
769              return 0;
770
771              break;
772
773           case RTEMS_INVALID_ID:
774
775              PRINT_MSG_S ( "ERROR: timer_settime RTEMS_INVALID_ID");
776
777              /* The timer identifier is not correct. In theory, this
778               * situation can not occur, but the solution is easy */
779
780              errno = EINVAL;
781
782              return -1;
783
784              break;
785
786           case RTEMS_INVALID_NUMBER:
787
788              PRINT_MSG_S ( "ERROR: timer_settime RTEMS_INVALID_NUMBER");
789
790              /* In this case, RTEMS fails because the values of timing
791               * are incorrect */
792
793              /*
794               * I do not know if errno must be actualized
795               *
796               * errno = EINVAL;
797               */
798
799              return -1;
800
801              break;
802           
803           default:
804        }
805
806        break;
807
808      default:
809
810        /* It does nothing, although it will be probably necessary to
811         * return an error */
812
813   }
814
815   /* To avoid problems */
816
817   return 0;
818
819}
820
821
822/*
823 *  14.2.4 Per-Process Timers, P1003.1b-1993, p. 267
824 */
825
826/* **************
827 * timer_gettime
828 * **************/
829
830int timer_gettime(
831  timer_t            timerid,
832  struct itimerspec *value
833)
834{
835
836 /*
837  * IDEA:  This function does not use functions of RTEMS to the handle
838  *        of timers. It uses some functions for managing the time.
839  *
840  *        A possible form to do this is the following:
841  *
842  *          - When a timer is initialized, the value of the time in
843  *            that moment is stored.
844  *          - When this function is called, it returns the difference
845  *            between the current time and the initialization time.
846  */
847 
848  rtems_time_of_day current_time;
849  rtems_status_code return_v;
850  int               timer_pos;
851  unsigned32        hours;
852  unsigned32        minutes;
853  unsigned32        seconds;
854  unsigned32        ticks;
855  unsigned32        nanosec;
856 
857
858  /* Reads the current time */
859
860  return_v = rtems_clock_get ( RTEMS_CLOCK_GET_TOD, &current_time );
861
862  timer_pos = TIMER_POSITION_F ( timerid );
863
864  if ( timer_pos == BAD_TIMER_C ) {
865
866     /* The timer identifier is erroneus */ 
867
868     errno = EINVAL;
869
870     return (-1);
871
872  }
873
874  /* Calculates the difference between the start time of the timer and
875   * the current one */
876
877  hours    = current_time.hour - timer_struct[timer_pos].time.hour;
878
879  if ( current_time.minute < timer_struct[timer_pos].time.minute ) {
880     minutes = 60 - timer_struct[timer_pos].time.minute + current_time.minute;
881     hours--;
882  } else {
883     minutes = current_time.minute - timer_struct[timer_pos].time.minute;
884  }
885   
886  if ( current_time.second < timer_struct[timer_pos].time.second ) {
887     seconds = 60 - timer_struct[timer_pos].time.second + current_time.second;
888     minutes--;
889  } else {
890     seconds = current_time.second - timer_struct[timer_pos].time.second;
891  }
892
893  if ( current_time.ticks < timer_struct[timer_pos].time.ticks ) {
894     ticks = 100 - timer_struct[timer_pos].time.ticks + current_time.ticks;
895     seconds--;
896  } else {
897     ticks = current_time.ticks - timer_struct[timer_pos].time.ticks;
898  }
899
900  /* The time that the timer is running is calculated */
901  seconds = hours   * 60 * 60 +
902            minutes * 60      +
903            seconds;
904
905  nanosec  = ticks * 10 *  /* msec     */
906             1000  *       /* microsec */
907             1000;         /* nanosec  */
908
909 
910  /* Calculates the time left before the timer finishes */
911 
912  value->it_value.tv_sec =
913    timer_struct[timer_pos].timer_data.it_value.tv_sec - seconds;
914 
915  value->it_value.tv_nsec =
916    timer_struct[timer_pos].timer_data.it_value.tv_nsec - nanosec;
917
918
919  value->it_interval.tv_sec  =
920    timer_struct[timer_pos].timer_data.it_interval.tv_sec;
921  value->it_interval.tv_nsec =
922    timer_struct[timer_pos].timer_data.it_interval.tv_nsec;
923 
924
925  return 0;
926
927}
928
929/*
930 *  14.2.4 Per-Process Timers, P1003.1b-1993, p. 267
931 */
932
933/* *****************
934 * timer_getoverrun
935 * *****************/
936
937int timer_getoverrun(
938  timer_t   timerid
939)
940{
941
942 /*
943  * IDEA: This function must count the times the timer expires.
944  *   
945  *       The expiration of a timer must increase by one a counter.
946  *       After the signal handler associated to the timer finishs
947  *       its execution, FIRE_TIMER_S will have to set this counter to 0.
948  */
949
950  int timer_pos; /* Position of the timer in the structure     */
951  int overrun;   /* Overflow count                             */
952
953
954  timer_pos = TIMER_POSITION_F ( timerid );
955
956  if ( timer_pos == BAD_TIMER_C ) {
957     /* The timer identifier is erroneus */
958
959     errno = EINVAL;
960
961     return -1;
962  }
963
964  /* The overflow count of the timer is stored in "overrun" */
965
966  overrun = timer_struct[timer_pos].overrun;
967
968  /* It is set to 0 */
969
970  timer_struct[timer_pos].overrun = 0;
971
972  return overrun;
973
974}
Note: See TracBrowser for help on using the repository browser.