source: rtems/cpukit/posix/src/ptimer1.c @ ea56c0a8

4.104.114.84.95
Last change on this file since ea56c0a8 was ea56c0a8, checked in by Joel Sherrill <joel.sherrill@…>, on 08/15/00 at 13:10:29

2000-08-15 Joel Sherrill <joel@…>

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