source: rtems/c/src/exec/posix/src/ptimer1.c @ 939e29d

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

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

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