Changeset 68003979 in rtems


Ignore:
Timestamp:
Nov 2, 1999, 7:04:51 PM (20 years ago)
Author:
Joel Sherrill <joel.sherrill@…>
Branches:
4.10, 4.11, 4.8, 4.9, master
Children:
07e0743
Parents:
db7f70a
Message:

* empty log message *

Files:
4 added
3 edited

Legend:

Unmodified
Added
Removed
  • c/src/exec/posix/src/Makefile.in

    rdb7f70a r68003979  
    7474    clockgetres clockgettime clocksetenableattr clocksettime nanosleep
    7575
     76# the timer manager needs to be split further but only after its
     77# dependence on the Classic API Timer Manager is removed.
     78TIMER_C_PIECES=ptimer ptimer1
     79
    7680C_PIECES = adasupp $(CANCEL_C_PIECES) $(CONDITION_VARIABLE_C_PIECES) \
    7781    getpid $(KEY_C_PIECES) $(MESSAGE_QUEUE_C_PIECES) \
    7882    $(MUTEX_C_PIECES) $(PTHREAD_C_PIECES) \
    79     $(PSIGNAL_C_PIECES) ptimer sched $(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) \
    8185    $(BUILD_FOR_NOW_C_PIECES)
    8286
  • c/src/exec/posix/src/ptimer.c

    rdb7f70a r68003979  
    3333/*****************************/
    3434
    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>
    17336
    17437/* ***************************************************************************
     
    17841 *               the timers are stored
    17942 * ***************************************************************************/
     43
     44extern void TIMER_INITIALIZE_S( int );
     45int timer_max;
     46timer_alive_t *timer_struct;
     47
    18048
    18149void _POSIX_Timer_Manager_initialization ( int max_timers )
     
    19866}
    19967
    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 
    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_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 
    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 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 
    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_S
    271  *
    272  *  Description: This function converts the data of a structure itimerspec
    273  *               into structure rtems_time_of_day
    274  * ***************************************************************************/
    275 
    276 void 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 
    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 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 
    393 int 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 
    525 int 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 
    581 int 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 
    838 int 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 
    945 int 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 }
  • cpukit/posix/src/ptimer.c

    rdb7f70a r68003979  
    3333/*****************************/
    3434
    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>
    17336
    17437/* ***************************************************************************
     
    17841 *               the timers are stored
    17942 * ***************************************************************************/
     43
     44extern void TIMER_INITIALIZE_S( int );
     45int timer_max;
     46timer_alive_t *timer_struct;
     47
    18048
    18149void _POSIX_Timer_Manager_initialization ( int max_timers )
     
    19866}
    19967
    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 
    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_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 
    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 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 
    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_S
    271  *
    272  *  Description: This function converts the data of a structure itimerspec
    273  *               into structure rtems_time_of_day
    274  * ***************************************************************************/
    275 
    276 void 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 
    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 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 
    393 int 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 
    525 int 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 
    581 int 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 
    838 int 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 
    945 int 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 TracChangeset for help on using the changeset viewer.