summaryrefslogtreecommitdiffstats
path: root/c/src/exec
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>1999-02-03 16:22:18 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>1999-02-03 16:22:18 +0000
commit0747e2d3c3859bfe2bc6e7591679710e3fdf8a5a (patch)
tree53da5d9364147d18a4628962c75fb83779a15dea /c/src/exec
parentNew test from Juan Zamorano Flores <jzamora@avellano.datsi.fi.upm.es> (diff)
downloadrtems-0747e2d3c3859bfe2bc6e7591679710e3fdf8a5a.tar.bz2
POSIX Timers submitted by Juan Zamorano Flores
<jzamora@avellano.datsi.fi.upm.es>.
Diffstat (limited to 'c/src/exec')
-rw-r--r--c/src/exec/posix/include/rtems/posix/Makefile.in2
-rw-r--r--c/src/exec/posix/include/rtems/posix/config.h1
-rw-r--r--c/src/exec/posix/include/rtems/posix/ptimer.h91
-rw-r--r--c/src/exec/posix/src/Makefile.in4
-rw-r--r--c/src/exec/posix/src/ptimer.c915
-rw-r--r--c/src/exec/sapi/include/confdefs.h9
-rw-r--r--c/src/exec/sapi/src/posixapi.c3
7 files changed, 1014 insertions, 11 deletions
diff --git a/c/src/exec/posix/include/rtems/posix/Makefile.in b/c/src/exec/posix/include/rtems/posix/Makefile.in
index 3c75974208..e61c8029a7 100644
--- a/c/src/exec/posix/include/rtems/posix/Makefile.in
+++ b/c/src/exec/posix/include/rtems/posix/Makefile.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
diff --git a/c/src/exec/posix/include/rtems/posix/config.h b/c/src/exec/posix/include/rtems/posix/config.h
index 8753c42382..c64250579c 100644
--- a/c/src/exec/posix/include/rtems/posix/config.h
+++ b/c/src/exec/posix/include/rtems/posix/config.h
@@ -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;
diff --git a/c/src/exec/posix/include/rtems/posix/ptimer.h b/c/src/exec/posix/include/rtems/posix/ptimer.h
new file mode 100644
index 0000000000..c19f10c54c
--- /dev/null
+++ b/c/src/exec/posix/include/rtems/posix/ptimer.h
@@ -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ņ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
+
diff --git a/c/src/exec/posix/src/Makefile.in b/c/src/exec/posix/src/Makefile.in
index f8148aca0e..cb3083329b 100644
--- a/c/src/exec/posix/src/Makefile.in
+++ b/c/src/exec/posix/src/Makefile.in
@@ -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)
diff --git a/c/src/exec/posix/src/ptimer.c b/c/src/exec/posix/src/ptimer.c
index 0446a7a683..ff65297f96 100644
--- a/c/src/exec/posix/src/ptimer.c
+++ b/c/src/exec/posix/src/ptimer.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, &current_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;
+
}
diff --git a/c/src/exec/sapi/include/confdefs.h b/c/src/exec/sapi/include/confdefs.h
index 75f3132055..0cec9c8f15 100644
--- a/c/src/exec/sapi/include/confdefs.h
+++ b/c/src/exec/sapi/include/confdefs.h
@@ -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
diff --git a/c/src/exec/sapi/src/posixapi.c b/c/src/exec/sapi/src/posixapi.c
index cc41c30d20..481d640c0b 100644
--- a/c/src/exec/sapi/src/posixapi.c
+++ b/c/src/exec/sapi/src/posixapi.c
@@ -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