Changeset 0747e2d in rtems


Ignore:
Timestamp:
Feb 3, 1999, 4:22:18 PM (20 years ago)
Author:
Joel Sherrill <joel.sherrill@…>
Branches:
4.10, 4.11, 4.8, 4.9, master
Children:
cd792a86
Parents:
c30d04d7
Message:

POSIX Timers submitted by Juan Zamorano Flores
<jzamora@…>.

Files:
2 added
10 edited

Legend:

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

    rc30d04d7 r0747e2d  
    1414
    1515H_PIECES= cond config key mutex posixapi \
    16     priority psignal pthread seterr threadsup time
     16    priority psignal pthread ptimer seterr threadsup time
    1717#H_PIECES= cancel cond intr key mqueue mqueuemp mutex \
    1818#    mutexmp pthread pthreadmp priority semaphore semaphoremp threadsup \
  • c/src/exec/posix/include/rtems/posix/config.h

    rc30d04d7 r0747e2d  
    4747  int                                 maximum_condition_variables;
    4848  int                                 maximum_keys;
     49  int                                 maximum_timers;
    4950  int                                 maximum_queued_signals;
    5051  int                                 number_of_initialization_threads;
  • c/src/exec/posix/src/Makefile.in

    rc30d04d7 r0747e2d  
    1010
    1111# following are semi-implemented and untested
    12 # C_PIECES=aio cancel devctl intr mqueue ptimer semaphore time utsname
     12# C_PIECES=aio cancel devctl intr mqueue semaphore time utsname
    1313
    1414ENOSYS_C_PIECES=\
     
    3737
    3838C_PIECES= adasupp cond getpid key mutex $(PTHREAD_PIECES) \
    39   $(PSIGNAL_PIECES) sched time \
     39  $(PSIGNAL_PIECES) ptimer sched time \
    4040  types unistd $(ENOSYS_C_PIECES)
    4141
  • c/src/exec/posix/src/ptimer.c

    rc30d04d7 r0747e2d  
    11/*
    2  *  $Id$
     2 *  ptimer.c,v 1.1 1996/06/03 16:29:58 joel Exp
    33 */
    4 
     4 
    55#include <assert.h>
    66#include <time.h>
     
    1414#include <rtems/posix/time.h>
    1515
     16/************************************/
     17/* These includes are now necessary */
     18/************************************/
     19
     20#include <sys/features.h>
     21#include <rtems/rtems/status.h>
     22#include <rtems/rtems/types.h>
     23#include <rtems/rtems/timer.h>
     24#include <rtems/rtems/clock.h>
     25#include <rtems/posix/psignal.h>
     26#include <rtems/score/wkspace.h>
     27#include <pthread.h>
     28#include <stdio.h>
     29#include <signal.h>
     30
     31/*****************************/
     32/* End of necessary includes */
     33/*****************************/
     34
     35/* ************
     36 * Constants
     37 * ************/
     38
     39#define STATE_FREE_C        0x01 /* Free position of the table of timers   */
     40#define STATE_CREATE_NEW_C  0x02 /* Created timer but not running          */
     41#define STATE_CREATE_RUN_C  0x03 /* Created timer and running              */
     42#define STATE_CREATE_STOP_C 0x04 /* Created, ran and stopped timer         */
     43#define MAX_NSEC_C    1000000000 /* Maximum number of nsec allowed         */
     44#define MIN_NSEC_C             0 /* Minimum number of nsec allowew         */
     45#define TIMER_RELATIVE_C       0 /* Indicates that the fire time is       
     46                                  * relative to the current one            */
     47#define SEC_TO_TICKS_C _TOD_Ticks_per_second /* Number of ticks in a second*/
     48#define NSEC_PER_SEC_C 1000000000 /* Nanoseconds in a second               */
     49
     50#define NO_MORE_TIMERS_C      11 /* There is not available timers          */
     51#define BAD_TIMER_C           11 /* The timer does not exist in the table  */
     52
     53#define SECONDS_PER_YEAR_C    ( 360 * 24 * 60 * 60 )
     54#define SECONDS_PER_MONTH_C    ( 30 * 24 * 60 * 60 )
     55#define SECONDS_PER_DAY_C           ( 24 * 60 * 60 )
     56#define SECONDS_PER_HOUR_C               ( 60 * 60 )
     57#define SECONDS_PER_MINUTE_C                  ( 60 )
     58
    1659/*
     60#define DEBUG_MESSAGES
     61 */
     62
     63/* *********************************************************
     64 * Types that will store the created timers and their data
     65 * *********************************************************/
     66
     67/*
     68 * Data for a timer
     69 */
     70
     71typedef struct {
     72  pthread_t         thread_id;  /* Thread identifier                     */
     73  char              state;      /* State of the timer                    */
     74  struct sigevent   inf;        /* Information associated to the timer   */
     75  timer_t           timer_id;   /* Created timer identifier              */
     76  struct itimerspec timer_data; /* Timing data of the timer              */
     77  unsigned32        ticks;      /* Number of ticks of the initialization */
     78  unsigned32        overrun;    /* Number of expirations of the timer    */
     79  rtems_time_of_day time;       /* Time in which the timer was started   */
     80} timer_alive_t;
     81
     82/*
     83 * Array of Timers
     84 */
     85
     86int timer_max;
     87timer_alive_t *timer_struct;
     88
     89/*
     90 * Data for the signals
     91 */
     92
     93struct sigaction signal_inf[SIGRTMAX];
     94
     95/***********************************
     96 * Definition of Internal Functions
     97 ***********************************/
     98
     99/* ***************************************************************************
     100 * PRINT_MSG_S
     101 *
     102 *  Description: This function write a message in the display.
     103 *               It is used for debugging and all the calls must be deleted
     104 *               when the tests finish
     105 * ***************************************************************************/
     106
     107static void PRINT_MSG_S ( char *msg )
     108{
     109
     110#ifdef DEBUG_MESSAGES
     111   printf("%s\n", msg);
     112#endif
     113
     114}
     115
     116/* ***************************************************************************
     117 * PRINT_ERRNO_S
     118 *
     119 *  Description: Print the value of the global variable errno in the display
     120 * ***************************************************************************/
     121
     122static void PRINT_ERRNO_S ()
     123{
     124#ifdef DEBUG_MESSAGES
     125  switch (errno)
     126  {
     127     case EINVAL:
     128       PRINT_MSG_S ( "errno EINVAL"); break;
     129     case EPERM:
     130       PRINT_MSG_S ( "errno EPERM"); break;
     131     case ESRCH:
     132       PRINT_MSG_S ( "errno ESRCH"); break;
     133     case EAGAIN:
     134       PRINT_MSG_S ( "errno EAGAIN"); break;
     135     default :
     136       printf ("errno: %d\n", errno);
     137       break;
     138  }
     139#endif
     140}
     141 
     142/* ***************************************************************************
     143 * TIMER_INITIALIZE_S
     144 *
     145 *  Description: Initialize the data of a timer
     146 * ***************************************************************************/
     147
     148void TIMER_INITIALIZE_S ( int timer_pos )
     149{
     150
     151   /*
     152    * Indicates that the position in the table is free
     153    */
     154
     155    timer_struct[timer_pos].state = STATE_FREE_C;
     156
     157   /*
     158    * The initial data of timing are set with null value
     159    */
     160
     161    timer_struct[timer_pos].timer_data.it_value.tv_sec     = 0;
     162    timer_struct[timer_pos].timer_data.it_value.tv_nsec    = 0;
     163    timer_struct[timer_pos].timer_data.it_interval.tv_sec  = 0;
     164    timer_struct[timer_pos].timer_data.it_interval.tv_nsec = 0;
     165
     166   /*
     167    * The count of expirations is 0
     168    */
     169
     170    timer_struct[timer_pos].overrun = 0;
     171
     172}
     173
     174/* ***************************************************************************
     175 * _POSIX_Timer_Manager_initialization
     176 *
     177 *  Description: Initialize the internal structure in which the data of all
     178 *               the timers are stored
     179 * ***************************************************************************/
     180
     181void _POSIX_Timer_Manager_initialization ( int max_timers )
     182{
     183   int index;
     184
     185   timer_struct = _Workspace_Allocate_or_fatal_error(
     186      max_timers * sizeof(timer_alive_t) );
     187
     188   /*
     189    *  Initialize all the timers
     190    */
     191
     192   for (index=0; index<max_timers; index++)
     193     TIMER_INITIALIZE_S( index );
     194}
     195
     196/* ***************************************************************************
     197 * FIRST_FREE_POSITION_F
     198 *
     199 *  Description: Returns the first free position in the table of timers.
     200 *               If there is not a free position, it returns NO_MORE_TIMERS_C
     201 * ***************************************************************************/
     202
     203int FIRST_FREE_POSITION_F ()
     204{
     205   int index;
     206
     207   for (index=0; index<timer_max; index++) {
     208      if ( timer_struct[index].state == STATE_FREE_C ) {
     209         return index;
     210      }
     211   }
     212   
     213   /* The function reaches this point only if all the position are occupied */
     214
     215   return NO_MORE_TIMERS_C;
     216}
     217
     218/* ***************************************************************************
     219 * TIMER_POSITION_F
     220 *
     221 *  Description: Returns the position in the table of timers in which the
     222 *               data of the timer are stored.
     223 *               If the timer identifier does not exist, it returns
     224 *               BAD_TIMER_C
     225 * ***************************************************************************/
     226
     227int TIMER_POSITION_F ( timer_t timer_id )
     228{
     229  int index;
     230
     231  for (index=0; index<timer_max; index++ ) {
     232
     233     /* Looks for the position of the timer. The timer must exist and the
     234      * position can not be free */
     235     if ( ( timer_struct[index].timer_id == timer_id ) &&
     236          ( timer_struct[index].state != STATE_FREE_C ) ) {
     237        return index;
     238     }
     239  }
     240
     241  /* If the function reaches this point is because the timer identifier
     242   * is not correct */
     243
     244   return BAD_TIMER_C;
     245
     246}
     247
     248/* ***************************************************************************
     249 * COPY_ITIMERSPEC_S
     250 *
     251 *  Description: Does a copy of a variable of type struct itimerspec 
     252 * ***************************************************************************/
     253
     254void COPY_ITIMERSPEC_S ( const struct itimerspec *source,
     255                         struct itimerspec *target )
     256{
     257
     258   target->it_value.tv_sec     = source->it_value.tv_sec;
     259   target->it_value.tv_nsec    = source->it_value.tv_nsec;
     260   target->it_interval.tv_sec  = source->it_interval.tv_sec;
     261   target->it_interval.tv_nsec = source->it_interval.tv_nsec;
     262
     263}
     264
     265/* ***************************************************************************
     266 * ITIMERSPEC_TO_RTEMS_TIME_OF_DAY_S
     267 *
     268 *  Description: This function converts the data of a structure itimerspec
     269 *               into structure rtems_time_of_day
     270 * ***************************************************************************/
     271
     272void ITIMERSPEC_TO_RTEMS_TIME_OF_DAY_S
     273   ( const struct itimerspec *itimer, rtems_time_of_day *rtems_time )
     274{
     275   unsigned long int seconds;
     276
     277   /* The leap years and the months with 28, 29 or 31 days have not been
     278    * considerated. It will be made in the future */
     279
     280   seconds            = itimer->it_value.tv_sec;
     281
     282   rtems_time->year   = seconds / SECONDS_PER_YEAR_C;
     283   seconds            = seconds % SECONDS_PER_YEAR_C;
     284
     285   rtems_time->month  = seconds / SECONDS_PER_MONTH_C;
     286   seconds            = seconds % SECONDS_PER_MONTH_C;
     287
     288   rtems_time->day    = seconds / SECONDS_PER_DAY_C;
     289   seconds            = seconds % SECONDS_PER_DAY_C;
     290
     291   rtems_time->hour   = seconds / SECONDS_PER_HOUR_C;
     292   seconds            = seconds % SECONDS_PER_HOUR_C;
     293
     294   rtems_time->minute = seconds / SECONDS_PER_MINUTE_C;
     295   seconds            = seconds % SECONDS_PER_MINUTE_C;
     296
     297   rtems_time->second = seconds;
     298
     299   rtems_time->ticks  = ( itimer->it_value.tv_nsec * SEC_TO_TICKS_C ) /
     300                        NSEC_PER_SEC_C;
     301
     302}
     303
     304
     305/* ***************************************************************************
     306 * FIRE_TIMER_S
     307 *
     308 *  Description: This is the operation that is ran when a timer expires
     309 * ***************************************************************************/
     310
     311
     312rtems_timer_service_routine FIRE_TIMER_S (rtems_id timer, void *data)
     313{
     314  int               timer_pos;  /* Position in the table of the timer that   
     315                                 *  has expirated                            */
     316  rtems_status_code return_v;   /* Return value of rtems_timer_fire_after    */
     317  int               sig_number; /* Number of the signal to send              */
     318
     319 
     320  /* The position of the table of timers that contains the data of the
     321   * expired timer will be stored in "timer_pos". In theory a timer can not
     322   * expire if it has not been created or has been deleted */
     323
     324  PRINT_MSG_S ("FIRE_TIMER_S");
     325
     326  timer_pos = TIMER_POSITION_F(timer);
     327
     328  /* Increases the number of expiration of the timer in one unit. */
     329  timer_struct[timer_pos].overrun = timer_struct[timer_pos].overrun + 1;
     330
     331
     332  if ( ( timer_struct[timer_pos].timer_data.it_interval.tv_sec  != 0 ) ||
     333       ( timer_struct[timer_pos].timer_data.it_interval.tv_nsec != 0 ) ) {
     334
     335     /* The timer must be reprogrammed */
     336
     337     return_v = rtems_timer_fire_after ( timer,
     338                                        timer_struct[timer_pos].ticks,
     339                                        FIRE_TIMER_S,
     340                                        NULL );
     341
     342     /* Stores the time when the timer was started again */
     343
     344     return_v = rtems_clock_get ( RTEMS_CLOCK_GET_TOD,
     345                                 &timer_struct[timer_pos].time );
     346     
     347     /* The state has not to be actualized, because nothing modifies it */
     348
     349     timer_struct[timer_pos].state = STATE_CREATE_RUN_C;
     350
     351  } else {
     352     /* Indicates that the timer is stopped */
     353 
     354     timer_struct[timer_pos].state = STATE_CREATE_STOP_C;
     355
     356  }
     357
     358  /*
     359   * The sending of the signal to the process running the handling function
     360   * specified for that signal is simulated
     361   */
     362
     363  sig_number = timer_struct[timer_pos].inf.sigev_signo;
     364
     365  if( pthread_kill ( timer_struct[timer_pos].thread_id ,
     366                     timer_struct[timer_pos].inf.sigev_signo ) ) {
     367     PRINT_MSG_S ("ERROR_PTHREAD_KILL");
     368  } else {
     369     PRINT_MSG_S ("SUCCESS_PTHREAD_KILL");
     370  }
     371
     372  /*
     373   * After the signal handler returns, the count of expirations of the
     374   * timer must be set to 0.
     375   */
     376
     377  timer_struct[timer_pos].overrun = 0;
     378
     379}
     380
     381/* *********************************************************************
    17382 *  14.2.2 Create a Per-Process Timer, P1003.1b-1993, p. 264
    18  */
     383 * ********************************************************************/
     384
     385/* **************
     386 * timer_create
     387 * **************/
    19388
    20389int timer_create(
     
    24393)
    25394{
    26   return POSIX_NOT_IMPLEMENTED();
     395
     396  rtems_status_code return_v;  /* return value of the operation    */
     397  rtems_id          timer_id;  /* created timer identifier         */
     398  int               timer_pos; /* Position in the table of timers  */
     399
     400 /*
     401  * The data of the structure evp are checked in order to verify if they
     402  * are coherent.
     403  */
     404
     405  if (evp != NULL) {
     406     /* The structure has data */
     407
     408     if ( ( evp->sigev_notify != SIGEV_NONE ) &&
     409          ( evp->sigev_notify != SIGEV_SIGNAL ) ) {
     410       /* The value of the field sigev_notify is not valid */
     411
     412       return (-1);
     413
     414     }
     415  }
     416 
     417 /*
     418  * A timer is created using the primitive rtems_timer_create
     419  */
     420
     421  return_v = rtems_timer_create ( clock_id, &timer_id );
     422
     423  switch (return_v) {
     424     case RTEMS_SUCCESSFUL :
     425
     426       PRINT_MSG_S("SUCCESS: rtems create timer RTEMS_SUCCESSFUL");
     427     
     428       /*
     429        * The timer has been created properly
     430        */
     431 
     432        /* Obtains the first free position in the table of timers */
     433
     434        timer_pos = FIRST_FREE_POSITION_F();
     435
     436        if ( timer_pos == NO_MORE_TIMERS_C ) {
     437           /* There is not position for another timers in spite of RTEMS
     438            * supports it. It will necessaty to increase the structure used */
     439
     440           errno = EAGAIN;
     441
     442           return -1;
     443        }
     444
     445        /* Exit parameter */
     446
     447        *timerid  = timer_id;
     448
     449        /* The data of the created timer are stored to use them later */
     450
     451        timer_struct[timer_pos].state     = STATE_CREATE_NEW_C;
     452
     453        /* NEW VERSION*/
     454        timer_struct[timer_pos].thread_id = pthread_self ();
     455       
     456
     457        if ( evp != NULL ) {
     458
     459           timer_struct[timer_pos].inf.sigev_notify = evp->sigev_notify;
     460           timer_struct[timer_pos].inf.sigev_signo  = evp->sigev_signo;
     461           timer_struct[timer_pos].inf.sigev_value  = evp->sigev_value;
     462
     463        }
     464
     465
     466        timer_struct[timer_pos].timer_id = timer_id;
     467
     468        timer_struct[timer_pos].overrun  = 0;
     469
     470        timer_struct[timer_pos].timer_data.it_value.tv_sec     = 0;
     471        timer_struct[timer_pos].timer_data.it_value.tv_nsec    = 0;
     472        timer_struct[timer_pos].timer_data.it_interval.tv_sec  = 0;
     473        timer_struct[timer_pos].timer_data.it_interval.tv_nsec = 0;
     474
     475        return 0;
     476   
     477
     478     case RTEMS_INVALID_NAME : /* The assigned name is not valid*/
     479
     480       PRINT_MSG_S ("ERROR: rtems create timer RTEMS_INVALID_NAME");
     481
     482       errno = EINVAL;
     483
     484       return (-1);
     485
     486
     487     case RTEMS_TOO_MANY :
     488
     489       PRINT_MSG_S ("ERROR: rtems create timer RTEMS_TOO_MANY ");
     490 
     491       /* There has been created too much timers for the same process */
     492
     493       errno = EAGAIN;
     494
     495       return (-1);
     496     
     497     default :
     498
     499       /*
     500        * Does nothing. It only returns the error without assigning a value
     501        * to errno. In theory, it can not happen because the call to
     502        * rtems_timer_create can not return other different value.
     503        */
     504
     505       return (-1);
     506
     507  }
     508
     509  /*
     510   * The next sentence is used to avoid singular situations
     511   */
     512
     513  return (-1);
     514
    27515}
    28516
     
    35523)
    36524{
    37   return POSIX_NOT_IMPLEMENTED();
     525 
     526 /*
     527  * IDEA: This function must probably stop the timer first and then delete it
     528  *
     529  *       It will have to do a call to rtems_timer_cancel and then another
     530  *       call to rtems_timer_delete.
     531  *       The call to rtems_timer_delete will be probably unnecessary,
     532  *       because rtems_timer_delete stops the timer before deleting it.
     533  */
     534
     535  int               timer_pos;
     536  rtems_status_code status;
     537
     538
     539   /* First the position in the table of timers is obtained */
     540
     541   timer_pos = TIMER_POSITION_F ( timerid );
     542
     543   if ( timer_pos == BAD_TIMER_C ) {
     544      /* The timer identifier is erroneus */
     545
     546      errno = EINVAL;
     547      return -1;
     548   }
     549
     550   /* The timer is deleted */
     551
     552   status = rtems_timer_delete ( timerid );
     553
     554   if ( status == RTEMS_INVALID_ID ) {
     555      /* The timer identifier is erroneus */
     556
     557      errno = EINVAL;
     558      return -1;
     559   }
     560
     561   /* Initializes the data of the timer */
     562
     563   TIMER_INITIALIZE_S ( timer_pos );
     564
     565   return 0;
    38566}
    39567
     
    41569 *  14.2.4 Per-Process Timers, P1003.1b-1993, p. 267
    42570 */
     571
     572/* **************
     573 * timer_settime
     574 * **************/
     575
    43576
    44577int timer_settime(
     
    49582)
    50583{
    51   return POSIX_NOT_IMPLEMENTED();
    52 }
     584
     585   rtems_status_code return_v;   /* Return of the calls to RTEMS        */
     586   int               timer_pos;  /* Position of the timer in the table  */
     587   rtems_time_of_day rtems_time; /* Time in RTEMS                       */
     588
     589   /* First the position in the table of timers is obtained */
     590
     591   timer_pos = TIMER_POSITION_F ( timerid );
     592
     593   if ( timer_pos == BAD_TIMER_C ) {
     594      /* The timer identifier is erroneus */
     595
     596      errno = EINVAL;
     597      return -1;
     598   }
     599
     600   if ( value == NULL ) {
     601     /* The stucture of times of the timer is free, and then returns an
     602        error but the variable errno is not actualized */
     603
     604     /* errno = ?????? */
     605
     606     return -1;
     607   }
     608
     609   /* If the function reaches this point, then it will be necessary to do
     610    * something with the structure of times of the timer: to stop, start
     611    * or start it again */
     612
     613   /* First, it verifies if the timer must be stopped */
     614
     615   if ( value->it_value.tv_sec == 0 && value->it_value.tv_nsec == 0 ) {
     616      /* The timer is stopped */
     617
     618      return_v = rtems_timer_cancel ( timerid );
     619
     620      /* The old data of the timer are returned */
     621
     622      COPY_ITIMERSPEC_S ( &timer_struct[timer_pos].timer_data, ovalue );
     623
     624      /* The new data are set */
     625
     626      COPY_ITIMERSPEC_S ( value, &timer_struct[timer_pos].timer_data );
     627
     628      /* Indicates that the timer is created and stopped */
     629 
     630      timer_struct[timer_pos].state = STATE_CREATE_STOP_C;
     631
     632      /* Returns with success */
     633
     634      return 0;
     635   }
     636
     637   /*
     638    * If the function reaches this point, then the timer will have to be
     639    * initialized with new values: to start it or start it again
     640    */
     641 
     642   /* First, it verifies if the structure "value" is correct */
     643
     644    if ( ( value->it_value.tv_nsec > MAX_NSEC_C ) ||
     645         ( value->it_value.tv_nsec < MIN_NSEC_C ) ) {
     646       /* The number of nanoseconds is not correct */
     647
     648       errno = EINVAL;
     649
     650       return -1;
     651    }
     652
     653   /* Then, "value" must be converted from seconds and nanoseconds to clock
     654    * ticks, to use it in the calls to RTEMS */
     655
     656   /* It is also necessary to take in account if the time is absolute
     657    * or relative */
     658
     659   switch (flags) {
     660      case TIMER_ABSTIME:
     661
     662        /* The fire time is absolute:
     663         * It has to use "rtems_time_fire_when" */
     664
     665        /* First, it converts from struct itimerspec to rtems_time_of_day */
     666
     667        ITIMERSPEC_TO_RTEMS_TIME_OF_DAY_S ( value, &rtems_time );
     668
     669        return_v = rtems_timer_fire_when ( timerid, &rtems_time, FIRE_TIMER_S, NULL);
     670
     671        switch ( return_v ) {
     672           case RTEMS_SUCCESSFUL:
     673
     674              PRINT_MSG_S ("SUCCESS: timer_settime RTEMS_SUCCESSFUL");
     675
     676              /* The timer has been started and is running */
     677
     678              /* Actualizes the data of the structure and
     679               * returns the old ones in "ovalue" */
     680
     681              COPY_ITIMERSPEC_S ( &timer_struct[timer_pos].timer_data, ovalue );
     682
     683              COPY_ITIMERSPEC_S ( value, &timer_struct[timer_pos].timer_data );
     684 
     685              /* It indicates that the time is running */
     686
     687              timer_struct[timer_pos].state = STATE_CREATE_RUN_C;
     688
     689              /* Stores the time in which the timer was started again */
     690
     691              return_v = rtems_clock_get ( RTEMS_CLOCK_GET_TOD,
     692                                          &timer_struct[timer_pos].time );
     693
     694              return 0;
     695
     696              break;
     697
     698           case RTEMS_INVALID_ID:
     699
     700              PRINT_MSG_S ("ERROR: timer_settime RTEMS_INVALID_ID");
     701              break;
     702
     703           case RTEMS_NOT_DEFINED:
     704
     705              PRINT_MSG_S ("ERROR: timer_settime RTEMS_NOT_DEFINED");
     706              break;
     707
     708           case RTEMS_INVALID_CLOCK:
     709
     710              PRINT_MSG_S ("ERROR: timer_settime RTEMS_INVALID_CLOCK");
     711              break;
     712
     713           default:
     714
     715       
     716        }
     717     
     718        break;
     719
     720      case TIMER_RELATIVE_C:
     721
     722        /* The fire time is relative:
     723         * It has to use "rtems_time_fire_after" */
     724
     725        /* First, it converts from seconds and nanoseconds to ticks */
     726
     727        /* The form in which this operation is done can produce a lost
     728         * of precision of 1 second */
     729 
     730/*      This is the process to convert from nanoseconds to ticks
     731 *
     732 *      There is a tick every 10 miliseconds, then the nanoseconds are
     733 *      divided between 10**7. The result of this operation will be the
     734 *      number of ticks
     735 */
     736
     737        timer_struct[timer_pos].ticks =
     738             ( SEC_TO_TICKS_C * value->it_value.tv_sec ) +
     739             ( value->it_value.tv_nsec / ( 1000 * 1000 * 10 ) );
     740
     741        return_v = rtems_timer_fire_after ( timerid,
     742                                           timer_struct[timer_pos].ticks,
     743                                           FIRE_TIMER_S,
     744                                           NULL );
     745
     746        switch (return_v) {
     747           case RTEMS_SUCCESSFUL:
     748
     749              PRINT_MSG_S ( "SUCCESS: timer_settime RTEMS_SUCCESSFUL");
     750             
     751              /* The timer has been started and is running */
     752
     753              /* Actualizes the data of the structure and
     754               * returns the old ones in "ovalue" */
     755
     756              COPY_ITIMERSPEC_S ( &timer_struct[timer_pos].timer_data, ovalue );
     757
     758              COPY_ITIMERSPEC_S ( value, &timer_struct[timer_pos].timer_data );
     759 
     760              /* It indicates that the time is running */
     761
     762              timer_struct[timer_pos].state = STATE_CREATE_RUN_C;
     763
     764              /* Stores the time in which the timer was started again */
     765
     766              return_v = rtems_clock_get ( RTEMS_CLOCK_GET_TOD,
     767                                          &timer_struct[timer_pos].time );
     768 
     769              return 0;
     770
     771              break;
     772
     773           case RTEMS_INVALID_ID:
     774
     775              PRINT_MSG_S ( "ERROR: timer_settime RTEMS_INVALID_ID");
     776
     777              /* The timer identifier is not correct. In theory, this
     778               * situation can not occur, but the solution is easy */
     779
     780              errno = EINVAL;
     781
     782              return -1;
     783
     784              break;
     785
     786           case RTEMS_INVALID_NUMBER:
     787
     788              PRINT_MSG_S ( "ERROR: timer_settime RTEMS_INVALID_NUMBER");
     789
     790              /* In this case, RTEMS fails because the values of timing
     791               * are incorrect */
     792
     793              /*
     794               * I do not know if errno must be actualized
     795               *
     796               * errno = EINVAL;
     797               */
     798
     799              return -1;
     800
     801              break;
     802           
     803           default:
     804        }
     805
     806        break;
     807
     808      default:
     809
     810        /* It does nothing, although it will be probably necessary to
     811         * return an error */
     812
     813   }
     814
     815   /* To avoid problems */
     816
     817   return 0;
     818
     819}
     820
    53821
    54822/*
    55823 *  14.2.4 Per-Process Timers, P1003.1b-1993, p. 267
    56824 */
     825
     826/* **************
     827 * timer_gettime
     828 * **************/
    57829
    58830int timer_gettime(
     
    61833)
    62834{
    63   return POSIX_NOT_IMPLEMENTED();
     835
     836 /*
     837  * IDEA:  This function does not use functions of RTEMS to the handle
     838  *        of timers. It uses some functions for managing the time.
     839  *
     840  *        A possible form to do this is the following:
     841  *
     842  *          - When a timer is initialized, the value of the time in
     843  *            that moment is stored.
     844  *          - When this function is called, it returns the difference
     845  *            between the current time and the initialization time.
     846  */
     847 
     848  rtems_time_of_day current_time;
     849  rtems_status_code return_v;
     850  int               timer_pos;
     851  unsigned32        hours;
     852  unsigned32        minutes;
     853  unsigned32        seconds;
     854  unsigned32        ticks;
     855  unsigned32        nanosec;
     856 
     857
     858  /* Reads the current time */
     859
     860  return_v = rtems_clock_get ( RTEMS_CLOCK_GET_TOD, &current_time );
     861
     862  timer_pos = TIMER_POSITION_F ( timerid );
     863
     864  if ( timer_pos == BAD_TIMER_C ) {
     865
     866     /* The timer identifier is erroneus */ 
     867
     868     errno = EINVAL;
     869
     870     return (-1);
     871
     872  }
     873
     874  /* Calculates the difference between the start time of the timer and
     875   * the current one */
     876
     877  hours    = current_time.hour - timer_struct[timer_pos].time.hour;
     878
     879  if ( current_time.minute < timer_struct[timer_pos].time.minute ) {
     880     minutes = 60 - timer_struct[timer_pos].time.minute + current_time.minute;
     881     hours--;
     882  } else {
     883     minutes = current_time.minute - timer_struct[timer_pos].time.minute;
     884  }
     885   
     886  if ( current_time.second < timer_struct[timer_pos].time.second ) {
     887     seconds = 60 - timer_struct[timer_pos].time.second + current_time.second;
     888     minutes--;
     889  } else {
     890     seconds = current_time.second - timer_struct[timer_pos].time.second;
     891  }
     892
     893  if ( current_time.ticks < timer_struct[timer_pos].time.ticks ) {
     894     ticks = 100 - timer_struct[timer_pos].time.ticks + current_time.ticks;
     895     seconds--;
     896  } else {
     897     ticks = current_time.ticks - timer_struct[timer_pos].time.ticks;
     898  }
     899
     900  /* The time that the timer is running is calculated */
     901  seconds = hours   * 60 * 60 +
     902            minutes * 60      +
     903            seconds;
     904
     905  nanosec  = ticks * 10 *  /* msec     */
     906             1000  *       /* microsec */
     907             1000;         /* nanosec  */
     908
     909 
     910  /* Calculates the time left before the timer finishes */
     911 
     912  value->it_value.tv_sec =
     913    timer_struct[timer_pos].timer_data.it_value.tv_sec - seconds;
     914 
     915  value->it_value.tv_nsec =
     916    timer_struct[timer_pos].timer_data.it_value.tv_nsec - nanosec;
     917
     918
     919  value->it_interval.tv_sec  =
     920    timer_struct[timer_pos].timer_data.it_interval.tv_sec;
     921  value->it_interval.tv_nsec =
     922    timer_struct[timer_pos].timer_data.it_interval.tv_nsec;
     923 
     924
     925  return 0;
     926
    64927}
    65928
     
    68931 */
    69932
     933/* *****************
     934 * timer_getoverrun
     935 * *****************/
     936
    70937int timer_getoverrun(
    71938  timer_t   timerid
    72939)
    73940{
    74   return POSIX_NOT_IMPLEMENTED();
    75 }
     941
     942 /*
     943  * IDEA: This function must count the times the timer expires.
     944  *   
     945  *       The expiration of a timer must increase by one a counter.
     946  *       After the signal handler associated to the timer finishs
     947  *       its execution, FIRE_TIMER_S will have to set this counter to 0.
     948  */
     949
     950  int timer_pos; /* Position of the timer in the structure     */
     951  int overrun;   /* Overflow count                             */
     952
     953
     954  timer_pos = TIMER_POSITION_F ( timerid );
     955
     956  if ( timer_pos == BAD_TIMER_C ) {
     957     /* The timer identifier is erroneus */
     958
     959     errno = EINVAL;
     960
     961     return -1;
     962  }
     963
     964  /* The overflow count of the timer is stored in "overrun" */
     965
     966  overrun = timer_struct[timer_pos].overrun;
     967
     968  /* It is set to 0 */
     969
     970  timer_struct[timer_pos].overrun = 0;
     971
     972  return overrun;
     973
     974}
  • c/src/exec/sapi/include/confdefs.h

    rc30d04d7 r0747e2d  
    354354#endif
    355355
     356#ifndef CONFIGURE_MAXIMUM_POSIX_TIMERS
     357#define CONFIGURE_MAXIMUM_POSIX_TIMERS 0
     358#endif
     359
    356360#ifndef CONFIGURE_MAXIMUM_POSIX_QUEUED_SIGNALS
    357361#define CONFIGURE_MAXIMUM_POSIX_QUEUED_SIGNALS 0
     
    412416  ((_keys) * \
    413417   ( sizeof(POSIX_Keys_Control) + CONFIGURE_OBJECT_TABLE_STUFF ) )
     418
     419#define CONFIGURE_MEMORY_FOR_POSIX_TIMERS(_timers) \
     420  ((_timers) * \
     421   ( 0 ) )
    414422
    415423#define CONFIGURE_MEMORY_FOR_POSIX_QUEUED_SIGNALS(_queued_signals) \
     
    618626    CONFIGURE_MAXIMUM_ADA_TASKS + CONFIGURE_MAXIMUM_FAKE_ADA_TASKS,
    619627  CONFIGURE_MAXIMUM_POSIX_KEYS + CONFIGURE_GNAT_KEYS,
     628  CONFIGURE_MAXIMUM_POSIX_TIMERS,
    620629  CONFIGURE_MAXIMUM_POSIX_QUEUED_SIGNALS,
    621630  CONFIGURE_POSIX_INIT_THREAD_TABLE_SIZE,
  • c/src/exec/sapi/src/posixapi.c

    rc30d04d7 r0747e2d  
    3737#include <rtems/posix/psignal.h>
    3838#include <rtems/posix/pthread.h>
     39#include <rtems/posix/ptimer.h>
    3940#include <rtems/posix/time.h>
    4041
     
    5152  0,                             /* maximum_condition_variables */
    5253  0,                             /* maximum_keys */
     54  0,                             /* maximum_timers */
    5355  0,                             /* maximum_queued_signals */
    5456  0,                             /* number_of_initialization_threads */
     
    9193  );
    9294
     95  _POSIX_Timer_Manager_initialization ( api_configuration->maximum_timers );
    9396}
    9497
  • cpukit/posix/include/rtems/posix/config.h

    rc30d04d7 r0747e2d  
    4747  int                                 maximum_condition_variables;
    4848  int                                 maximum_keys;
     49  int                                 maximum_timers;
    4950  int                                 maximum_queued_signals;
    5051  int                                 number_of_initialization_threads;
  • cpukit/posix/src/ptimer.c

    rc30d04d7 r0747e2d  
    11/*
    2  *  $Id$
     2 *  ptimer.c,v 1.1 1996/06/03 16:29:58 joel Exp
    33 */
    4 
     4 
    55#include <assert.h>
    66#include <time.h>
     
    1414#include <rtems/posix/time.h>
    1515
     16/************************************/
     17/* These includes are now necessary */
     18/************************************/
     19
     20#include <sys/features.h>
     21#include <rtems/rtems/status.h>
     22#include <rtems/rtems/types.h>
     23#include <rtems/rtems/timer.h>
     24#include <rtems/rtems/clock.h>
     25#include <rtems/posix/psignal.h>
     26#include <rtems/score/wkspace.h>
     27#include <pthread.h>
     28#include <stdio.h>
     29#include <signal.h>
     30
     31/*****************************/
     32/* End of necessary includes */
     33/*****************************/
     34
     35/* ************
     36 * Constants
     37 * ************/
     38
     39#define STATE_FREE_C        0x01 /* Free position of the table of timers   */
     40#define STATE_CREATE_NEW_C  0x02 /* Created timer but not running          */
     41#define STATE_CREATE_RUN_C  0x03 /* Created timer and running              */
     42#define STATE_CREATE_STOP_C 0x04 /* Created, ran and stopped timer         */
     43#define MAX_NSEC_C    1000000000 /* Maximum number of nsec allowed         */
     44#define MIN_NSEC_C             0 /* Minimum number of nsec allowew         */
     45#define TIMER_RELATIVE_C       0 /* Indicates that the fire time is       
     46                                  * relative to the current one            */
     47#define SEC_TO_TICKS_C _TOD_Ticks_per_second /* Number of ticks in a second*/
     48#define NSEC_PER_SEC_C 1000000000 /* Nanoseconds in a second               */
     49
     50#define NO_MORE_TIMERS_C      11 /* There is not available timers          */
     51#define BAD_TIMER_C           11 /* The timer does not exist in the table  */
     52
     53#define SECONDS_PER_YEAR_C    ( 360 * 24 * 60 * 60 )
     54#define SECONDS_PER_MONTH_C    ( 30 * 24 * 60 * 60 )
     55#define SECONDS_PER_DAY_C           ( 24 * 60 * 60 )
     56#define SECONDS_PER_HOUR_C               ( 60 * 60 )
     57#define SECONDS_PER_MINUTE_C                  ( 60 )
     58
    1659/*
     60#define DEBUG_MESSAGES
     61 */
     62
     63/* *********************************************************
     64 * Types that will store the created timers and their data
     65 * *********************************************************/
     66
     67/*
     68 * Data for a timer
     69 */
     70
     71typedef struct {
     72  pthread_t         thread_id;  /* Thread identifier                     */
     73  char              state;      /* State of the timer                    */
     74  struct sigevent   inf;        /* Information associated to the timer   */
     75  timer_t           timer_id;   /* Created timer identifier              */
     76  struct itimerspec timer_data; /* Timing data of the timer              */
     77  unsigned32        ticks;      /* Number of ticks of the initialization */
     78  unsigned32        overrun;    /* Number of expirations of the timer    */
     79  rtems_time_of_day time;       /* Time in which the timer was started   */
     80} timer_alive_t;
     81
     82/*
     83 * Array of Timers
     84 */
     85
     86int timer_max;
     87timer_alive_t *timer_struct;
     88
     89/*
     90 * Data for the signals
     91 */
     92
     93struct sigaction signal_inf[SIGRTMAX];
     94
     95/***********************************
     96 * Definition of Internal Functions
     97 ***********************************/
     98
     99/* ***************************************************************************
     100 * PRINT_MSG_S
     101 *
     102 *  Description: This function write a message in the display.
     103 *               It is used for debugging and all the calls must be deleted
     104 *               when the tests finish
     105 * ***************************************************************************/
     106
     107static void PRINT_MSG_S ( char *msg )
     108{
     109
     110#ifdef DEBUG_MESSAGES
     111   printf("%s\n", msg);
     112#endif
     113
     114}
     115
     116/* ***************************************************************************
     117 * PRINT_ERRNO_S
     118 *
     119 *  Description: Print the value of the global variable errno in the display
     120 * ***************************************************************************/
     121
     122static void PRINT_ERRNO_S ()
     123{
     124#ifdef DEBUG_MESSAGES
     125  switch (errno)
     126  {
     127     case EINVAL:
     128       PRINT_MSG_S ( "errno EINVAL"); break;
     129     case EPERM:
     130       PRINT_MSG_S ( "errno EPERM"); break;
     131     case ESRCH:
     132       PRINT_MSG_S ( "errno ESRCH"); break;
     133     case EAGAIN:
     134       PRINT_MSG_S ( "errno EAGAIN"); break;
     135     default :
     136       printf ("errno: %d\n", errno);
     137       break;
     138  }
     139#endif
     140}
     141 
     142/* ***************************************************************************
     143 * TIMER_INITIALIZE_S
     144 *
     145 *  Description: Initialize the data of a timer
     146 * ***************************************************************************/
     147
     148void TIMER_INITIALIZE_S ( int timer_pos )
     149{
     150
     151   /*
     152    * Indicates that the position in the table is free
     153    */
     154
     155    timer_struct[timer_pos].state = STATE_FREE_C;
     156
     157   /*
     158    * The initial data of timing are set with null value
     159    */
     160
     161    timer_struct[timer_pos].timer_data.it_value.tv_sec     = 0;
     162    timer_struct[timer_pos].timer_data.it_value.tv_nsec    = 0;
     163    timer_struct[timer_pos].timer_data.it_interval.tv_sec  = 0;
     164    timer_struct[timer_pos].timer_data.it_interval.tv_nsec = 0;
     165
     166   /*
     167    * The count of expirations is 0
     168    */
     169
     170    timer_struct[timer_pos].overrun = 0;
     171
     172}
     173
     174/* ***************************************************************************
     175 * _POSIX_Timer_Manager_initialization
     176 *
     177 *  Description: Initialize the internal structure in which the data of all
     178 *               the timers are stored
     179 * ***************************************************************************/
     180
     181void _POSIX_Timer_Manager_initialization ( int max_timers )
     182{
     183   int index;
     184
     185   timer_struct = _Workspace_Allocate_or_fatal_error(
     186      max_timers * sizeof(timer_alive_t) );
     187
     188   /*
     189    *  Initialize all the timers
     190    */
     191
     192   for (index=0; index<max_timers; index++)
     193     TIMER_INITIALIZE_S( index );
     194}
     195
     196/* ***************************************************************************
     197 * FIRST_FREE_POSITION_F
     198 *
     199 *  Description: Returns the first free position in the table of timers.
     200 *               If there is not a free position, it returns NO_MORE_TIMERS_C
     201 * ***************************************************************************/
     202
     203int FIRST_FREE_POSITION_F ()
     204{
     205   int index;
     206
     207   for (index=0; index<timer_max; index++) {
     208      if ( timer_struct[index].state == STATE_FREE_C ) {
     209         return index;
     210      }
     211   }
     212   
     213   /* The function reaches this point only if all the position are occupied */
     214
     215   return NO_MORE_TIMERS_C;
     216}
     217
     218/* ***************************************************************************
     219 * TIMER_POSITION_F
     220 *
     221 *  Description: Returns the position in the table of timers in which the
     222 *               data of the timer are stored.
     223 *               If the timer identifier does not exist, it returns
     224 *               BAD_TIMER_C
     225 * ***************************************************************************/
     226
     227int TIMER_POSITION_F ( timer_t timer_id )
     228{
     229  int index;
     230
     231  for (index=0; index<timer_max; index++ ) {
     232
     233     /* Looks for the position of the timer. The timer must exist and the
     234      * position can not be free */
     235     if ( ( timer_struct[index].timer_id == timer_id ) &&
     236          ( timer_struct[index].state != STATE_FREE_C ) ) {
     237        return index;
     238     }
     239  }
     240
     241  /* If the function reaches this point is because the timer identifier
     242   * is not correct */
     243
     244   return BAD_TIMER_C;
     245
     246}
     247
     248/* ***************************************************************************
     249 * COPY_ITIMERSPEC_S
     250 *
     251 *  Description: Does a copy of a variable of type struct itimerspec 
     252 * ***************************************************************************/
     253
     254void COPY_ITIMERSPEC_S ( const struct itimerspec *source,
     255                         struct itimerspec *target )
     256{
     257
     258   target->it_value.tv_sec     = source->it_value.tv_sec;
     259   target->it_value.tv_nsec    = source->it_value.tv_nsec;
     260   target->it_interval.tv_sec  = source->it_interval.tv_sec;
     261   target->it_interval.tv_nsec = source->it_interval.tv_nsec;
     262
     263}
     264
     265/* ***************************************************************************
     266 * ITIMERSPEC_TO_RTEMS_TIME_OF_DAY_S
     267 *
     268 *  Description: This function converts the data of a structure itimerspec
     269 *               into structure rtems_time_of_day
     270 * ***************************************************************************/
     271
     272void ITIMERSPEC_TO_RTEMS_TIME_OF_DAY_S
     273   ( const struct itimerspec *itimer, rtems_time_of_day *rtems_time )
     274{
     275   unsigned long int seconds;
     276
     277   /* The leap years and the months with 28, 29 or 31 days have not been
     278    * considerated. It will be made in the future */
     279
     280   seconds            = itimer->it_value.tv_sec;
     281
     282   rtems_time->year   = seconds / SECONDS_PER_YEAR_C;
     283   seconds            = seconds % SECONDS_PER_YEAR_C;
     284
     285   rtems_time->month  = seconds / SECONDS_PER_MONTH_C;
     286   seconds            = seconds % SECONDS_PER_MONTH_C;
     287
     288   rtems_time->day    = seconds / SECONDS_PER_DAY_C;
     289   seconds            = seconds % SECONDS_PER_DAY_C;
     290
     291   rtems_time->hour   = seconds / SECONDS_PER_HOUR_C;
     292   seconds            = seconds % SECONDS_PER_HOUR_C;
     293
     294   rtems_time->minute = seconds / SECONDS_PER_MINUTE_C;
     295   seconds            = seconds % SECONDS_PER_MINUTE_C;
     296
     297   rtems_time->second = seconds;
     298
     299   rtems_time->ticks  = ( itimer->it_value.tv_nsec * SEC_TO_TICKS_C ) /
     300                        NSEC_PER_SEC_C;
     301
     302}
     303
     304
     305/* ***************************************************************************
     306 * FIRE_TIMER_S
     307 *
     308 *  Description: This is the operation that is ran when a timer expires
     309 * ***************************************************************************/
     310
     311
     312rtems_timer_service_routine FIRE_TIMER_S (rtems_id timer, void *data)
     313{
     314  int               timer_pos;  /* Position in the table of the timer that   
     315                                 *  has expirated                            */
     316  rtems_status_code return_v;   /* Return value of rtems_timer_fire_after    */
     317  int               sig_number; /* Number of the signal to send              */
     318
     319 
     320  /* The position of the table of timers that contains the data of the
     321   * expired timer will be stored in "timer_pos". In theory a timer can not
     322   * expire if it has not been created or has been deleted */
     323
     324  PRINT_MSG_S ("FIRE_TIMER_S");
     325
     326  timer_pos = TIMER_POSITION_F(timer);
     327
     328  /* Increases the number of expiration of the timer in one unit. */
     329  timer_struct[timer_pos].overrun = timer_struct[timer_pos].overrun + 1;
     330
     331
     332  if ( ( timer_struct[timer_pos].timer_data.it_interval.tv_sec  != 0 ) ||
     333       ( timer_struct[timer_pos].timer_data.it_interval.tv_nsec != 0 ) ) {
     334
     335     /* The timer must be reprogrammed */
     336
     337     return_v = rtems_timer_fire_after ( timer,
     338                                        timer_struct[timer_pos].ticks,
     339                                        FIRE_TIMER_S,
     340                                        NULL );
     341
     342     /* Stores the time when the timer was started again */
     343
     344     return_v = rtems_clock_get ( RTEMS_CLOCK_GET_TOD,
     345                                 &timer_struct[timer_pos].time );
     346     
     347     /* The state has not to be actualized, because nothing modifies it */
     348
     349     timer_struct[timer_pos].state = STATE_CREATE_RUN_C;
     350
     351  } else {
     352     /* Indicates that the timer is stopped */
     353 
     354     timer_struct[timer_pos].state = STATE_CREATE_STOP_C;
     355
     356  }
     357
     358  /*
     359   * The sending of the signal to the process running the handling function
     360   * specified for that signal is simulated
     361   */
     362
     363  sig_number = timer_struct[timer_pos].inf.sigev_signo;
     364
     365  if( pthread_kill ( timer_struct[timer_pos].thread_id ,
     366                     timer_struct[timer_pos].inf.sigev_signo ) ) {
     367     PRINT_MSG_S ("ERROR_PTHREAD_KILL");
     368  } else {
     369     PRINT_MSG_S ("SUCCESS_PTHREAD_KILL");
     370  }
     371
     372  /*
     373   * After the signal handler returns, the count of expirations of the
     374   * timer must be set to 0.
     375   */
     376
     377  timer_struct[timer_pos].overrun = 0;
     378
     379}
     380
     381/* *********************************************************************
    17382 *  14.2.2 Create a Per-Process Timer, P1003.1b-1993, p. 264
    18  */
     383 * ********************************************************************/
     384
     385/* **************
     386 * timer_create
     387 * **************/
    19388
    20389int timer_create(
     
    24393)
    25394{
    26   return POSIX_NOT_IMPLEMENTED();
     395
     396  rtems_status_code return_v;  /* return value of the operation    */
     397  rtems_id          timer_id;  /* created timer identifier         */
     398  int               timer_pos; /* Position in the table of timers  */
     399
     400 /*
     401  * The data of the structure evp are checked in order to verify if they
     402  * are coherent.
     403  */
     404
     405  if (evp != NULL) {
     406     /* The structure has data */
     407
     408     if ( ( evp->sigev_notify != SIGEV_NONE ) &&
     409          ( evp->sigev_notify != SIGEV_SIGNAL ) ) {
     410       /* The value of the field sigev_notify is not valid */
     411
     412       return (-1);
     413
     414     }
     415  }
     416 
     417 /*
     418  * A timer is created using the primitive rtems_timer_create
     419  */
     420
     421  return_v = rtems_timer_create ( clock_id, &timer_id );
     422
     423  switch (return_v) {
     424     case RTEMS_SUCCESSFUL :
     425
     426       PRINT_MSG_S("SUCCESS: rtems create timer RTEMS_SUCCESSFUL");
     427     
     428       /*
     429        * The timer has been created properly
     430        */
     431 
     432        /* Obtains the first free position in the table of timers */
     433
     434        timer_pos = FIRST_FREE_POSITION_F();
     435
     436        if ( timer_pos == NO_MORE_TIMERS_C ) {
     437           /* There is not position for another timers in spite of RTEMS
     438            * supports it. It will necessaty to increase the structure used */
     439
     440           errno = EAGAIN;
     441
     442           return -1;
     443        }
     444
     445        /* Exit parameter */
     446
     447        *timerid  = timer_id;
     448
     449        /* The data of the created timer are stored to use them later */
     450
     451        timer_struct[timer_pos].state     = STATE_CREATE_NEW_C;
     452
     453        /* NEW VERSION*/
     454        timer_struct[timer_pos].thread_id = pthread_self ();
     455       
     456
     457        if ( evp != NULL ) {
     458
     459           timer_struct[timer_pos].inf.sigev_notify = evp->sigev_notify;
     460           timer_struct[timer_pos].inf.sigev_signo  = evp->sigev_signo;
     461           timer_struct[timer_pos].inf.sigev_value  = evp->sigev_value;
     462
     463        }
     464
     465
     466        timer_struct[timer_pos].timer_id = timer_id;
     467
     468        timer_struct[timer_pos].overrun  = 0;
     469
     470        timer_struct[timer_pos].timer_data.it_value.tv_sec     = 0;
     471        timer_struct[timer_pos].timer_data.it_value.tv_nsec    = 0;
     472        timer_struct[timer_pos].timer_data.it_interval.tv_sec  = 0;
     473        timer_struct[timer_pos].timer_data.it_interval.tv_nsec = 0;
     474
     475        return 0;
     476   
     477
     478     case RTEMS_INVALID_NAME : /* The assigned name is not valid*/
     479
     480       PRINT_MSG_S ("ERROR: rtems create timer RTEMS_INVALID_NAME");
     481
     482       errno = EINVAL;
     483
     484       return (-1);
     485
     486
     487     case RTEMS_TOO_MANY :
     488
     489       PRINT_MSG_S ("ERROR: rtems create timer RTEMS_TOO_MANY ");
     490 
     491       /* There has been created too much timers for the same process */
     492
     493       errno = EAGAIN;
     494
     495       return (-1);
     496     
     497     default :
     498
     499       /*
     500        * Does nothing. It only returns the error without assigning a value
     501        * to errno. In theory, it can not happen because the call to
     502        * rtems_timer_create can not return other different value.
     503        */
     504
     505       return (-1);
     506
     507  }
     508
     509  /*
     510   * The next sentence is used to avoid singular situations
     511   */
     512
     513  return (-1);
     514
    27515}
    28516
     
    35523)
    36524{
    37   return POSIX_NOT_IMPLEMENTED();
     525 
     526 /*
     527  * IDEA: This function must probably stop the timer first and then delete it
     528  *
     529  *       It will have to do a call to rtems_timer_cancel and then another
     530  *       call to rtems_timer_delete.
     531  *       The call to rtems_timer_delete will be probably unnecessary,
     532  *       because rtems_timer_delete stops the timer before deleting it.
     533  */
     534
     535  int               timer_pos;
     536  rtems_status_code status;
     537
     538
     539   /* First the position in the table of timers is obtained */
     540
     541   timer_pos = TIMER_POSITION_F ( timerid );
     542
     543   if ( timer_pos == BAD_TIMER_C ) {
     544      /* The timer identifier is erroneus */
     545
     546      errno = EINVAL;
     547      return -1;
     548   }
     549
     550   /* The timer is deleted */
     551
     552   status = rtems_timer_delete ( timerid );
     553
     554   if ( status == RTEMS_INVALID_ID ) {
     555      /* The timer identifier is erroneus */
     556
     557      errno = EINVAL;
     558      return -1;
     559   }
     560
     561   /* Initializes the data of the timer */
     562
     563   TIMER_INITIALIZE_S ( timer_pos );
     564
     565   return 0;
    38566}
    39567
     
    41569 *  14.2.4 Per-Process Timers, P1003.1b-1993, p. 267
    42570 */
     571
     572/* **************
     573 * timer_settime
     574 * **************/
     575
    43576
    44577int timer_settime(
     
    49582)
    50583{
    51   return POSIX_NOT_IMPLEMENTED();
    52 }
     584
     585   rtems_status_code return_v;   /* Return of the calls to RTEMS        */
     586   int               timer_pos;  /* Position of the timer in the table  */
     587   rtems_time_of_day rtems_time; /* Time in RTEMS                       */
     588
     589   /* First the position in the table of timers is obtained */
     590
     591   timer_pos = TIMER_POSITION_F ( timerid );
     592
     593   if ( timer_pos == BAD_TIMER_C ) {
     594      /* The timer identifier is erroneus */
     595
     596      errno = EINVAL;
     597      return -1;
     598   }
     599
     600   if ( value == NULL ) {
     601     /* The stucture of times of the timer is free, and then returns an
     602        error but the variable errno is not actualized */
     603
     604     /* errno = ?????? */
     605
     606     return -1;
     607   }
     608
     609   /* If the function reaches this point, then it will be necessary to do
     610    * something with the structure of times of the timer: to stop, start
     611    * or start it again */
     612
     613   /* First, it verifies if the timer must be stopped */
     614
     615   if ( value->it_value.tv_sec == 0 && value->it_value.tv_nsec == 0 ) {
     616      /* The timer is stopped */
     617
     618      return_v = rtems_timer_cancel ( timerid );
     619
     620      /* The old data of the timer are returned */
     621
     622      COPY_ITIMERSPEC_S ( &timer_struct[timer_pos].timer_data, ovalue );
     623
     624      /* The new data are set */
     625
     626      COPY_ITIMERSPEC_S ( value, &timer_struct[timer_pos].timer_data );
     627
     628      /* Indicates that the timer is created and stopped */
     629 
     630      timer_struct[timer_pos].state = STATE_CREATE_STOP_C;
     631
     632      /* Returns with success */
     633
     634      return 0;
     635   }
     636
     637   /*
     638    * If the function reaches this point, then the timer will have to be
     639    * initialized with new values: to start it or start it again
     640    */
     641 
     642   /* First, it verifies if the structure "value" is correct */
     643
     644    if ( ( value->it_value.tv_nsec > MAX_NSEC_C ) ||
     645         ( value->it_value.tv_nsec < MIN_NSEC_C ) ) {
     646       /* The number of nanoseconds is not correct */
     647
     648       errno = EINVAL;
     649
     650       return -1;
     651    }
     652
     653   /* Then, "value" must be converted from seconds and nanoseconds to clock
     654    * ticks, to use it in the calls to RTEMS */
     655
     656   /* It is also necessary to take in account if the time is absolute
     657    * or relative */
     658
     659   switch (flags) {
     660      case TIMER_ABSTIME:
     661
     662        /* The fire time is absolute:
     663         * It has to use "rtems_time_fire_when" */
     664
     665        /* First, it converts from struct itimerspec to rtems_time_of_day */
     666
     667        ITIMERSPEC_TO_RTEMS_TIME_OF_DAY_S ( value, &rtems_time );
     668
     669        return_v = rtems_timer_fire_when ( timerid, &rtems_time, FIRE_TIMER_S, NULL);
     670
     671        switch ( return_v ) {
     672           case RTEMS_SUCCESSFUL:
     673
     674              PRINT_MSG_S ("SUCCESS: timer_settime RTEMS_SUCCESSFUL");
     675
     676              /* The timer has been started and is running */
     677
     678              /* Actualizes the data of the structure and
     679               * returns the old ones in "ovalue" */
     680
     681              COPY_ITIMERSPEC_S ( &timer_struct[timer_pos].timer_data, ovalue );
     682
     683              COPY_ITIMERSPEC_S ( value, &timer_struct[timer_pos].timer_data );
     684 
     685              /* It indicates that the time is running */
     686
     687              timer_struct[timer_pos].state = STATE_CREATE_RUN_C;
     688
     689              /* Stores the time in which the timer was started again */
     690
     691              return_v = rtems_clock_get ( RTEMS_CLOCK_GET_TOD,
     692                                          &timer_struct[timer_pos].time );
     693
     694              return 0;
     695
     696              break;
     697
     698           case RTEMS_INVALID_ID:
     699
     700              PRINT_MSG_S ("ERROR: timer_settime RTEMS_INVALID_ID");
     701              break;
     702
     703           case RTEMS_NOT_DEFINED:
     704
     705              PRINT_MSG_S ("ERROR: timer_settime RTEMS_NOT_DEFINED");
     706              break;
     707
     708           case RTEMS_INVALID_CLOCK:
     709
     710              PRINT_MSG_S ("ERROR: timer_settime RTEMS_INVALID_CLOCK");
     711              break;
     712
     713           default:
     714
     715       
     716        }
     717     
     718        break;
     719
     720      case TIMER_RELATIVE_C:
     721
     722        /* The fire time is relative:
     723         * It has to use "rtems_time_fire_after" */
     724
     725        /* First, it converts from seconds and nanoseconds to ticks */
     726
     727        /* The form in which this operation is done can produce a lost
     728         * of precision of 1 second */
     729 
     730/*      This is the process to convert from nanoseconds to ticks
     731 *
     732 *      There is a tick every 10 miliseconds, then the nanoseconds are
     733 *      divided between 10**7. The result of this operation will be the
     734 *      number of ticks
     735 */
     736
     737        timer_struct[timer_pos].ticks =
     738             ( SEC_TO_TICKS_C * value->it_value.tv_sec ) +
     739             ( value->it_value.tv_nsec / ( 1000 * 1000 * 10 ) );
     740
     741        return_v = rtems_timer_fire_after ( timerid,
     742                                           timer_struct[timer_pos].ticks,
     743                                           FIRE_TIMER_S,
     744                                           NULL );
     745
     746        switch (return_v) {
     747           case RTEMS_SUCCESSFUL:
     748
     749              PRINT_MSG_S ( "SUCCESS: timer_settime RTEMS_SUCCESSFUL");
     750             
     751              /* The timer has been started and is running */
     752
     753              /* Actualizes the data of the structure and
     754               * returns the old ones in "ovalue" */
     755
     756              COPY_ITIMERSPEC_S ( &timer_struct[timer_pos].timer_data, ovalue );
     757
     758              COPY_ITIMERSPEC_S ( value, &timer_struct[timer_pos].timer_data );
     759 
     760              /* It indicates that the time is running */
     761
     762              timer_struct[timer_pos].state = STATE_CREATE_RUN_C;
     763
     764              /* Stores the time in which the timer was started again */
     765
     766              return_v = rtems_clock_get ( RTEMS_CLOCK_GET_TOD,
     767                                          &timer_struct[timer_pos].time );
     768 
     769              return 0;
     770
     771              break;
     772
     773           case RTEMS_INVALID_ID:
     774
     775              PRINT_MSG_S ( "ERROR: timer_settime RTEMS_INVALID_ID");
     776
     777              /* The timer identifier is not correct. In theory, this
     778               * situation can not occur, but the solution is easy */
     779
     780              errno = EINVAL;
     781
     782              return -1;
     783
     784              break;
     785
     786           case RTEMS_INVALID_NUMBER:
     787
     788              PRINT_MSG_S ( "ERROR: timer_settime RTEMS_INVALID_NUMBER");
     789
     790              /* In this case, RTEMS fails because the values of timing
     791               * are incorrect */
     792
     793              /*
     794               * I do not know if errno must be actualized
     795               *
     796               * errno = EINVAL;
     797               */
     798
     799              return -1;
     800
     801              break;
     802           
     803           default:
     804        }
     805
     806        break;
     807
     808      default:
     809
     810        /* It does nothing, although it will be probably necessary to
     811         * return an error */
     812
     813   }
     814
     815   /* To avoid problems */
     816
     817   return 0;
     818
     819}
     820
    53821
    54822/*
    55823 *  14.2.4 Per-Process Timers, P1003.1b-1993, p. 267
    56824 */
     825
     826/* **************
     827 * timer_gettime
     828 * **************/
    57829
    58830int timer_gettime(
     
    61833)
    62834{
    63   return POSIX_NOT_IMPLEMENTED();
     835
     836 /*
     837  * IDEA:  This function does not use functions of RTEMS to the handle
     838  *        of timers. It uses some functions for managing the time.
     839  *
     840  *        A possible form to do this is the following:
     841  *
     842  *          - When a timer is initialized, the value of the time in
     843  *            that moment is stored.
     844  *          - When this function is called, it returns the difference
     845  *            between the current time and the initialization time.
     846  */
     847 
     848  rtems_time_of_day current_time;
     849  rtems_status_code return_v;
     850  int               timer_pos;
     851  unsigned32        hours;
     852  unsigned32        minutes;
     853  unsigned32        seconds;
     854  unsigned32        ticks;
     855  unsigned32        nanosec;
     856 
     857
     858  /* Reads the current time */
     859
     860  return_v = rtems_clock_get ( RTEMS_CLOCK_GET_TOD, &current_time );
     861
     862  timer_pos = TIMER_POSITION_F ( timerid );
     863
     864  if ( timer_pos == BAD_TIMER_C ) {
     865
     866     /* The timer identifier is erroneus */ 
     867
     868     errno = EINVAL;
     869
     870     return (-1);
     871
     872  }
     873
     874  /* Calculates the difference between the start time of the timer and
     875   * the current one */
     876
     877  hours    = current_time.hour - timer_struct[timer_pos].time.hour;
     878
     879  if ( current_time.minute < timer_struct[timer_pos].time.minute ) {
     880     minutes = 60 - timer_struct[timer_pos].time.minute + current_time.minute;
     881     hours--;
     882  } else {
     883     minutes = current_time.minute - timer_struct[timer_pos].time.minute;
     884  }
     885   
     886  if ( current_time.second < timer_struct[timer_pos].time.second ) {
     887     seconds = 60 - timer_struct[timer_pos].time.second + current_time.second;
     888     minutes--;
     889  } else {
     890     seconds = current_time.second - timer_struct[timer_pos].time.second;
     891  }
     892
     893  if ( current_time.ticks < timer_struct[timer_pos].time.ticks ) {
     894     ticks = 100 - timer_struct[timer_pos].time.ticks + current_time.ticks;
     895     seconds--;
     896  } else {
     897     ticks = current_time.ticks - timer_struct[timer_pos].time.ticks;
     898  }
     899
     900  /* The time that the timer is running is calculated */
     901  seconds = hours   * 60 * 60 +
     902            minutes * 60      +
     903            seconds;
     904
     905  nanosec  = ticks * 10 *  /* msec     */
     906             1000  *       /* microsec */
     907             1000;         /* nanosec  */
     908
     909 
     910  /* Calculates the time left before the timer finishes */
     911 
     912  value->it_value.tv_sec =
     913    timer_struct[timer_pos].timer_data.it_value.tv_sec - seconds;
     914 
     915  value->it_value.tv_nsec =
     916    timer_struct[timer_pos].timer_data.it_value.tv_nsec - nanosec;
     917
     918
     919  value->it_interval.tv_sec  =
     920    timer_struct[timer_pos].timer_data.it_interval.tv_sec;
     921  value->it_interval.tv_nsec =
     922    timer_struct[timer_pos].timer_data.it_interval.tv_nsec;
     923 
     924
     925  return 0;
     926
    64927}
    65928
     
    68931 */
    69932
     933/* *****************
     934 * timer_getoverrun
     935 * *****************/
     936
    70937int timer_getoverrun(
    71938  timer_t   timerid
    72939)
    73940{
    74   return POSIX_NOT_IMPLEMENTED();
    75 }
     941
     942 /*
     943  * IDEA: This function must count the times the timer expires.
     944  *   
     945  *       The expiration of a timer must increase by one a counter.
     946  *       After the signal handler associated to the timer finishs
     947  *       its execution, FIRE_TIMER_S will have to set this counter to 0.
     948  */
     949
     950  int timer_pos; /* Position of the timer in the structure     */
     951  int overrun;   /* Overflow count                             */
     952
     953
     954  timer_pos = TIMER_POSITION_F ( timerid );
     955
     956  if ( timer_pos == BAD_TIMER_C ) {
     957     /* The timer identifier is erroneus */
     958
     959     errno = EINVAL;
     960
     961     return -1;
     962  }
     963
     964  /* The overflow count of the timer is stored in "overrun" */
     965
     966  overrun = timer_struct[timer_pos].overrun;
     967
     968  /* It is set to 0 */
     969
     970  timer_struct[timer_pos].overrun = 0;
     971
     972  return overrun;
     973
     974}
  • cpukit/sapi/include/confdefs.h

    rc30d04d7 r0747e2d  
    354354#endif
    355355
     356#ifndef CONFIGURE_MAXIMUM_POSIX_TIMERS
     357#define CONFIGURE_MAXIMUM_POSIX_TIMERS 0
     358#endif
     359
    356360#ifndef CONFIGURE_MAXIMUM_POSIX_QUEUED_SIGNALS
    357361#define CONFIGURE_MAXIMUM_POSIX_QUEUED_SIGNALS 0
     
    412416  ((_keys) * \
    413417   ( sizeof(POSIX_Keys_Control) + CONFIGURE_OBJECT_TABLE_STUFF ) )
     418
     419#define CONFIGURE_MEMORY_FOR_POSIX_TIMERS(_timers) \
     420  ((_timers) * \
     421   ( 0 ) )
    414422
    415423#define CONFIGURE_MEMORY_FOR_POSIX_QUEUED_SIGNALS(_queued_signals) \
     
    618626    CONFIGURE_MAXIMUM_ADA_TASKS + CONFIGURE_MAXIMUM_FAKE_ADA_TASKS,
    619627  CONFIGURE_MAXIMUM_POSIX_KEYS + CONFIGURE_GNAT_KEYS,
     628  CONFIGURE_MAXIMUM_POSIX_TIMERS,
    620629  CONFIGURE_MAXIMUM_POSIX_QUEUED_SIGNALS,
    621630  CONFIGURE_POSIX_INIT_THREAD_TABLE_SIZE,
  • cpukit/sapi/src/posixapi.c

    rc30d04d7 r0747e2d  
    3737#include <rtems/posix/psignal.h>
    3838#include <rtems/posix/pthread.h>
     39#include <rtems/posix/ptimer.h>
    3940#include <rtems/posix/time.h>
    4041
     
    5152  0,                             /* maximum_condition_variables */
    5253  0,                             /* maximum_keys */
     54  0,                             /* maximum_timers */
    5355  0,                             /* maximum_queued_signals */
    5456  0,                             /* number_of_initialization_threads */
     
    9193  );
    9294
     95  _POSIX_Timer_Manager_initialization ( api_configuration->maximum_timers );
    9396}
    9497
Note: See TracChangeset for help on using the changeset viewer.