OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rtems/] [c/] [src/] [exec/] [posix/] [src/] [ptimer1.c] - Blame information for rev 158

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 158 chris
/*
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
 
49
struct 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
 
63
static 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
 
78
static 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
 
104
extern 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
 
122
int 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
 
146
int 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
 
173
void 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
 
191
void 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
 
231
rtems_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
 
308
int 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
 
440
int 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
 
496
int 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
 
753
int 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
 
860
int 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
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.