source: rtems/c/src/exec/posix/src/ptimer.c @ 812f440

4.104.114.84.95
Last change on this file since 812f440 was 812f440, checked in by Joel Sherrill <joel.sherrill@…>, on 10/21/99 at 16:38:49

Fixed core dump caused when output parameter (otimer) was NULL.

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