source: rtems/cpukit/posix/src/ptimer1.c @ 07e0743

4.104.114.84.95
Last change on this file since 07e0743 was 07e0743, checked in by Joel Sherrill <joel.sherrill@…>, on 11/02/99 at 19:11:16

Final tuning required to drop out POSIX timers.

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