mirror of
https://gitlab.rtems.org/rtems/rtos/rtems.git
synced 2025-12-05 15:15:44 +00:00
POSIX Timers submitted by Juan Zamorano Flores
<jzamora@avellano.datsi.fi.upm.es>.
This commit is contained in:
@@ -13,7 +13,7 @@ MP_PIECES_yes_V = condmp mutexmp pthreadmp
|
||||
MP_PIECES = $(MP_PIECES_$(HAS_MP)_V)
|
||||
|
||||
H_PIECES= cond config key mutex posixapi \
|
||||
priority psignal pthread seterr threadsup time
|
||||
priority psignal pthread ptimer seterr threadsup time
|
||||
#H_PIECES= cancel cond intr key mqueue mqueuemp mutex \
|
||||
# mutexmp pthread pthreadmp priority semaphore semaphoremp threadsup \
|
||||
# time
|
||||
|
||||
@@ -46,6 +46,7 @@ typedef struct {
|
||||
int maximum_mutexes;
|
||||
int maximum_condition_variables;
|
||||
int maximum_keys;
|
||||
int maximum_timers;
|
||||
int maximum_queued_signals;
|
||||
int number_of_initialization_threads;
|
||||
posix_initialization_threads_table *User_initialization_threads_table;
|
||||
|
||||
91
c/src/exec/posix/include/rtems/posix/ptimer.h
Normal file
91
c/src/exec/posix/include/rtems/posix/ptimer.h
Normal file
@@ -0,0 +1,91 @@
|
||||
/* rtems/posix/ptimer.h
|
||||
*
|
||||
* This include file contains all the private support information for
|
||||
* POSIX timers.
|
||||
*
|
||||
* COPYRIGHT (c) 1998.
|
||||
* Alfonso Escalera Pi<50>a
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.OARcorp.com/rtems/license.html.
|
||||
*
|
||||
* ptimer.h,v 1.0 1998/03/31 16:21:16
|
||||
*/
|
||||
|
||||
#ifndef __RTEMS_POSIX_TIMERS_h
|
||||
#define __RTEMS_POSIX_TIMERS_h
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <rtems/posix/config.h>
|
||||
|
||||
/*
|
||||
* _POSIX_Timers_Manager_initialization
|
||||
*
|
||||
* DESCRIPTION:
|
||||
*
|
||||
* This routine performs the initialization necessary for this manager.
|
||||
*/
|
||||
|
||||
void _POSIX_Timer_Manager_initialization ( int max_timers );
|
||||
|
||||
/*
|
||||
* 14.2.2 Create a Per-Process Timer, P1003.1b-1993, p. 264
|
||||
*
|
||||
* timer_create
|
||||
*/
|
||||
|
||||
int timer_create(
|
||||
clockid_t clock_id,
|
||||
struct sigevent *evp,
|
||||
timer_t *timerid
|
||||
);
|
||||
|
||||
/*
|
||||
* 14.2.3 Delete a Per_process Timer, P1003.1b-1993, p. 266
|
||||
*/
|
||||
|
||||
int timer_delete(
|
||||
timer_t timerid
|
||||
);
|
||||
|
||||
/*
|
||||
* 14.2.4 Per-Process Timers, P1003.1b-1993, p. 267
|
||||
*
|
||||
* timer_settime
|
||||
*/
|
||||
|
||||
int timer_settime(
|
||||
timer_t timerid,
|
||||
int flags,
|
||||
const struct itimerspec *value,
|
||||
struct itimerspec *ovalue
|
||||
);
|
||||
|
||||
/*
|
||||
* 14.2.4 Per-Process Timers, P1003.1b-1993, p. 267
|
||||
*
|
||||
* timer_gettime
|
||||
*/
|
||||
|
||||
int timer_gettime(
|
||||
timer_t timerid,
|
||||
struct itimerspec *value
|
||||
);
|
||||
|
||||
/*
|
||||
* 14.2.4 Per-Process Timers, P1003.1b-1993, p. 267
|
||||
*
|
||||
* timer_getoverrun
|
||||
*
|
||||
*/
|
||||
|
||||
int timer_getoverrun(
|
||||
timer_t timerid
|
||||
);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -9,7 +9,7 @@ RTEMS_ROOT = @top_srcdir@
|
||||
PROJECT_ROOT = @PROJECT_ROOT@
|
||||
|
||||
# following are semi-implemented and untested
|
||||
# C_PIECES=aio cancel devctl intr mqueue ptimer semaphore time utsname
|
||||
# C_PIECES=aio cancel devctl intr mqueue semaphore time utsname
|
||||
|
||||
ENOSYS_C_PIECES=\
|
||||
execl execle execlp execv execve execvp fork \
|
||||
@@ -36,7 +36,7 @@ PSIGNAL_PIECES=\
|
||||
sigwaitinfo
|
||||
|
||||
C_PIECES= adasupp cond getpid key mutex $(PTHREAD_PIECES) \
|
||||
$(PSIGNAL_PIECES) sched time \
|
||||
$(PSIGNAL_PIECES) ptimer sched time \
|
||||
types unistd $(ENOSYS_C_PIECES)
|
||||
|
||||
C_FILES=$(C_PIECES:%=%.c)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ptimer.c,v 1.1 1996/06/03 16:29:58 joel Exp
|
||||
*/
|
||||
|
||||
|
||||
#include <assert.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
@@ -13,17 +13,505 @@
|
||||
|
||||
#include <rtems/posix/time.h>
|
||||
|
||||
/************************************/
|
||||
/* These includes are now necessary */
|
||||
/************************************/
|
||||
|
||||
#include <sys/features.h>
|
||||
#include <rtems/rtems/status.h>
|
||||
#include <rtems/rtems/types.h>
|
||||
#include <rtems/rtems/timer.h>
|
||||
#include <rtems/rtems/clock.h>
|
||||
#include <rtems/posix/psignal.h>
|
||||
#include <rtems/score/wkspace.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
|
||||
/*****************************/
|
||||
/* End of necessary includes */
|
||||
/*****************************/
|
||||
|
||||
/* ************
|
||||
* Constants
|
||||
* ************/
|
||||
|
||||
#define STATE_FREE_C 0x01 /* Free position of the table of timers */
|
||||
#define STATE_CREATE_NEW_C 0x02 /* Created timer but not running */
|
||||
#define STATE_CREATE_RUN_C 0x03 /* Created timer and running */
|
||||
#define STATE_CREATE_STOP_C 0x04 /* Created, ran and stopped timer */
|
||||
#define MAX_NSEC_C 1000000000 /* Maximum number of nsec allowed */
|
||||
#define MIN_NSEC_C 0 /* Minimum number of nsec allowew */
|
||||
#define TIMER_RELATIVE_C 0 /* Indicates that the fire time is
|
||||
* relative to the current one */
|
||||
#define SEC_TO_TICKS_C _TOD_Ticks_per_second /* Number of ticks in a second*/
|
||||
#define NSEC_PER_SEC_C 1000000000 /* Nanoseconds in a second */
|
||||
|
||||
#define NO_MORE_TIMERS_C 11 /* There is not available timers */
|
||||
#define BAD_TIMER_C 11 /* The timer does not exist in the table */
|
||||
|
||||
#define SECONDS_PER_YEAR_C ( 360 * 24 * 60 * 60 )
|
||||
#define SECONDS_PER_MONTH_C ( 30 * 24 * 60 * 60 )
|
||||
#define SECONDS_PER_DAY_C ( 24 * 60 * 60 )
|
||||
#define SECONDS_PER_HOUR_C ( 60 * 60 )
|
||||
#define SECONDS_PER_MINUTE_C ( 60 )
|
||||
|
||||
/*
|
||||
* 14.2.2 Create a Per-Process Timer, P1003.1b-1993, p. 264
|
||||
#define DEBUG_MESSAGES
|
||||
*/
|
||||
|
||||
/* *********************************************************
|
||||
* Types that will store the created timers and their data
|
||||
* *********************************************************/
|
||||
|
||||
/*
|
||||
* Data for a timer
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
pthread_t thread_id; /* Thread identifier */
|
||||
char state; /* State of the timer */
|
||||
struct sigevent inf; /* Information associated to the timer */
|
||||
timer_t timer_id; /* Created timer identifier */
|
||||
struct itimerspec timer_data; /* Timing data of the timer */
|
||||
unsigned32 ticks; /* Number of ticks of the initialization */
|
||||
unsigned32 overrun; /* Number of expirations of the timer */
|
||||
rtems_time_of_day time; /* Time in which the timer was started */
|
||||
} timer_alive_t;
|
||||
|
||||
/*
|
||||
* Array of Timers
|
||||
*/
|
||||
|
||||
int timer_max;
|
||||
timer_alive_t *timer_struct;
|
||||
|
||||
/*
|
||||
* Data for the signals
|
||||
*/
|
||||
|
||||
struct sigaction signal_inf[SIGRTMAX];
|
||||
|
||||
/***********************************
|
||||
* Definition of Internal Functions
|
||||
***********************************/
|
||||
|
||||
/* ***************************************************************************
|
||||
* PRINT_MSG_S
|
||||
*
|
||||
* Description: This function write a message in the display.
|
||||
* It is used for debugging and all the calls must be deleted
|
||||
* when the tests finish
|
||||
* ***************************************************************************/
|
||||
|
||||
static void PRINT_MSG_S ( char *msg )
|
||||
{
|
||||
|
||||
#ifdef DEBUG_MESSAGES
|
||||
printf("%s\n", msg);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/* ***************************************************************************
|
||||
* PRINT_ERRNO_S
|
||||
*
|
||||
* Description: Print the value of the global variable errno in the display
|
||||
* ***************************************************************************/
|
||||
|
||||
static void PRINT_ERRNO_S ()
|
||||
{
|
||||
#ifdef DEBUG_MESSAGES
|
||||
switch (errno)
|
||||
{
|
||||
case EINVAL:
|
||||
PRINT_MSG_S ( "errno EINVAL"); break;
|
||||
case EPERM:
|
||||
PRINT_MSG_S ( "errno EPERM"); break;
|
||||
case ESRCH:
|
||||
PRINT_MSG_S ( "errno ESRCH"); break;
|
||||
case EAGAIN:
|
||||
PRINT_MSG_S ( "errno EAGAIN"); break;
|
||||
default :
|
||||
printf ("errno: %d\n", errno);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* ***************************************************************************
|
||||
* TIMER_INITIALIZE_S
|
||||
*
|
||||
* Description: Initialize the data of a timer
|
||||
* ***************************************************************************/
|
||||
|
||||
void TIMER_INITIALIZE_S ( int timer_pos )
|
||||
{
|
||||
|
||||
/*
|
||||
* Indicates that the position in the table is free
|
||||
*/
|
||||
|
||||
timer_struct[timer_pos].state = STATE_FREE_C;
|
||||
|
||||
/*
|
||||
* The initial data of timing are set with null value
|
||||
*/
|
||||
|
||||
timer_struct[timer_pos].timer_data.it_value.tv_sec = 0;
|
||||
timer_struct[timer_pos].timer_data.it_value.tv_nsec = 0;
|
||||
timer_struct[timer_pos].timer_data.it_interval.tv_sec = 0;
|
||||
timer_struct[timer_pos].timer_data.it_interval.tv_nsec = 0;
|
||||
|
||||
/*
|
||||
* The count of expirations is 0
|
||||
*/
|
||||
|
||||
timer_struct[timer_pos].overrun = 0;
|
||||
|
||||
}
|
||||
|
||||
/* ***************************************************************************
|
||||
* _POSIX_Timer_Manager_initialization
|
||||
*
|
||||
* Description: Initialize the internal structure in which the data of all
|
||||
* the timers are stored
|
||||
* ***************************************************************************/
|
||||
|
||||
void _POSIX_Timer_Manager_initialization ( int max_timers )
|
||||
{
|
||||
int index;
|
||||
|
||||
timer_struct = _Workspace_Allocate_or_fatal_error(
|
||||
max_timers * sizeof(timer_alive_t) );
|
||||
|
||||
/*
|
||||
* Initialize all the timers
|
||||
*/
|
||||
|
||||
for (index=0; index<max_timers; index++)
|
||||
TIMER_INITIALIZE_S( index );
|
||||
}
|
||||
|
||||
/* ***************************************************************************
|
||||
* FIRST_FREE_POSITION_F
|
||||
*
|
||||
* Description: Returns the first free position in the table of timers.
|
||||
* If there is not a free position, it returns NO_MORE_TIMERS_C
|
||||
* ***************************************************************************/
|
||||
|
||||
int FIRST_FREE_POSITION_F ()
|
||||
{
|
||||
int index;
|
||||
|
||||
for (index=0; index<timer_max; index++) {
|
||||
if ( timer_struct[index].state == STATE_FREE_C ) {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
||||
/* The function reaches this point only if all the position are occupied */
|
||||
|
||||
return NO_MORE_TIMERS_C;
|
||||
}
|
||||
|
||||
/* ***************************************************************************
|
||||
* TIMER_POSITION_F
|
||||
*
|
||||
* Description: Returns the position in the table of timers in which the
|
||||
* data of the timer are stored.
|
||||
* If the timer identifier does not exist, it returns
|
||||
* BAD_TIMER_C
|
||||
* ***************************************************************************/
|
||||
|
||||
int TIMER_POSITION_F ( timer_t timer_id )
|
||||
{
|
||||
int index;
|
||||
|
||||
for (index=0; index<timer_max; index++ ) {
|
||||
|
||||
/* Looks for the position of the timer. The timer must exist and the
|
||||
* position can not be free */
|
||||
if ( ( timer_struct[index].timer_id == timer_id ) &&
|
||||
( timer_struct[index].state != STATE_FREE_C ) ) {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
||||
/* If the function reaches this point is because the timer identifier
|
||||
* is not correct */
|
||||
|
||||
return BAD_TIMER_C;
|
||||
|
||||
}
|
||||
|
||||
/* ***************************************************************************
|
||||
* COPY_ITIMERSPEC_S
|
||||
*
|
||||
* Description: Does a copy of a variable of type struct itimerspec
|
||||
* ***************************************************************************/
|
||||
|
||||
void COPY_ITIMERSPEC_S ( const struct itimerspec *source,
|
||||
struct itimerspec *target )
|
||||
{
|
||||
|
||||
target->it_value.tv_sec = source->it_value.tv_sec;
|
||||
target->it_value.tv_nsec = source->it_value.tv_nsec;
|
||||
target->it_interval.tv_sec = source->it_interval.tv_sec;
|
||||
target->it_interval.tv_nsec = source->it_interval.tv_nsec;
|
||||
|
||||
}
|
||||
|
||||
/* ***************************************************************************
|
||||
* ITIMERSPEC_TO_RTEMS_TIME_OF_DAY_S
|
||||
*
|
||||
* Description: This function converts the data of a structure itimerspec
|
||||
* into structure rtems_time_of_day
|
||||
* ***************************************************************************/
|
||||
|
||||
void ITIMERSPEC_TO_RTEMS_TIME_OF_DAY_S
|
||||
( const struct itimerspec *itimer, rtems_time_of_day *rtems_time )
|
||||
{
|
||||
unsigned long int seconds;
|
||||
|
||||
/* The leap years and the months with 28, 29 or 31 days have not been
|
||||
* considerated. It will be made in the future */
|
||||
|
||||
seconds = itimer->it_value.tv_sec;
|
||||
|
||||
rtems_time->year = seconds / SECONDS_PER_YEAR_C;
|
||||
seconds = seconds % SECONDS_PER_YEAR_C;
|
||||
|
||||
rtems_time->month = seconds / SECONDS_PER_MONTH_C;
|
||||
seconds = seconds % SECONDS_PER_MONTH_C;
|
||||
|
||||
rtems_time->day = seconds / SECONDS_PER_DAY_C;
|
||||
seconds = seconds % SECONDS_PER_DAY_C;
|
||||
|
||||
rtems_time->hour = seconds / SECONDS_PER_HOUR_C;
|
||||
seconds = seconds % SECONDS_PER_HOUR_C;
|
||||
|
||||
rtems_time->minute = seconds / SECONDS_PER_MINUTE_C;
|
||||
seconds = seconds % SECONDS_PER_MINUTE_C;
|
||||
|
||||
rtems_time->second = seconds;
|
||||
|
||||
rtems_time->ticks = ( itimer->it_value.tv_nsec * SEC_TO_TICKS_C ) /
|
||||
NSEC_PER_SEC_C;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* ***************************************************************************
|
||||
* FIRE_TIMER_S
|
||||
*
|
||||
* Description: This is the operation that is ran when a timer expires
|
||||
* ***************************************************************************/
|
||||
|
||||
|
||||
rtems_timer_service_routine FIRE_TIMER_S (rtems_id timer, void *data)
|
||||
{
|
||||
int timer_pos; /* Position in the table of the timer that
|
||||
* has expirated */
|
||||
rtems_status_code return_v; /* Return value of rtems_timer_fire_after */
|
||||
int sig_number; /* Number of the signal to send */
|
||||
|
||||
|
||||
/* The position of the table of timers that contains the data of the
|
||||
* expired timer will be stored in "timer_pos". In theory a timer can not
|
||||
* expire if it has not been created or has been deleted */
|
||||
|
||||
PRINT_MSG_S ("FIRE_TIMER_S");
|
||||
|
||||
timer_pos = TIMER_POSITION_F(timer);
|
||||
|
||||
/* Increases the number of expiration of the timer in one unit. */
|
||||
timer_struct[timer_pos].overrun = timer_struct[timer_pos].overrun + 1;
|
||||
|
||||
|
||||
if ( ( timer_struct[timer_pos].timer_data.it_interval.tv_sec != 0 ) ||
|
||||
( timer_struct[timer_pos].timer_data.it_interval.tv_nsec != 0 ) ) {
|
||||
|
||||
/* The timer must be reprogrammed */
|
||||
|
||||
return_v = rtems_timer_fire_after ( timer,
|
||||
timer_struct[timer_pos].ticks,
|
||||
FIRE_TIMER_S,
|
||||
NULL );
|
||||
|
||||
/* Stores the time when the timer was started again */
|
||||
|
||||
return_v = rtems_clock_get ( RTEMS_CLOCK_GET_TOD,
|
||||
&timer_struct[timer_pos].time );
|
||||
|
||||
/* The state has not to be actualized, because nothing modifies it */
|
||||
|
||||
timer_struct[timer_pos].state = STATE_CREATE_RUN_C;
|
||||
|
||||
} else {
|
||||
/* Indicates that the timer is stopped */
|
||||
|
||||
timer_struct[timer_pos].state = STATE_CREATE_STOP_C;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* The sending of the signal to the process running the handling function
|
||||
* specified for that signal is simulated
|
||||
*/
|
||||
|
||||
sig_number = timer_struct[timer_pos].inf.sigev_signo;
|
||||
|
||||
if( pthread_kill ( timer_struct[timer_pos].thread_id ,
|
||||
timer_struct[timer_pos].inf.sigev_signo ) ) {
|
||||
PRINT_MSG_S ("ERROR_PTHREAD_KILL");
|
||||
} else {
|
||||
PRINT_MSG_S ("SUCCESS_PTHREAD_KILL");
|
||||
}
|
||||
|
||||
/*
|
||||
* After the signal handler returns, the count of expirations of the
|
||||
* timer must be set to 0.
|
||||
*/
|
||||
|
||||
timer_struct[timer_pos].overrun = 0;
|
||||
|
||||
}
|
||||
|
||||
/* *********************************************************************
|
||||
* 14.2.2 Create a Per-Process Timer, P1003.1b-1993, p. 264
|
||||
* ********************************************************************/
|
||||
|
||||
/* **************
|
||||
* timer_create
|
||||
* **************/
|
||||
|
||||
int timer_create(
|
||||
clockid_t clock_id,
|
||||
struct sigevent *evp,
|
||||
timer_t *timerid
|
||||
)
|
||||
{
|
||||
return POSIX_NOT_IMPLEMENTED();
|
||||
|
||||
rtems_status_code return_v; /* return value of the operation */
|
||||
rtems_id timer_id; /* created timer identifier */
|
||||
int timer_pos; /* Position in the table of timers */
|
||||
|
||||
/*
|
||||
* The data of the structure evp are checked in order to verify if they
|
||||
* are coherent.
|
||||
*/
|
||||
|
||||
if (evp != NULL) {
|
||||
/* The structure has data */
|
||||
|
||||
if ( ( evp->sigev_notify != SIGEV_NONE ) &&
|
||||
( evp->sigev_notify != SIGEV_SIGNAL ) ) {
|
||||
/* The value of the field sigev_notify is not valid */
|
||||
|
||||
return (-1);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* A timer is created using the primitive rtems_timer_create
|
||||
*/
|
||||
|
||||
return_v = rtems_timer_create ( clock_id, &timer_id );
|
||||
|
||||
switch (return_v) {
|
||||
case RTEMS_SUCCESSFUL :
|
||||
|
||||
PRINT_MSG_S("SUCCESS: rtems create timer RTEMS_SUCCESSFUL");
|
||||
|
||||
/*
|
||||
* The timer has been created properly
|
||||
*/
|
||||
|
||||
/* Obtains the first free position in the table of timers */
|
||||
|
||||
timer_pos = FIRST_FREE_POSITION_F();
|
||||
|
||||
if ( timer_pos == NO_MORE_TIMERS_C ) {
|
||||
/* There is not position for another timers in spite of RTEMS
|
||||
* supports it. It will necessaty to increase the structure used */
|
||||
|
||||
errno = EAGAIN;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Exit parameter */
|
||||
|
||||
*timerid = timer_id;
|
||||
|
||||
/* The data of the created timer are stored to use them later */
|
||||
|
||||
timer_struct[timer_pos].state = STATE_CREATE_NEW_C;
|
||||
|
||||
/* NEW VERSION*/
|
||||
timer_struct[timer_pos].thread_id = pthread_self ();
|
||||
|
||||
|
||||
if ( evp != NULL ) {
|
||||
|
||||
timer_struct[timer_pos].inf.sigev_notify = evp->sigev_notify;
|
||||
timer_struct[timer_pos].inf.sigev_signo = evp->sigev_signo;
|
||||
timer_struct[timer_pos].inf.sigev_value = evp->sigev_value;
|
||||
|
||||
}
|
||||
|
||||
|
||||
timer_struct[timer_pos].timer_id = timer_id;
|
||||
|
||||
timer_struct[timer_pos].overrun = 0;
|
||||
|
||||
timer_struct[timer_pos].timer_data.it_value.tv_sec = 0;
|
||||
timer_struct[timer_pos].timer_data.it_value.tv_nsec = 0;
|
||||
timer_struct[timer_pos].timer_data.it_interval.tv_sec = 0;
|
||||
timer_struct[timer_pos].timer_data.it_interval.tv_nsec = 0;
|
||||
|
||||
return 0;
|
||||
|
||||
|
||||
case RTEMS_INVALID_NAME : /* The assigned name is not valid*/
|
||||
|
||||
PRINT_MSG_S ("ERROR: rtems create timer RTEMS_INVALID_NAME");
|
||||
|
||||
errno = EINVAL;
|
||||
|
||||
return (-1);
|
||||
|
||||
|
||||
case RTEMS_TOO_MANY :
|
||||
|
||||
PRINT_MSG_S ("ERROR: rtems create timer RTEMS_TOO_MANY ");
|
||||
|
||||
/* There has been created too much timers for the same process */
|
||||
|
||||
errno = EAGAIN;
|
||||
|
||||
return (-1);
|
||||
|
||||
default :
|
||||
|
||||
/*
|
||||
* Does nothing. It only returns the error without assigning a value
|
||||
* to errno. In theory, it can not happen because the call to
|
||||
* rtems_timer_create can not return other different value.
|
||||
*/
|
||||
|
||||
return (-1);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* The next sentence is used to avoid singular situations
|
||||
*/
|
||||
|
||||
return (-1);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -34,13 +522,58 @@ int timer_delete(
|
||||
timer_t timerid
|
||||
)
|
||||
{
|
||||
return POSIX_NOT_IMPLEMENTED();
|
||||
|
||||
/*
|
||||
* IDEA: This function must probably stop the timer first and then delete it
|
||||
*
|
||||
* It will have to do a call to rtems_timer_cancel and then another
|
||||
* call to rtems_timer_delete.
|
||||
* The call to rtems_timer_delete will be probably unnecessary,
|
||||
* because rtems_timer_delete stops the timer before deleting it.
|
||||
*/
|
||||
|
||||
int timer_pos;
|
||||
rtems_status_code status;
|
||||
|
||||
|
||||
/* First the position in the table of timers is obtained */
|
||||
|
||||
timer_pos = TIMER_POSITION_F ( timerid );
|
||||
|
||||
if ( timer_pos == BAD_TIMER_C ) {
|
||||
/* The timer identifier is erroneus */
|
||||
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* The timer is deleted */
|
||||
|
||||
status = rtems_timer_delete ( timerid );
|
||||
|
||||
if ( status == RTEMS_INVALID_ID ) {
|
||||
/* The timer identifier is erroneus */
|
||||
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Initializes the data of the timer */
|
||||
|
||||
TIMER_INITIALIZE_S ( timer_pos );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* 14.2.4 Per-Process Timers, P1003.1b-1993, p. 267
|
||||
*/
|
||||
|
||||
/* **************
|
||||
* timer_settime
|
||||
* **************/
|
||||
|
||||
|
||||
int timer_settime(
|
||||
timer_t timerid,
|
||||
int flags,
|
||||
@@ -48,28 +581,394 @@ int timer_settime(
|
||||
struct itimerspec *ovalue
|
||||
)
|
||||
{
|
||||
return POSIX_NOT_IMPLEMENTED();
|
||||
|
||||
rtems_status_code return_v; /* Return of the calls to RTEMS */
|
||||
int timer_pos; /* Position of the timer in the table */
|
||||
rtems_time_of_day rtems_time; /* Time in RTEMS */
|
||||
|
||||
/* First the position in the table of timers is obtained */
|
||||
|
||||
timer_pos = TIMER_POSITION_F ( timerid );
|
||||
|
||||
if ( timer_pos == BAD_TIMER_C ) {
|
||||
/* The timer identifier is erroneus */
|
||||
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( value == NULL ) {
|
||||
/* The stucture of times of the timer is free, and then returns an
|
||||
error but the variable errno is not actualized */
|
||||
|
||||
/* errno = ?????? */
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* If the function reaches this point, then it will be necessary to do
|
||||
* something with the structure of times of the timer: to stop, start
|
||||
* or start it again */
|
||||
|
||||
/* First, it verifies if the timer must be stopped */
|
||||
|
||||
if ( value->it_value.tv_sec == 0 && value->it_value.tv_nsec == 0 ) {
|
||||
/* The timer is stopped */
|
||||
|
||||
return_v = rtems_timer_cancel ( timerid );
|
||||
|
||||
/* The old data of the timer are returned */
|
||||
|
||||
COPY_ITIMERSPEC_S ( &timer_struct[timer_pos].timer_data, ovalue );
|
||||
|
||||
/* The new data are set */
|
||||
|
||||
COPY_ITIMERSPEC_S ( value, &timer_struct[timer_pos].timer_data );
|
||||
|
||||
/* Indicates that the timer is created and stopped */
|
||||
|
||||
timer_struct[timer_pos].state = STATE_CREATE_STOP_C;
|
||||
|
||||
/* Returns with success */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the function reaches this point, then the timer will have to be
|
||||
* initialized with new values: to start it or start it again
|
||||
*/
|
||||
|
||||
/* First, it verifies if the structure "value" is correct */
|
||||
|
||||
if ( ( value->it_value.tv_nsec > MAX_NSEC_C ) ||
|
||||
( value->it_value.tv_nsec < MIN_NSEC_C ) ) {
|
||||
/* The number of nanoseconds is not correct */
|
||||
|
||||
errno = EINVAL;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Then, "value" must be converted from seconds and nanoseconds to clock
|
||||
* ticks, to use it in the calls to RTEMS */
|
||||
|
||||
/* It is also necessary to take in account if the time is absolute
|
||||
* or relative */
|
||||
|
||||
switch (flags) {
|
||||
case TIMER_ABSTIME:
|
||||
|
||||
/* The fire time is absolute:
|
||||
* It has to use "rtems_time_fire_when" */
|
||||
|
||||
/* First, it converts from struct itimerspec to rtems_time_of_day */
|
||||
|
||||
ITIMERSPEC_TO_RTEMS_TIME_OF_DAY_S ( value, &rtems_time );
|
||||
|
||||
return_v = rtems_timer_fire_when ( timerid, &rtems_time, FIRE_TIMER_S, NULL);
|
||||
|
||||
switch ( return_v ) {
|
||||
case RTEMS_SUCCESSFUL:
|
||||
|
||||
PRINT_MSG_S ("SUCCESS: timer_settime RTEMS_SUCCESSFUL");
|
||||
|
||||
/* The timer has been started and is running */
|
||||
|
||||
/* Actualizes the data of the structure and
|
||||
* returns the old ones in "ovalue" */
|
||||
|
||||
COPY_ITIMERSPEC_S ( &timer_struct[timer_pos].timer_data, ovalue );
|
||||
|
||||
COPY_ITIMERSPEC_S ( value, &timer_struct[timer_pos].timer_data );
|
||||
|
||||
/* It indicates that the time is running */
|
||||
|
||||
timer_struct[timer_pos].state = STATE_CREATE_RUN_C;
|
||||
|
||||
/* Stores the time in which the timer was started again */
|
||||
|
||||
return_v = rtems_clock_get ( RTEMS_CLOCK_GET_TOD,
|
||||
&timer_struct[timer_pos].time );
|
||||
|
||||
return 0;
|
||||
|
||||
break;
|
||||
|
||||
case RTEMS_INVALID_ID:
|
||||
|
||||
PRINT_MSG_S ("ERROR: timer_settime RTEMS_INVALID_ID");
|
||||
break;
|
||||
|
||||
case RTEMS_NOT_DEFINED:
|
||||
|
||||
PRINT_MSG_S ("ERROR: timer_settime RTEMS_NOT_DEFINED");
|
||||
break;
|
||||
|
||||
case RTEMS_INVALID_CLOCK:
|
||||
|
||||
PRINT_MSG_S ("ERROR: timer_settime RTEMS_INVALID_CLOCK");
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case TIMER_RELATIVE_C:
|
||||
|
||||
/* The fire time is relative:
|
||||
* It has to use "rtems_time_fire_after" */
|
||||
|
||||
/* First, it converts from seconds and nanoseconds to ticks */
|
||||
|
||||
/* The form in which this operation is done can produce a lost
|
||||
* of precision of 1 second */
|
||||
|
||||
/* This is the process to convert from nanoseconds to ticks
|
||||
*
|
||||
* There is a tick every 10 miliseconds, then the nanoseconds are
|
||||
* divided between 10**7. The result of this operation will be the
|
||||
* number of ticks
|
||||
*/
|
||||
|
||||
timer_struct[timer_pos].ticks =
|
||||
( SEC_TO_TICKS_C * value->it_value.tv_sec ) +
|
||||
( value->it_value.tv_nsec / ( 1000 * 1000 * 10 ) );
|
||||
|
||||
return_v = rtems_timer_fire_after ( timerid,
|
||||
timer_struct[timer_pos].ticks,
|
||||
FIRE_TIMER_S,
|
||||
NULL );
|
||||
|
||||
switch (return_v) {
|
||||
case RTEMS_SUCCESSFUL:
|
||||
|
||||
PRINT_MSG_S ( "SUCCESS: timer_settime RTEMS_SUCCESSFUL");
|
||||
|
||||
/* The timer has been started and is running */
|
||||
|
||||
/* Actualizes the data of the structure and
|
||||
* returns the old ones in "ovalue" */
|
||||
|
||||
COPY_ITIMERSPEC_S ( &timer_struct[timer_pos].timer_data, ovalue );
|
||||
|
||||
COPY_ITIMERSPEC_S ( value, &timer_struct[timer_pos].timer_data );
|
||||
|
||||
/* It indicates that the time is running */
|
||||
|
||||
timer_struct[timer_pos].state = STATE_CREATE_RUN_C;
|
||||
|
||||
/* Stores the time in which the timer was started again */
|
||||
|
||||
return_v = rtems_clock_get ( RTEMS_CLOCK_GET_TOD,
|
||||
&timer_struct[timer_pos].time );
|
||||
|
||||
return 0;
|
||||
|
||||
break;
|
||||
|
||||
case RTEMS_INVALID_ID:
|
||||
|
||||
PRINT_MSG_S ( "ERROR: timer_settime RTEMS_INVALID_ID");
|
||||
|
||||
/* The timer identifier is not correct. In theory, this
|
||||
* situation can not occur, but the solution is easy */
|
||||
|
||||
errno = EINVAL;
|
||||
|
||||
return -1;
|
||||
|
||||
break;
|
||||
|
||||
case RTEMS_INVALID_NUMBER:
|
||||
|
||||
PRINT_MSG_S ( "ERROR: timer_settime RTEMS_INVALID_NUMBER");
|
||||
|
||||
/* In this case, RTEMS fails because the values of timing
|
||||
* are incorrect */
|
||||
|
||||
/*
|
||||
* I do not know if errno must be actualized
|
||||
*
|
||||
* errno = EINVAL;
|
||||
*/
|
||||
|
||||
return -1;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
/* It does nothing, although it will be probably necessary to
|
||||
* return an error */
|
||||
|
||||
}
|
||||
|
||||
/* To avoid problems */
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 14.2.4 Per-Process Timers, P1003.1b-1993, p. 267
|
||||
*/
|
||||
|
||||
/* **************
|
||||
* timer_gettime
|
||||
* **************/
|
||||
|
||||
int timer_gettime(
|
||||
timer_t timerid,
|
||||
struct itimerspec *value
|
||||
)
|
||||
{
|
||||
return POSIX_NOT_IMPLEMENTED();
|
||||
|
||||
/*
|
||||
* IDEA: This function does not use functions of RTEMS to the handle
|
||||
* of timers. It uses some functions for managing the time.
|
||||
*
|
||||
* A possible form to do this is the following:
|
||||
*
|
||||
* - When a timer is initialized, the value of the time in
|
||||
* that moment is stored.
|
||||
* - When this function is called, it returns the difference
|
||||
* between the current time and the initialization time.
|
||||
*/
|
||||
|
||||
rtems_time_of_day current_time;
|
||||
rtems_status_code return_v;
|
||||
int timer_pos;
|
||||
unsigned32 hours;
|
||||
unsigned32 minutes;
|
||||
unsigned32 seconds;
|
||||
unsigned32 ticks;
|
||||
unsigned32 nanosec;
|
||||
|
||||
|
||||
/* Reads the current time */
|
||||
|
||||
return_v = rtems_clock_get ( RTEMS_CLOCK_GET_TOD, ¤t_time );
|
||||
|
||||
timer_pos = TIMER_POSITION_F ( timerid );
|
||||
|
||||
if ( timer_pos == BAD_TIMER_C ) {
|
||||
|
||||
/* The timer identifier is erroneus */
|
||||
|
||||
errno = EINVAL;
|
||||
|
||||
return (-1);
|
||||
|
||||
}
|
||||
|
||||
/* Calculates the difference between the start time of the timer and
|
||||
* the current one */
|
||||
|
||||
hours = current_time.hour - timer_struct[timer_pos].time.hour;
|
||||
|
||||
if ( current_time.minute < timer_struct[timer_pos].time.minute ) {
|
||||
minutes = 60 - timer_struct[timer_pos].time.minute + current_time.minute;
|
||||
hours--;
|
||||
} else {
|
||||
minutes = current_time.minute - timer_struct[timer_pos].time.minute;
|
||||
}
|
||||
|
||||
if ( current_time.second < timer_struct[timer_pos].time.second ) {
|
||||
seconds = 60 - timer_struct[timer_pos].time.second + current_time.second;
|
||||
minutes--;
|
||||
} else {
|
||||
seconds = current_time.second - timer_struct[timer_pos].time.second;
|
||||
}
|
||||
|
||||
if ( current_time.ticks < timer_struct[timer_pos].time.ticks ) {
|
||||
ticks = 100 - timer_struct[timer_pos].time.ticks + current_time.ticks;
|
||||
seconds--;
|
||||
} else {
|
||||
ticks = current_time.ticks - timer_struct[timer_pos].time.ticks;
|
||||
}
|
||||
|
||||
/* The time that the timer is running is calculated */
|
||||
seconds = hours * 60 * 60 +
|
||||
minutes * 60 +
|
||||
seconds;
|
||||
|
||||
nanosec = ticks * 10 * /* msec */
|
||||
1000 * /* microsec */
|
||||
1000; /* nanosec */
|
||||
|
||||
|
||||
/* Calculates the time left before the timer finishes */
|
||||
|
||||
value->it_value.tv_sec =
|
||||
timer_struct[timer_pos].timer_data.it_value.tv_sec - seconds;
|
||||
|
||||
value->it_value.tv_nsec =
|
||||
timer_struct[timer_pos].timer_data.it_value.tv_nsec - nanosec;
|
||||
|
||||
|
||||
value->it_interval.tv_sec =
|
||||
timer_struct[timer_pos].timer_data.it_interval.tv_sec;
|
||||
value->it_interval.tv_nsec =
|
||||
timer_struct[timer_pos].timer_data.it_interval.tv_nsec;
|
||||
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* 14.2.4 Per-Process Timers, P1003.1b-1993, p. 267
|
||||
*/
|
||||
|
||||
/* *****************
|
||||
* timer_getoverrun
|
||||
* *****************/
|
||||
|
||||
int timer_getoverrun(
|
||||
timer_t timerid
|
||||
)
|
||||
{
|
||||
return POSIX_NOT_IMPLEMENTED();
|
||||
|
||||
/*
|
||||
* IDEA: This function must count the times the timer expires.
|
||||
*
|
||||
* The expiration of a timer must increase by one a counter.
|
||||
* After the signal handler associated to the timer finishs
|
||||
* its execution, FIRE_TIMER_S will have to set this counter to 0.
|
||||
*/
|
||||
|
||||
int timer_pos; /* Position of the timer in the structure */
|
||||
int overrun; /* Overflow count */
|
||||
|
||||
|
||||
timer_pos = TIMER_POSITION_F ( timerid );
|
||||
|
||||
if ( timer_pos == BAD_TIMER_C ) {
|
||||
/* The timer identifier is erroneus */
|
||||
|
||||
errno = EINVAL;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* The overflow count of the timer is stored in "overrun" */
|
||||
|
||||
overrun = timer_struct[timer_pos].overrun;
|
||||
|
||||
/* It is set to 0 */
|
||||
|
||||
timer_struct[timer_pos].overrun = 0;
|
||||
|
||||
return overrun;
|
||||
|
||||
}
|
||||
|
||||
@@ -353,6 +353,10 @@ rtems_extensions_table Configuration_Initial_Extensions[] = {
|
||||
#define CONFIGURE_MAXIMUM_POSIX_KEYS 0
|
||||
#endif
|
||||
|
||||
#ifndef CONFIGURE_MAXIMUM_POSIX_TIMERS
|
||||
#define CONFIGURE_MAXIMUM_POSIX_TIMERS 0
|
||||
#endif
|
||||
|
||||
#ifndef CONFIGURE_MAXIMUM_POSIX_QUEUED_SIGNALS
|
||||
#define CONFIGURE_MAXIMUM_POSIX_QUEUED_SIGNALS 0
|
||||
#endif
|
||||
@@ -412,6 +416,10 @@ posix_initialization_threads_table POSIX_Initialization_threads[] = {
|
||||
((_keys) * \
|
||||
( sizeof(POSIX_Keys_Control) + CONFIGURE_OBJECT_TABLE_STUFF ) )
|
||||
|
||||
#define CONFIGURE_MEMORY_FOR_POSIX_TIMERS(_timers) \
|
||||
((_timers) * \
|
||||
( 0 ) )
|
||||
|
||||
#define CONFIGURE_MEMORY_FOR_POSIX_QUEUED_SIGNALS(_queued_signals) \
|
||||
((_queued_signals) * \
|
||||
( sizeof(POSIX_signals_Siginfo_node) + CONFIGURE_OBJECT_TABLE_STUFF ) )
|
||||
@@ -617,6 +625,7 @@ posix_api_configuration_table Configuration_POSIX_API = {
|
||||
CONFIGURE_MAXIMUM_POSIX_CONDITION_VARIABLES +
|
||||
CONFIGURE_MAXIMUM_ADA_TASKS + CONFIGURE_MAXIMUM_FAKE_ADA_TASKS,
|
||||
CONFIGURE_MAXIMUM_POSIX_KEYS + CONFIGURE_GNAT_KEYS,
|
||||
CONFIGURE_MAXIMUM_POSIX_TIMERS,
|
||||
CONFIGURE_MAXIMUM_POSIX_QUEUED_SIGNALS,
|
||||
CONFIGURE_POSIX_INIT_THREAD_TABLE_SIZE,
|
||||
CONFIGURE_POSIX_INIT_THREAD_TABLE_NAME
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include <rtems/posix/priority.h>
|
||||
#include <rtems/posix/psignal.h>
|
||||
#include <rtems/posix/pthread.h>
|
||||
#include <rtems/posix/ptimer.h>
|
||||
#include <rtems/posix/time.h>
|
||||
|
||||
/*PAGE
|
||||
@@ -50,6 +51,7 @@ posix_api_configuration_table _POSIX_Default_configuration = {
|
||||
0, /* maximum_mutexes */
|
||||
0, /* maximum_condition_variables */
|
||||
0, /* maximum_keys */
|
||||
0, /* maximum_timers */
|
||||
0, /* maximum_queued_signals */
|
||||
0, /* number_of_initialization_threads */
|
||||
NULL /* User_initialization_threads_table */
|
||||
@@ -90,6 +92,7 @@ void _POSIX_API_Initialize(
|
||||
api_configuration->maximum_mutexes
|
||||
);
|
||||
|
||||
_POSIX_Timer_Manager_initialization ( api_configuration->maximum_timers );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -46,6 +46,7 @@ typedef struct {
|
||||
int maximum_mutexes;
|
||||
int maximum_condition_variables;
|
||||
int maximum_keys;
|
||||
int maximum_timers;
|
||||
int maximum_queued_signals;
|
||||
int number_of_initialization_threads;
|
||||
posix_initialization_threads_table *User_initialization_threads_table;
|
||||
|
||||
91
cpukit/posix/include/rtems/posix/ptimer.h
Normal file
91
cpukit/posix/include/rtems/posix/ptimer.h
Normal file
@@ -0,0 +1,91 @@
|
||||
/* rtems/posix/ptimer.h
|
||||
*
|
||||
* This include file contains all the private support information for
|
||||
* POSIX timers.
|
||||
*
|
||||
* COPYRIGHT (c) 1998.
|
||||
* Alfonso Escalera Pi<50>a
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.OARcorp.com/rtems/license.html.
|
||||
*
|
||||
* ptimer.h,v 1.0 1998/03/31 16:21:16
|
||||
*/
|
||||
|
||||
#ifndef __RTEMS_POSIX_TIMERS_h
|
||||
#define __RTEMS_POSIX_TIMERS_h
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <rtems/posix/config.h>
|
||||
|
||||
/*
|
||||
* _POSIX_Timers_Manager_initialization
|
||||
*
|
||||
* DESCRIPTION:
|
||||
*
|
||||
* This routine performs the initialization necessary for this manager.
|
||||
*/
|
||||
|
||||
void _POSIX_Timer_Manager_initialization ( int max_timers );
|
||||
|
||||
/*
|
||||
* 14.2.2 Create a Per-Process Timer, P1003.1b-1993, p. 264
|
||||
*
|
||||
* timer_create
|
||||
*/
|
||||
|
||||
int timer_create(
|
||||
clockid_t clock_id,
|
||||
struct sigevent *evp,
|
||||
timer_t *timerid
|
||||
);
|
||||
|
||||
/*
|
||||
* 14.2.3 Delete a Per_process Timer, P1003.1b-1993, p. 266
|
||||
*/
|
||||
|
||||
int timer_delete(
|
||||
timer_t timerid
|
||||
);
|
||||
|
||||
/*
|
||||
* 14.2.4 Per-Process Timers, P1003.1b-1993, p. 267
|
||||
*
|
||||
* timer_settime
|
||||
*/
|
||||
|
||||
int timer_settime(
|
||||
timer_t timerid,
|
||||
int flags,
|
||||
const struct itimerspec *value,
|
||||
struct itimerspec *ovalue
|
||||
);
|
||||
|
||||
/*
|
||||
* 14.2.4 Per-Process Timers, P1003.1b-1993, p. 267
|
||||
*
|
||||
* timer_gettime
|
||||
*/
|
||||
|
||||
int timer_gettime(
|
||||
timer_t timerid,
|
||||
struct itimerspec *value
|
||||
);
|
||||
|
||||
/*
|
||||
* 14.2.4 Per-Process Timers, P1003.1b-1993, p. 267
|
||||
*
|
||||
* timer_getoverrun
|
||||
*
|
||||
*/
|
||||
|
||||
int timer_getoverrun(
|
||||
timer_t timerid
|
||||
);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* $Id$
|
||||
* ptimer.c,v 1.1 1996/06/03 16:29:58 joel Exp
|
||||
*/
|
||||
|
||||
|
||||
#include <assert.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
@@ -13,17 +13,505 @@
|
||||
|
||||
#include <rtems/posix/time.h>
|
||||
|
||||
/************************************/
|
||||
/* These includes are now necessary */
|
||||
/************************************/
|
||||
|
||||
#include <sys/features.h>
|
||||
#include <rtems/rtems/status.h>
|
||||
#include <rtems/rtems/types.h>
|
||||
#include <rtems/rtems/timer.h>
|
||||
#include <rtems/rtems/clock.h>
|
||||
#include <rtems/posix/psignal.h>
|
||||
#include <rtems/score/wkspace.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
|
||||
/*****************************/
|
||||
/* End of necessary includes */
|
||||
/*****************************/
|
||||
|
||||
/* ************
|
||||
* Constants
|
||||
* ************/
|
||||
|
||||
#define STATE_FREE_C 0x01 /* Free position of the table of timers */
|
||||
#define STATE_CREATE_NEW_C 0x02 /* Created timer but not running */
|
||||
#define STATE_CREATE_RUN_C 0x03 /* Created timer and running */
|
||||
#define STATE_CREATE_STOP_C 0x04 /* Created, ran and stopped timer */
|
||||
#define MAX_NSEC_C 1000000000 /* Maximum number of nsec allowed */
|
||||
#define MIN_NSEC_C 0 /* Minimum number of nsec allowew */
|
||||
#define TIMER_RELATIVE_C 0 /* Indicates that the fire time is
|
||||
* relative to the current one */
|
||||
#define SEC_TO_TICKS_C _TOD_Ticks_per_second /* Number of ticks in a second*/
|
||||
#define NSEC_PER_SEC_C 1000000000 /* Nanoseconds in a second */
|
||||
|
||||
#define NO_MORE_TIMERS_C 11 /* There is not available timers */
|
||||
#define BAD_TIMER_C 11 /* The timer does not exist in the table */
|
||||
|
||||
#define SECONDS_PER_YEAR_C ( 360 * 24 * 60 * 60 )
|
||||
#define SECONDS_PER_MONTH_C ( 30 * 24 * 60 * 60 )
|
||||
#define SECONDS_PER_DAY_C ( 24 * 60 * 60 )
|
||||
#define SECONDS_PER_HOUR_C ( 60 * 60 )
|
||||
#define SECONDS_PER_MINUTE_C ( 60 )
|
||||
|
||||
/*
|
||||
* 14.2.2 Create a Per-Process Timer, P1003.1b-1993, p. 264
|
||||
#define DEBUG_MESSAGES
|
||||
*/
|
||||
|
||||
/* *********************************************************
|
||||
* Types that will store the created timers and their data
|
||||
* *********************************************************/
|
||||
|
||||
/*
|
||||
* Data for a timer
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
pthread_t thread_id; /* Thread identifier */
|
||||
char state; /* State of the timer */
|
||||
struct sigevent inf; /* Information associated to the timer */
|
||||
timer_t timer_id; /* Created timer identifier */
|
||||
struct itimerspec timer_data; /* Timing data of the timer */
|
||||
unsigned32 ticks; /* Number of ticks of the initialization */
|
||||
unsigned32 overrun; /* Number of expirations of the timer */
|
||||
rtems_time_of_day time; /* Time in which the timer was started */
|
||||
} timer_alive_t;
|
||||
|
||||
/*
|
||||
* Array of Timers
|
||||
*/
|
||||
|
||||
int timer_max;
|
||||
timer_alive_t *timer_struct;
|
||||
|
||||
/*
|
||||
* Data for the signals
|
||||
*/
|
||||
|
||||
struct sigaction signal_inf[SIGRTMAX];
|
||||
|
||||
/***********************************
|
||||
* Definition of Internal Functions
|
||||
***********************************/
|
||||
|
||||
/* ***************************************************************************
|
||||
* PRINT_MSG_S
|
||||
*
|
||||
* Description: This function write a message in the display.
|
||||
* It is used for debugging and all the calls must be deleted
|
||||
* when the tests finish
|
||||
* ***************************************************************************/
|
||||
|
||||
static void PRINT_MSG_S ( char *msg )
|
||||
{
|
||||
|
||||
#ifdef DEBUG_MESSAGES
|
||||
printf("%s\n", msg);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/* ***************************************************************************
|
||||
* PRINT_ERRNO_S
|
||||
*
|
||||
* Description: Print the value of the global variable errno in the display
|
||||
* ***************************************************************************/
|
||||
|
||||
static void PRINT_ERRNO_S ()
|
||||
{
|
||||
#ifdef DEBUG_MESSAGES
|
||||
switch (errno)
|
||||
{
|
||||
case EINVAL:
|
||||
PRINT_MSG_S ( "errno EINVAL"); break;
|
||||
case EPERM:
|
||||
PRINT_MSG_S ( "errno EPERM"); break;
|
||||
case ESRCH:
|
||||
PRINT_MSG_S ( "errno ESRCH"); break;
|
||||
case EAGAIN:
|
||||
PRINT_MSG_S ( "errno EAGAIN"); break;
|
||||
default :
|
||||
printf ("errno: %d\n", errno);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* ***************************************************************************
|
||||
* TIMER_INITIALIZE_S
|
||||
*
|
||||
* Description: Initialize the data of a timer
|
||||
* ***************************************************************************/
|
||||
|
||||
void TIMER_INITIALIZE_S ( int timer_pos )
|
||||
{
|
||||
|
||||
/*
|
||||
* Indicates that the position in the table is free
|
||||
*/
|
||||
|
||||
timer_struct[timer_pos].state = STATE_FREE_C;
|
||||
|
||||
/*
|
||||
* The initial data of timing are set with null value
|
||||
*/
|
||||
|
||||
timer_struct[timer_pos].timer_data.it_value.tv_sec = 0;
|
||||
timer_struct[timer_pos].timer_data.it_value.tv_nsec = 0;
|
||||
timer_struct[timer_pos].timer_data.it_interval.tv_sec = 0;
|
||||
timer_struct[timer_pos].timer_data.it_interval.tv_nsec = 0;
|
||||
|
||||
/*
|
||||
* The count of expirations is 0
|
||||
*/
|
||||
|
||||
timer_struct[timer_pos].overrun = 0;
|
||||
|
||||
}
|
||||
|
||||
/* ***************************************************************************
|
||||
* _POSIX_Timer_Manager_initialization
|
||||
*
|
||||
* Description: Initialize the internal structure in which the data of all
|
||||
* the timers are stored
|
||||
* ***************************************************************************/
|
||||
|
||||
void _POSIX_Timer_Manager_initialization ( int max_timers )
|
||||
{
|
||||
int index;
|
||||
|
||||
timer_struct = _Workspace_Allocate_or_fatal_error(
|
||||
max_timers * sizeof(timer_alive_t) );
|
||||
|
||||
/*
|
||||
* Initialize all the timers
|
||||
*/
|
||||
|
||||
for (index=0; index<max_timers; index++)
|
||||
TIMER_INITIALIZE_S( index );
|
||||
}
|
||||
|
||||
/* ***************************************************************************
|
||||
* FIRST_FREE_POSITION_F
|
||||
*
|
||||
* Description: Returns the first free position in the table of timers.
|
||||
* If there is not a free position, it returns NO_MORE_TIMERS_C
|
||||
* ***************************************************************************/
|
||||
|
||||
int FIRST_FREE_POSITION_F ()
|
||||
{
|
||||
int index;
|
||||
|
||||
for (index=0; index<timer_max; index++) {
|
||||
if ( timer_struct[index].state == STATE_FREE_C ) {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
||||
/* The function reaches this point only if all the position are occupied */
|
||||
|
||||
return NO_MORE_TIMERS_C;
|
||||
}
|
||||
|
||||
/* ***************************************************************************
|
||||
* TIMER_POSITION_F
|
||||
*
|
||||
* Description: Returns the position in the table of timers in which the
|
||||
* data of the timer are stored.
|
||||
* If the timer identifier does not exist, it returns
|
||||
* BAD_TIMER_C
|
||||
* ***************************************************************************/
|
||||
|
||||
int TIMER_POSITION_F ( timer_t timer_id )
|
||||
{
|
||||
int index;
|
||||
|
||||
for (index=0; index<timer_max; index++ ) {
|
||||
|
||||
/* Looks for the position of the timer. The timer must exist and the
|
||||
* position can not be free */
|
||||
if ( ( timer_struct[index].timer_id == timer_id ) &&
|
||||
( timer_struct[index].state != STATE_FREE_C ) ) {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
||||
/* If the function reaches this point is because the timer identifier
|
||||
* is not correct */
|
||||
|
||||
return BAD_TIMER_C;
|
||||
|
||||
}
|
||||
|
||||
/* ***************************************************************************
|
||||
* COPY_ITIMERSPEC_S
|
||||
*
|
||||
* Description: Does a copy of a variable of type struct itimerspec
|
||||
* ***************************************************************************/
|
||||
|
||||
void COPY_ITIMERSPEC_S ( const struct itimerspec *source,
|
||||
struct itimerspec *target )
|
||||
{
|
||||
|
||||
target->it_value.tv_sec = source->it_value.tv_sec;
|
||||
target->it_value.tv_nsec = source->it_value.tv_nsec;
|
||||
target->it_interval.tv_sec = source->it_interval.tv_sec;
|
||||
target->it_interval.tv_nsec = source->it_interval.tv_nsec;
|
||||
|
||||
}
|
||||
|
||||
/* ***************************************************************************
|
||||
* ITIMERSPEC_TO_RTEMS_TIME_OF_DAY_S
|
||||
*
|
||||
* Description: This function converts the data of a structure itimerspec
|
||||
* into structure rtems_time_of_day
|
||||
* ***************************************************************************/
|
||||
|
||||
void ITIMERSPEC_TO_RTEMS_TIME_OF_DAY_S
|
||||
( const struct itimerspec *itimer, rtems_time_of_day *rtems_time )
|
||||
{
|
||||
unsigned long int seconds;
|
||||
|
||||
/* The leap years and the months with 28, 29 or 31 days have not been
|
||||
* considerated. It will be made in the future */
|
||||
|
||||
seconds = itimer->it_value.tv_sec;
|
||||
|
||||
rtems_time->year = seconds / SECONDS_PER_YEAR_C;
|
||||
seconds = seconds % SECONDS_PER_YEAR_C;
|
||||
|
||||
rtems_time->month = seconds / SECONDS_PER_MONTH_C;
|
||||
seconds = seconds % SECONDS_PER_MONTH_C;
|
||||
|
||||
rtems_time->day = seconds / SECONDS_PER_DAY_C;
|
||||
seconds = seconds % SECONDS_PER_DAY_C;
|
||||
|
||||
rtems_time->hour = seconds / SECONDS_PER_HOUR_C;
|
||||
seconds = seconds % SECONDS_PER_HOUR_C;
|
||||
|
||||
rtems_time->minute = seconds / SECONDS_PER_MINUTE_C;
|
||||
seconds = seconds % SECONDS_PER_MINUTE_C;
|
||||
|
||||
rtems_time->second = seconds;
|
||||
|
||||
rtems_time->ticks = ( itimer->it_value.tv_nsec * SEC_TO_TICKS_C ) /
|
||||
NSEC_PER_SEC_C;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* ***************************************************************************
|
||||
* FIRE_TIMER_S
|
||||
*
|
||||
* Description: This is the operation that is ran when a timer expires
|
||||
* ***************************************************************************/
|
||||
|
||||
|
||||
rtems_timer_service_routine FIRE_TIMER_S (rtems_id timer, void *data)
|
||||
{
|
||||
int timer_pos; /* Position in the table of the timer that
|
||||
* has expirated */
|
||||
rtems_status_code return_v; /* Return value of rtems_timer_fire_after */
|
||||
int sig_number; /* Number of the signal to send */
|
||||
|
||||
|
||||
/* The position of the table of timers that contains the data of the
|
||||
* expired timer will be stored in "timer_pos". In theory a timer can not
|
||||
* expire if it has not been created or has been deleted */
|
||||
|
||||
PRINT_MSG_S ("FIRE_TIMER_S");
|
||||
|
||||
timer_pos = TIMER_POSITION_F(timer);
|
||||
|
||||
/* Increases the number of expiration of the timer in one unit. */
|
||||
timer_struct[timer_pos].overrun = timer_struct[timer_pos].overrun + 1;
|
||||
|
||||
|
||||
if ( ( timer_struct[timer_pos].timer_data.it_interval.tv_sec != 0 ) ||
|
||||
( timer_struct[timer_pos].timer_data.it_interval.tv_nsec != 0 ) ) {
|
||||
|
||||
/* The timer must be reprogrammed */
|
||||
|
||||
return_v = rtems_timer_fire_after ( timer,
|
||||
timer_struct[timer_pos].ticks,
|
||||
FIRE_TIMER_S,
|
||||
NULL );
|
||||
|
||||
/* Stores the time when the timer was started again */
|
||||
|
||||
return_v = rtems_clock_get ( RTEMS_CLOCK_GET_TOD,
|
||||
&timer_struct[timer_pos].time );
|
||||
|
||||
/* The state has not to be actualized, because nothing modifies it */
|
||||
|
||||
timer_struct[timer_pos].state = STATE_CREATE_RUN_C;
|
||||
|
||||
} else {
|
||||
/* Indicates that the timer is stopped */
|
||||
|
||||
timer_struct[timer_pos].state = STATE_CREATE_STOP_C;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* The sending of the signal to the process running the handling function
|
||||
* specified for that signal is simulated
|
||||
*/
|
||||
|
||||
sig_number = timer_struct[timer_pos].inf.sigev_signo;
|
||||
|
||||
if( pthread_kill ( timer_struct[timer_pos].thread_id ,
|
||||
timer_struct[timer_pos].inf.sigev_signo ) ) {
|
||||
PRINT_MSG_S ("ERROR_PTHREAD_KILL");
|
||||
} else {
|
||||
PRINT_MSG_S ("SUCCESS_PTHREAD_KILL");
|
||||
}
|
||||
|
||||
/*
|
||||
* After the signal handler returns, the count of expirations of the
|
||||
* timer must be set to 0.
|
||||
*/
|
||||
|
||||
timer_struct[timer_pos].overrun = 0;
|
||||
|
||||
}
|
||||
|
||||
/* *********************************************************************
|
||||
* 14.2.2 Create a Per-Process Timer, P1003.1b-1993, p. 264
|
||||
* ********************************************************************/
|
||||
|
||||
/* **************
|
||||
* timer_create
|
||||
* **************/
|
||||
|
||||
int timer_create(
|
||||
clockid_t clock_id,
|
||||
struct sigevent *evp,
|
||||
timer_t *timerid
|
||||
)
|
||||
{
|
||||
return POSIX_NOT_IMPLEMENTED();
|
||||
|
||||
rtems_status_code return_v; /* return value of the operation */
|
||||
rtems_id timer_id; /* created timer identifier */
|
||||
int timer_pos; /* Position in the table of timers */
|
||||
|
||||
/*
|
||||
* The data of the structure evp are checked in order to verify if they
|
||||
* are coherent.
|
||||
*/
|
||||
|
||||
if (evp != NULL) {
|
||||
/* The structure has data */
|
||||
|
||||
if ( ( evp->sigev_notify != SIGEV_NONE ) &&
|
||||
( evp->sigev_notify != SIGEV_SIGNAL ) ) {
|
||||
/* The value of the field sigev_notify is not valid */
|
||||
|
||||
return (-1);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* A timer is created using the primitive rtems_timer_create
|
||||
*/
|
||||
|
||||
return_v = rtems_timer_create ( clock_id, &timer_id );
|
||||
|
||||
switch (return_v) {
|
||||
case RTEMS_SUCCESSFUL :
|
||||
|
||||
PRINT_MSG_S("SUCCESS: rtems create timer RTEMS_SUCCESSFUL");
|
||||
|
||||
/*
|
||||
* The timer has been created properly
|
||||
*/
|
||||
|
||||
/* Obtains the first free position in the table of timers */
|
||||
|
||||
timer_pos = FIRST_FREE_POSITION_F();
|
||||
|
||||
if ( timer_pos == NO_MORE_TIMERS_C ) {
|
||||
/* There is not position for another timers in spite of RTEMS
|
||||
* supports it. It will necessaty to increase the structure used */
|
||||
|
||||
errno = EAGAIN;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Exit parameter */
|
||||
|
||||
*timerid = timer_id;
|
||||
|
||||
/* The data of the created timer are stored to use them later */
|
||||
|
||||
timer_struct[timer_pos].state = STATE_CREATE_NEW_C;
|
||||
|
||||
/* NEW VERSION*/
|
||||
timer_struct[timer_pos].thread_id = pthread_self ();
|
||||
|
||||
|
||||
if ( evp != NULL ) {
|
||||
|
||||
timer_struct[timer_pos].inf.sigev_notify = evp->sigev_notify;
|
||||
timer_struct[timer_pos].inf.sigev_signo = evp->sigev_signo;
|
||||
timer_struct[timer_pos].inf.sigev_value = evp->sigev_value;
|
||||
|
||||
}
|
||||
|
||||
|
||||
timer_struct[timer_pos].timer_id = timer_id;
|
||||
|
||||
timer_struct[timer_pos].overrun = 0;
|
||||
|
||||
timer_struct[timer_pos].timer_data.it_value.tv_sec = 0;
|
||||
timer_struct[timer_pos].timer_data.it_value.tv_nsec = 0;
|
||||
timer_struct[timer_pos].timer_data.it_interval.tv_sec = 0;
|
||||
timer_struct[timer_pos].timer_data.it_interval.tv_nsec = 0;
|
||||
|
||||
return 0;
|
||||
|
||||
|
||||
case RTEMS_INVALID_NAME : /* The assigned name is not valid*/
|
||||
|
||||
PRINT_MSG_S ("ERROR: rtems create timer RTEMS_INVALID_NAME");
|
||||
|
||||
errno = EINVAL;
|
||||
|
||||
return (-1);
|
||||
|
||||
|
||||
case RTEMS_TOO_MANY :
|
||||
|
||||
PRINT_MSG_S ("ERROR: rtems create timer RTEMS_TOO_MANY ");
|
||||
|
||||
/* There has been created too much timers for the same process */
|
||||
|
||||
errno = EAGAIN;
|
||||
|
||||
return (-1);
|
||||
|
||||
default :
|
||||
|
||||
/*
|
||||
* Does nothing. It only returns the error without assigning a value
|
||||
* to errno. In theory, it can not happen because the call to
|
||||
* rtems_timer_create can not return other different value.
|
||||
*/
|
||||
|
||||
return (-1);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* The next sentence is used to avoid singular situations
|
||||
*/
|
||||
|
||||
return (-1);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -34,13 +522,58 @@ int timer_delete(
|
||||
timer_t timerid
|
||||
)
|
||||
{
|
||||
return POSIX_NOT_IMPLEMENTED();
|
||||
|
||||
/*
|
||||
* IDEA: This function must probably stop the timer first and then delete it
|
||||
*
|
||||
* It will have to do a call to rtems_timer_cancel and then another
|
||||
* call to rtems_timer_delete.
|
||||
* The call to rtems_timer_delete will be probably unnecessary,
|
||||
* because rtems_timer_delete stops the timer before deleting it.
|
||||
*/
|
||||
|
||||
int timer_pos;
|
||||
rtems_status_code status;
|
||||
|
||||
|
||||
/* First the position in the table of timers is obtained */
|
||||
|
||||
timer_pos = TIMER_POSITION_F ( timerid );
|
||||
|
||||
if ( timer_pos == BAD_TIMER_C ) {
|
||||
/* The timer identifier is erroneus */
|
||||
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* The timer is deleted */
|
||||
|
||||
status = rtems_timer_delete ( timerid );
|
||||
|
||||
if ( status == RTEMS_INVALID_ID ) {
|
||||
/* The timer identifier is erroneus */
|
||||
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Initializes the data of the timer */
|
||||
|
||||
TIMER_INITIALIZE_S ( timer_pos );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* 14.2.4 Per-Process Timers, P1003.1b-1993, p. 267
|
||||
*/
|
||||
|
||||
/* **************
|
||||
* timer_settime
|
||||
* **************/
|
||||
|
||||
|
||||
int timer_settime(
|
||||
timer_t timerid,
|
||||
int flags,
|
||||
@@ -48,28 +581,394 @@ int timer_settime(
|
||||
struct itimerspec *ovalue
|
||||
)
|
||||
{
|
||||
return POSIX_NOT_IMPLEMENTED();
|
||||
|
||||
rtems_status_code return_v; /* Return of the calls to RTEMS */
|
||||
int timer_pos; /* Position of the timer in the table */
|
||||
rtems_time_of_day rtems_time; /* Time in RTEMS */
|
||||
|
||||
/* First the position in the table of timers is obtained */
|
||||
|
||||
timer_pos = TIMER_POSITION_F ( timerid );
|
||||
|
||||
if ( timer_pos == BAD_TIMER_C ) {
|
||||
/* The timer identifier is erroneus */
|
||||
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( value == NULL ) {
|
||||
/* The stucture of times of the timer is free, and then returns an
|
||||
error but the variable errno is not actualized */
|
||||
|
||||
/* errno = ?????? */
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* If the function reaches this point, then it will be necessary to do
|
||||
* something with the structure of times of the timer: to stop, start
|
||||
* or start it again */
|
||||
|
||||
/* First, it verifies if the timer must be stopped */
|
||||
|
||||
if ( value->it_value.tv_sec == 0 && value->it_value.tv_nsec == 0 ) {
|
||||
/* The timer is stopped */
|
||||
|
||||
return_v = rtems_timer_cancel ( timerid );
|
||||
|
||||
/* The old data of the timer are returned */
|
||||
|
||||
COPY_ITIMERSPEC_S ( &timer_struct[timer_pos].timer_data, ovalue );
|
||||
|
||||
/* The new data are set */
|
||||
|
||||
COPY_ITIMERSPEC_S ( value, &timer_struct[timer_pos].timer_data );
|
||||
|
||||
/* Indicates that the timer is created and stopped */
|
||||
|
||||
timer_struct[timer_pos].state = STATE_CREATE_STOP_C;
|
||||
|
||||
/* Returns with success */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the function reaches this point, then the timer will have to be
|
||||
* initialized with new values: to start it or start it again
|
||||
*/
|
||||
|
||||
/* First, it verifies if the structure "value" is correct */
|
||||
|
||||
if ( ( value->it_value.tv_nsec > MAX_NSEC_C ) ||
|
||||
( value->it_value.tv_nsec < MIN_NSEC_C ) ) {
|
||||
/* The number of nanoseconds is not correct */
|
||||
|
||||
errno = EINVAL;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Then, "value" must be converted from seconds and nanoseconds to clock
|
||||
* ticks, to use it in the calls to RTEMS */
|
||||
|
||||
/* It is also necessary to take in account if the time is absolute
|
||||
* or relative */
|
||||
|
||||
switch (flags) {
|
||||
case TIMER_ABSTIME:
|
||||
|
||||
/* The fire time is absolute:
|
||||
* It has to use "rtems_time_fire_when" */
|
||||
|
||||
/* First, it converts from struct itimerspec to rtems_time_of_day */
|
||||
|
||||
ITIMERSPEC_TO_RTEMS_TIME_OF_DAY_S ( value, &rtems_time );
|
||||
|
||||
return_v = rtems_timer_fire_when ( timerid, &rtems_time, FIRE_TIMER_S, NULL);
|
||||
|
||||
switch ( return_v ) {
|
||||
case RTEMS_SUCCESSFUL:
|
||||
|
||||
PRINT_MSG_S ("SUCCESS: timer_settime RTEMS_SUCCESSFUL");
|
||||
|
||||
/* The timer has been started and is running */
|
||||
|
||||
/* Actualizes the data of the structure and
|
||||
* returns the old ones in "ovalue" */
|
||||
|
||||
COPY_ITIMERSPEC_S ( &timer_struct[timer_pos].timer_data, ovalue );
|
||||
|
||||
COPY_ITIMERSPEC_S ( value, &timer_struct[timer_pos].timer_data );
|
||||
|
||||
/* It indicates that the time is running */
|
||||
|
||||
timer_struct[timer_pos].state = STATE_CREATE_RUN_C;
|
||||
|
||||
/* Stores the time in which the timer was started again */
|
||||
|
||||
return_v = rtems_clock_get ( RTEMS_CLOCK_GET_TOD,
|
||||
&timer_struct[timer_pos].time );
|
||||
|
||||
return 0;
|
||||
|
||||
break;
|
||||
|
||||
case RTEMS_INVALID_ID:
|
||||
|
||||
PRINT_MSG_S ("ERROR: timer_settime RTEMS_INVALID_ID");
|
||||
break;
|
||||
|
||||
case RTEMS_NOT_DEFINED:
|
||||
|
||||
PRINT_MSG_S ("ERROR: timer_settime RTEMS_NOT_DEFINED");
|
||||
break;
|
||||
|
||||
case RTEMS_INVALID_CLOCK:
|
||||
|
||||
PRINT_MSG_S ("ERROR: timer_settime RTEMS_INVALID_CLOCK");
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case TIMER_RELATIVE_C:
|
||||
|
||||
/* The fire time is relative:
|
||||
* It has to use "rtems_time_fire_after" */
|
||||
|
||||
/* First, it converts from seconds and nanoseconds to ticks */
|
||||
|
||||
/* The form in which this operation is done can produce a lost
|
||||
* of precision of 1 second */
|
||||
|
||||
/* This is the process to convert from nanoseconds to ticks
|
||||
*
|
||||
* There is a tick every 10 miliseconds, then the nanoseconds are
|
||||
* divided between 10**7. The result of this operation will be the
|
||||
* number of ticks
|
||||
*/
|
||||
|
||||
timer_struct[timer_pos].ticks =
|
||||
( SEC_TO_TICKS_C * value->it_value.tv_sec ) +
|
||||
( value->it_value.tv_nsec / ( 1000 * 1000 * 10 ) );
|
||||
|
||||
return_v = rtems_timer_fire_after ( timerid,
|
||||
timer_struct[timer_pos].ticks,
|
||||
FIRE_TIMER_S,
|
||||
NULL );
|
||||
|
||||
switch (return_v) {
|
||||
case RTEMS_SUCCESSFUL:
|
||||
|
||||
PRINT_MSG_S ( "SUCCESS: timer_settime RTEMS_SUCCESSFUL");
|
||||
|
||||
/* The timer has been started and is running */
|
||||
|
||||
/* Actualizes the data of the structure and
|
||||
* returns the old ones in "ovalue" */
|
||||
|
||||
COPY_ITIMERSPEC_S ( &timer_struct[timer_pos].timer_data, ovalue );
|
||||
|
||||
COPY_ITIMERSPEC_S ( value, &timer_struct[timer_pos].timer_data );
|
||||
|
||||
/* It indicates that the time is running */
|
||||
|
||||
timer_struct[timer_pos].state = STATE_CREATE_RUN_C;
|
||||
|
||||
/* Stores the time in which the timer was started again */
|
||||
|
||||
return_v = rtems_clock_get ( RTEMS_CLOCK_GET_TOD,
|
||||
&timer_struct[timer_pos].time );
|
||||
|
||||
return 0;
|
||||
|
||||
break;
|
||||
|
||||
case RTEMS_INVALID_ID:
|
||||
|
||||
PRINT_MSG_S ( "ERROR: timer_settime RTEMS_INVALID_ID");
|
||||
|
||||
/* The timer identifier is not correct. In theory, this
|
||||
* situation can not occur, but the solution is easy */
|
||||
|
||||
errno = EINVAL;
|
||||
|
||||
return -1;
|
||||
|
||||
break;
|
||||
|
||||
case RTEMS_INVALID_NUMBER:
|
||||
|
||||
PRINT_MSG_S ( "ERROR: timer_settime RTEMS_INVALID_NUMBER");
|
||||
|
||||
/* In this case, RTEMS fails because the values of timing
|
||||
* are incorrect */
|
||||
|
||||
/*
|
||||
* I do not know if errno must be actualized
|
||||
*
|
||||
* errno = EINVAL;
|
||||
*/
|
||||
|
||||
return -1;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
/* It does nothing, although it will be probably necessary to
|
||||
* return an error */
|
||||
|
||||
}
|
||||
|
||||
/* To avoid problems */
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 14.2.4 Per-Process Timers, P1003.1b-1993, p. 267
|
||||
*/
|
||||
|
||||
/* **************
|
||||
* timer_gettime
|
||||
* **************/
|
||||
|
||||
int timer_gettime(
|
||||
timer_t timerid,
|
||||
struct itimerspec *value
|
||||
)
|
||||
{
|
||||
return POSIX_NOT_IMPLEMENTED();
|
||||
|
||||
/*
|
||||
* IDEA: This function does not use functions of RTEMS to the handle
|
||||
* of timers. It uses some functions for managing the time.
|
||||
*
|
||||
* A possible form to do this is the following:
|
||||
*
|
||||
* - When a timer is initialized, the value of the time in
|
||||
* that moment is stored.
|
||||
* - When this function is called, it returns the difference
|
||||
* between the current time and the initialization time.
|
||||
*/
|
||||
|
||||
rtems_time_of_day current_time;
|
||||
rtems_status_code return_v;
|
||||
int timer_pos;
|
||||
unsigned32 hours;
|
||||
unsigned32 minutes;
|
||||
unsigned32 seconds;
|
||||
unsigned32 ticks;
|
||||
unsigned32 nanosec;
|
||||
|
||||
|
||||
/* Reads the current time */
|
||||
|
||||
return_v = rtems_clock_get ( RTEMS_CLOCK_GET_TOD, ¤t_time );
|
||||
|
||||
timer_pos = TIMER_POSITION_F ( timerid );
|
||||
|
||||
if ( timer_pos == BAD_TIMER_C ) {
|
||||
|
||||
/* The timer identifier is erroneus */
|
||||
|
||||
errno = EINVAL;
|
||||
|
||||
return (-1);
|
||||
|
||||
}
|
||||
|
||||
/* Calculates the difference between the start time of the timer and
|
||||
* the current one */
|
||||
|
||||
hours = current_time.hour - timer_struct[timer_pos].time.hour;
|
||||
|
||||
if ( current_time.minute < timer_struct[timer_pos].time.minute ) {
|
||||
minutes = 60 - timer_struct[timer_pos].time.minute + current_time.minute;
|
||||
hours--;
|
||||
} else {
|
||||
minutes = current_time.minute - timer_struct[timer_pos].time.minute;
|
||||
}
|
||||
|
||||
if ( current_time.second < timer_struct[timer_pos].time.second ) {
|
||||
seconds = 60 - timer_struct[timer_pos].time.second + current_time.second;
|
||||
minutes--;
|
||||
} else {
|
||||
seconds = current_time.second - timer_struct[timer_pos].time.second;
|
||||
}
|
||||
|
||||
if ( current_time.ticks < timer_struct[timer_pos].time.ticks ) {
|
||||
ticks = 100 - timer_struct[timer_pos].time.ticks + current_time.ticks;
|
||||
seconds--;
|
||||
} else {
|
||||
ticks = current_time.ticks - timer_struct[timer_pos].time.ticks;
|
||||
}
|
||||
|
||||
/* The time that the timer is running is calculated */
|
||||
seconds = hours * 60 * 60 +
|
||||
minutes * 60 +
|
||||
seconds;
|
||||
|
||||
nanosec = ticks * 10 * /* msec */
|
||||
1000 * /* microsec */
|
||||
1000; /* nanosec */
|
||||
|
||||
|
||||
/* Calculates the time left before the timer finishes */
|
||||
|
||||
value->it_value.tv_sec =
|
||||
timer_struct[timer_pos].timer_data.it_value.tv_sec - seconds;
|
||||
|
||||
value->it_value.tv_nsec =
|
||||
timer_struct[timer_pos].timer_data.it_value.tv_nsec - nanosec;
|
||||
|
||||
|
||||
value->it_interval.tv_sec =
|
||||
timer_struct[timer_pos].timer_data.it_interval.tv_sec;
|
||||
value->it_interval.tv_nsec =
|
||||
timer_struct[timer_pos].timer_data.it_interval.tv_nsec;
|
||||
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* 14.2.4 Per-Process Timers, P1003.1b-1993, p. 267
|
||||
*/
|
||||
|
||||
/* *****************
|
||||
* timer_getoverrun
|
||||
* *****************/
|
||||
|
||||
int timer_getoverrun(
|
||||
timer_t timerid
|
||||
)
|
||||
{
|
||||
return POSIX_NOT_IMPLEMENTED();
|
||||
|
||||
/*
|
||||
* IDEA: This function must count the times the timer expires.
|
||||
*
|
||||
* The expiration of a timer must increase by one a counter.
|
||||
* After the signal handler associated to the timer finishs
|
||||
* its execution, FIRE_TIMER_S will have to set this counter to 0.
|
||||
*/
|
||||
|
||||
int timer_pos; /* Position of the timer in the structure */
|
||||
int overrun; /* Overflow count */
|
||||
|
||||
|
||||
timer_pos = TIMER_POSITION_F ( timerid );
|
||||
|
||||
if ( timer_pos == BAD_TIMER_C ) {
|
||||
/* The timer identifier is erroneus */
|
||||
|
||||
errno = EINVAL;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* The overflow count of the timer is stored in "overrun" */
|
||||
|
||||
overrun = timer_struct[timer_pos].overrun;
|
||||
|
||||
/* It is set to 0 */
|
||||
|
||||
timer_struct[timer_pos].overrun = 0;
|
||||
|
||||
return overrun;
|
||||
|
||||
}
|
||||
|
||||
@@ -353,6 +353,10 @@ rtems_extensions_table Configuration_Initial_Extensions[] = {
|
||||
#define CONFIGURE_MAXIMUM_POSIX_KEYS 0
|
||||
#endif
|
||||
|
||||
#ifndef CONFIGURE_MAXIMUM_POSIX_TIMERS
|
||||
#define CONFIGURE_MAXIMUM_POSIX_TIMERS 0
|
||||
#endif
|
||||
|
||||
#ifndef CONFIGURE_MAXIMUM_POSIX_QUEUED_SIGNALS
|
||||
#define CONFIGURE_MAXIMUM_POSIX_QUEUED_SIGNALS 0
|
||||
#endif
|
||||
@@ -412,6 +416,10 @@ posix_initialization_threads_table POSIX_Initialization_threads[] = {
|
||||
((_keys) * \
|
||||
( sizeof(POSIX_Keys_Control) + CONFIGURE_OBJECT_TABLE_STUFF ) )
|
||||
|
||||
#define CONFIGURE_MEMORY_FOR_POSIX_TIMERS(_timers) \
|
||||
((_timers) * \
|
||||
( 0 ) )
|
||||
|
||||
#define CONFIGURE_MEMORY_FOR_POSIX_QUEUED_SIGNALS(_queued_signals) \
|
||||
((_queued_signals) * \
|
||||
( sizeof(POSIX_signals_Siginfo_node) + CONFIGURE_OBJECT_TABLE_STUFF ) )
|
||||
@@ -617,6 +625,7 @@ posix_api_configuration_table Configuration_POSIX_API = {
|
||||
CONFIGURE_MAXIMUM_POSIX_CONDITION_VARIABLES +
|
||||
CONFIGURE_MAXIMUM_ADA_TASKS + CONFIGURE_MAXIMUM_FAKE_ADA_TASKS,
|
||||
CONFIGURE_MAXIMUM_POSIX_KEYS + CONFIGURE_GNAT_KEYS,
|
||||
CONFIGURE_MAXIMUM_POSIX_TIMERS,
|
||||
CONFIGURE_MAXIMUM_POSIX_QUEUED_SIGNALS,
|
||||
CONFIGURE_POSIX_INIT_THREAD_TABLE_SIZE,
|
||||
CONFIGURE_POSIX_INIT_THREAD_TABLE_NAME
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include <rtems/posix/priority.h>
|
||||
#include <rtems/posix/psignal.h>
|
||||
#include <rtems/posix/pthread.h>
|
||||
#include <rtems/posix/ptimer.h>
|
||||
#include <rtems/posix/time.h>
|
||||
|
||||
/*PAGE
|
||||
@@ -50,6 +51,7 @@ posix_api_configuration_table _POSIX_Default_configuration = {
|
||||
0, /* maximum_mutexes */
|
||||
0, /* maximum_condition_variables */
|
||||
0, /* maximum_keys */
|
||||
0, /* maximum_timers */
|
||||
0, /* maximum_queued_signals */
|
||||
0, /* number_of_initialization_threads */
|
||||
NULL /* User_initialization_threads_table */
|
||||
@@ -90,6 +92,7 @@ void _POSIX_API_Initialize(
|
||||
api_configuration->maximum_mutexes
|
||||
);
|
||||
|
||||
_POSIX_Timer_Manager_initialization ( api_configuration->maximum_timers );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user