Changeset 68003979 in rtems
- Timestamp:
- 11/02/99 19:04:51 (24 years ago)
- Branches:
- 4.10, 4.11, 4.8, 4.9, 5, master
- Children:
- 07e0743
- Parents:
- db7f70a
- Files:
-
- 4 added
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
c/src/exec/posix/src/Makefile.in
rdb7f70a r68003979 74 74 clockgetres clockgettime clocksetenableattr clocksettime nanosleep 75 75 76 # the timer manager needs to be split further but only after its 77 # dependence on the Classic API Timer Manager is removed. 78 TIMER_C_PIECES=ptimer ptimer1 79 76 80 C_PIECES = adasupp $(CANCEL_C_PIECES) $(CONDITION_VARIABLE_C_PIECES) \ 77 81 getpid $(KEY_C_PIECES) $(MESSAGE_QUEUE_C_PIECES) \ 78 82 $(MUTEX_C_PIECES) $(PTHREAD_C_PIECES) \ 79 $(PSIGNAL_C_PIECES) ptimersched $(SEMAPHORE_C_PIECES) \80 $(TIME_C_PIECES) types unistd $(ENOSYS_C_PIECES) \83 $(PSIGNAL_C_PIECES) sched $(SEMAPHORE_C_PIECES) \ 84 $(TIME_C_PIECES) $(TIMER_C_PIECES) types unistd $(ENOSYS_C_PIECES) \ 81 85 $(BUILD_FOR_NOW_C_PIECES) 82 86 -
c/src/exec/posix/src/ptimer.c
rdb7f70a r68003979 33 33 /*****************************/ 34 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 71 typedef 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 86 int timer_max; 87 timer_alive_t *timer_struct; 88 89 /* 90 * Data for the signals 91 */ 92 93 struct 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 107 static 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 122 static 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 148 void 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 } 35 #include <rtems/posix/timer.h> 173 36 174 37 /* *************************************************************************** … … 178 41 * the timers are stored 179 42 * ***************************************************************************/ 43 44 extern void TIMER_INITIALIZE_S( int ); 45 int timer_max; 46 timer_alive_t *timer_struct; 47 180 48 181 49 void _POSIX_Timer_Manager_initialization ( int max_timers ) … … 198 66 } 199 67 200 /* ***************************************************************************201 * FIRST_FREE_POSITION_F202 *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_C205 * ***************************************************************************/206 207 int 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_F224 *225 * Description: Returns the position in the table of timers in which the226 * data of the timer are stored.227 * If the timer identifier does not exist, it returns228 * BAD_TIMER_C229 * ***************************************************************************/230 231 int 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 the238 * 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 identifier246 * is not correct */247 248 return BAD_TIMER_C;249 250 }251 252 /* ***************************************************************************253 * COPY_ITIMERSPEC_S254 *255 * Description: Does a copy of a variable of type struct itimerspec256 * ***************************************************************************/257 258 void 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_S271 *272 * Description: This function converts the data of a structure itimerspec273 * into structure rtems_time_of_day274 * ***************************************************************************/275 276 void ITIMERSPEC_TO_RTEMS_TIME_OF_DAY_S277 ( 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 been282 * 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_S311 *312 * Description: This is the operation that is ran when a timer expires313 * ***************************************************************************/314 315 316 rtems_timer_service_routine FIRE_TIMER_S (rtems_id timer, void *data)317 {318 int timer_pos; /* Position in the table of the timer that319 * 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 the325 * expired timer will be stored in "timer_pos". In theory a timer can not326 * 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 function364 * specified for that signal is simulated365 */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 the378 * 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. 264387 * ********************************************************************/388 389 /* **************390 * timer_create391 * **************/392 393 int timer_create(394 clockid_t clock_id,395 struct sigevent *evp,396 timer_t *timerid397 )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 they406 * 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_create423 */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 properly434 */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 RTEMS442 * 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 value505 * to errno. In theory, it can not happen because the call to506 * 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 situations515 */516 517 return (-1);518 519 }520 521 /*522 * 14.2.3 Delete a Per_process Timer, P1003.1b-1993, p. 266523 */524 525 int timer_delete(526 timer_t timerid527 )528 {529 530 /*531 * IDEA: This function must probably stop the timer first and then delete it532 *533 * It will have to do a call to rtems_timer_cancel and then another534 * 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. 267574 */575 576 /* **************577 * timer_settime578 * **************/579 580 581 int timer_settime(582 timer_t timerid,583 int flags,584 const struct itimerspec *value,585 struct itimerspec *ovalue586 )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 an607 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 do615 * something with the structure of times of the timer: to stop, start616 * 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 be645 * initialized with new values: to start it or start it again646 */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 clock660 * ticks, to use it in the calls to RTEMS */661 662 /* It is also necessary to take in account if the time is absolute663 * 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 and685 * 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 lost735 * of precision of 1 second */736 737 /* This is the process to convert from nanoseconds to ticks738 *739 * There is a tick every 10 miliseconds, then the nanoseconds are740 * divided between 10**7. The result of this operation will be the741 * number of ticks742 */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 and761 * 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, this786 * 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 timing799 * are incorrect */800 801 /*802 * I do not know if errno must be actualized803 *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 to819 * 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. 267832 */833 834 /* **************835 * timer_gettime836 * **************/837 838 int timer_gettime(839 timer_t timerid,840 struct itimerspec *value841 )842 {843 844 /*845 * IDEA: This function does not use functions of RTEMS to the handle846 * 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 in851 * that moment is stored.852 * - When this function is called, it returns the difference853 * 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, ¤t_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 and883 * 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. 267939 */940 941 /* *****************942 * timer_getoverrun943 * *****************/944 945 int timer_getoverrun(946 timer_t timerid947 )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 finishs955 * 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 } -
cpukit/posix/src/ptimer.c
rdb7f70a r68003979 33 33 /*****************************/ 34 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 71 typedef 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 86 int timer_max; 87 timer_alive_t *timer_struct; 88 89 /* 90 * Data for the signals 91 */ 92 93 struct 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 107 static 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 122 static 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 148 void 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 } 35 #include <rtems/posix/timer.h> 173 36 174 37 /* *************************************************************************** … … 178 41 * the timers are stored 179 42 * ***************************************************************************/ 43 44 extern void TIMER_INITIALIZE_S( int ); 45 int timer_max; 46 timer_alive_t *timer_struct; 47 180 48 181 49 void _POSIX_Timer_Manager_initialization ( int max_timers ) … … 198 66 } 199 67 200 /* ***************************************************************************201 * FIRST_FREE_POSITION_F202 *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_C205 * ***************************************************************************/206 207 int 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_F224 *225 * Description: Returns the position in the table of timers in which the226 * data of the timer are stored.227 * If the timer identifier does not exist, it returns228 * BAD_TIMER_C229 * ***************************************************************************/230 231 int 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 the238 * 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 identifier246 * is not correct */247 248 return BAD_TIMER_C;249 250 }251 252 /* ***************************************************************************253 * COPY_ITIMERSPEC_S254 *255 * Description: Does a copy of a variable of type struct itimerspec256 * ***************************************************************************/257 258 void 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_S271 *272 * Description: This function converts the data of a structure itimerspec273 * into structure rtems_time_of_day274 * ***************************************************************************/275 276 void ITIMERSPEC_TO_RTEMS_TIME_OF_DAY_S277 ( 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 been282 * 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_S311 *312 * Description: This is the operation that is ran when a timer expires313 * ***************************************************************************/314 315 316 rtems_timer_service_routine FIRE_TIMER_S (rtems_id timer, void *data)317 {318 int timer_pos; /* Position in the table of the timer that319 * 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 the325 * expired timer will be stored in "timer_pos". In theory a timer can not326 * 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 function364 * specified for that signal is simulated365 */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 the378 * 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. 264387 * ********************************************************************/388 389 /* **************390 * timer_create391 * **************/392 393 int timer_create(394 clockid_t clock_id,395 struct sigevent *evp,396 timer_t *timerid397 )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 they406 * 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_create423 */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 properly434 */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 RTEMS442 * 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 value505 * to errno. In theory, it can not happen because the call to506 * 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 situations515 */516 517 return (-1);518 519 }520 521 /*522 * 14.2.3 Delete a Per_process Timer, P1003.1b-1993, p. 266523 */524 525 int timer_delete(526 timer_t timerid527 )528 {529 530 /*531 * IDEA: This function must probably stop the timer first and then delete it532 *533 * It will have to do a call to rtems_timer_cancel and then another534 * 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. 267574 */575 576 /* **************577 * timer_settime578 * **************/579 580 581 int timer_settime(582 timer_t timerid,583 int flags,584 const struct itimerspec *value,585 struct itimerspec *ovalue586 )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 an607 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 do615 * something with the structure of times of the timer: to stop, start616 * 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 be645 * initialized with new values: to start it or start it again646 */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 clock660 * ticks, to use it in the calls to RTEMS */661 662 /* It is also necessary to take in account if the time is absolute663 * 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 and685 * 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 lost735 * of precision of 1 second */736 737 /* This is the process to convert from nanoseconds to ticks738 *739 * There is a tick every 10 miliseconds, then the nanoseconds are740 * divided between 10**7. The result of this operation will be the741 * number of ticks742 */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 and761 * 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, this786 * 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 timing799 * are incorrect */800 801 /*802 * I do not know if errno must be actualized803 *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 to819 * 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. 267832 */833 834 /* **************835 * timer_gettime836 * **************/837 838 int timer_gettime(839 timer_t timerid,840 struct itimerspec *value841 )842 {843 844 /*845 * IDEA: This function does not use functions of RTEMS to the handle846 * 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 in851 * that moment is stored.852 * - When this function is called, it returns the difference853 * 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, ¤t_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 and883 * 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. 267939 */940 941 /* *****************942 * timer_getoverrun943 * *****************/944 945 int timer_getoverrun(946 timer_t timerid947 )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 finishs955 * 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 TracChangeset
for help on using the changeset viewer.