summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--cpukit/ChangeLog11
-rw-r--r--cpukit/rtems/include/rtems/rtems/timer.h107
-rw-r--r--cpukit/rtems/src/rtemstimer.c1
-rw-r--r--cpukit/rtems/src/timerreset.c9
-rw-r--r--cpukit/rtems/src/timerserver.c401
-rw-r--r--cpukit/rtems/src/timerserverfireafter.c10
-rw-r--r--cpukit/rtems/src/timerserverfirewhen.c10
-rw-r--r--cpukit/score/Makefile.am4
-rw-r--r--cpukit/score/include/rtems/score/watchdog.h19
-rw-r--r--cpukit/score/src/watchdogadjusttochain.c67
10 files changed, 406 insertions, 233 deletions
diff --git a/cpukit/ChangeLog b/cpukit/ChangeLog
index ecb3983f4f..d8cf203be9 100644
--- a/cpukit/ChangeLog
+++ b/cpukit/ChangeLog
@@ -1,5 +1,16 @@
2008-12-03 Joel Sherrill <joel.sherrill@OARcorp.com>
+ PR 1347/cpukit
+ * rtems/include/rtems/rtems/timer.h, rtems/src/rtemstimer.c,
+ rtems/src/timerreset.c, rtems/src/timerserver.c,
+ rtems/src/timerserverfireafter.c, rtems/src/timerserverfirewhen.c,
+ score/Makefile.am, score/include/rtems/score/watchdog.h: Rework Timer
+ Server to ensure that the context allows for blocking, allocating
+ memory, and acquiring semaphores and mutexes.
+ * score/src/watchdogadjusttochain.c: New file.
+
+2008-12-03 Joel Sherrill <joel.sherrill@OARcorp.com>
+
PR 1346/cpukit
* rtems/include/rtems/rtems/ratemon.h: Sense of rate monotonic
statistics nanoseconds or ticks granularity conditional is backwards.
diff --git a/cpukit/rtems/include/rtems/rtems/timer.h b/cpukit/rtems/include/rtems/rtems/timer.h
index a7d6029620..711995e983 100644
--- a/cpukit/rtems/include/rtems/rtems/timer.h
+++ b/cpukit/rtems/include/rtems/rtems/timer.h
@@ -58,7 +58,12 @@ extern "C" {
/**
* @defgroup ClassicTimer Classic API Timer
*
- * This encapsulates functionality which XXX
+ * This encapsulates functionality related to the Classic API Timer
+ * Manager. This manager provides functionality which allows the
+ * application to schedule the execution of methods at a specified
+ * time in the future. These methods may be scheduled based upon
+ * interval or wall time and may be executed in either the clock tick
+ * ISR or in a special dedicated timer server task.
*/
/**@{*/
@@ -126,32 +131,6 @@ RTEMS_TIMER_EXTERN Objects_Information _Timer_Information;
RTEMS_TIMER_EXTERN Thread_Control *_Timer_Server;
/**
- * This chain contains the list of interval timers that are
- * executed in the context of the Timer Server.
- *
- * @note This is extern'ed because they do not have to be in the
- * minimum footprint. It is only really required when
- * task-based timers are used. Since task-based timers can
- * not be started until the server is initiated, this structure
- * does not have to be initialized until then. This is declared
- * in the same file as _Timer_Server_body.
- */
-extern Chain_Control _Timer_Ticks_chain;
-
-/**
- * This chain contains the list of time of day timers that are
- * executed in the context of the Timer Server.
- *
- * @note This is extern'ed because they do not have to be in the
- * minimum footprint. It is only really required when
- * task-based timers are used. Since task-based timers can
- * not be started until the server is initiated, this structure
- * does not have to be initialized until then. This is declared
- * in the same file as _Timer_Server_body.
- */
-extern Chain_Control _Timer_Seconds_chain;
-
-/**
* The following records define the control block used to manage
* each timer.
*/
@@ -174,18 +153,6 @@ void _Timer_Manager_initialization(
);
/**
- * @brief _Timer_Server_body
- *
- * This is the server for task based timers. This task executes whenever
- * a task-based timer should fire. It services both "after" and "when"
- * timers. It is not created automatically but must be created explicitly
- * by the application before task-based timers may be initiated.
- */
-Thread _Timer_Server_body(
- uint32_t ignored
-);
-
-/**
* @brief rtems_timer_create
*
* This routine implements the rtems_timer_create directive. The
@@ -353,63 +320,19 @@ rtems_status_code rtems_timer_get_information(
);
/**
- * Macros and routines that expose the mechanisms required to service
- * the Timer Server timer. These stop the timer, synchronize it with
- * the current time, and restart it.
+ * This type defines the method used to schedule the insertion of task
+ * based timers.
*/
-extern Watchdog_Control _Timer_Seconds_timer;
-
-/**
- * This method is used to temporarily disable updates to the
- * Ticks Timer Chain managed by the Timer Server.
- */
-#define _Timer_Server_stop_ticks_timer() \
- _Watchdog_Remove( &_Timer_Server->Timer )
-
-/**
- * This method is used to temporarily disable updates to the
- * Seconds Timer Chain managed by the Timer Server.
- */
-#define _Timer_Server_stop_seconds_timer() \
- _Watchdog_Remove( &_Timer_Seconds_timer );
-
-/**
- * This is a helper function which processes the ticks chain when
- * needed. It advances time for the ticks chain which results in
- * timers firing.
- */
-void _Timer_Server_process_ticks_chain(void);
-
-/**
- * This is a helper function which processes the seconds chain when
- * needed. It advances time for the seconds chain which results in
- * timers firing.
- */
-void _Timer_Server_process_seconds_chain(void);
-
-/**
- * This method resets a timer and places it on the Ticks chain. It
- * is assumed that the timer has already been canceled.
- */
-#define _Timer_Server_reset_ticks_timer() \
- do { \
- if ( !_Chain_Is_empty( &_Timer_Ticks_chain ) ) { \
- _Watchdog_Insert_ticks( &_Timer_Server->Timer, \
- ((Watchdog_Control *)_Timer_Ticks_chain.first)->delta_interval ); \
- } \
- } while (0)
+typedef void (*Timer_Server_schedule_operation_t)(
+ Timer_Control *the_timer
+);
/**
- * This method resets a timer and places it on the Seconds chain. It
- * is assumed that the timer has already been canceled.
+ * This variable will point to the schedule operation method once the
+ * timer server is initialized.
*/
-#define _Timer_Server_reset_seconds_timer() \
- do { \
- if ( !_Chain_Is_empty( &_Timer_Seconds_chain ) ) { \
- _Watchdog_Insert_seconds( &_Timer_Seconds_timer, \
- ((Watchdog_Control *)_Timer_Seconds_chain.first)->delta_interval ); \
- } \
- } while (0)
+RTEMS_TIMER_EXTERN Timer_Server_schedule_operation_t
+ _Timer_Server_schedule_operation;
#ifndef __RTEMS_APPLICATION__
#include <rtems/rtems/timer.inl>
diff --git a/cpukit/rtems/src/rtemstimer.c b/cpukit/rtems/src/rtemstimer.c
index 909bb9b15a..a7dd750656 100644
--- a/cpukit/rtems/src/rtemstimer.c
+++ b/cpukit/rtems/src/rtemstimer.c
@@ -62,4 +62,5 @@ void _Timer_Manager_initialization(
*/
_Timer_Server = NULL;
+ _Timer_Server_schedule_operation = NULL;
}
diff --git a/cpukit/rtems/src/timerreset.c b/cpukit/rtems/src/timerreset.c
index 7fea9fa7d5..1688051f8a 100644
--- a/cpukit/rtems/src/timerreset.c
+++ b/cpukit/rtems/src/timerreset.c
@@ -56,11 +56,12 @@ rtems_status_code rtems_timer_reset(
_Watchdog_Insert( &_Watchdog_Ticks_chain, &the_timer->Ticker );
break;
case TIMER_INTERVAL_ON_TASK:
- _Timer_Server_stop_ticks_timer();
+ if ( !_Timer_Server_schedule_operation ) {
+ _Thread_Enable_dispatch();
+ return RTEMS_INCORRECT_STATE;
+ }
_Watchdog_Remove( &the_timer->Ticker );
- _Timer_Server_process_ticks_chain();
- _Watchdog_Insert( &_Timer_Ticks_chain, &the_timer->Ticker );
- _Timer_Server_reset_ticks_timer();
+ (*_Timer_Server_schedule_operation)( the_timer );
break;
case TIMER_TIME_OF_DAY:
case TIMER_TIME_OF_DAY_ON_TASK:
diff --git a/cpukit/rtems/src/timerserver.c b/cpukit/rtems/src/timerserver.c
index a96b45272e..9c4ea90b50 100644
--- a/cpukit/rtems/src/timerserver.c
+++ b/cpukit/rtems/src/timerserver.c
@@ -1,8 +1,18 @@
-/*
+/**
+ * @file timerserver.c
+ *
* Timer Manager - rtems_timer_initiate_server directive along with
- * the Timer Server Body and support routines
+ * the Timer Server Body and support routines
*
- * COPYRIGHT (c) 1989-2008.
+ * @note Data specific to the Timer Server is declared in this
+ * file as the Timer Server so it does not have to be in the
+ * minimum footprint. It is only really required when
+ * task-based timers are used. Since task-based timers can
+ * not be started until the server is initiated, this structure
+ * does not have to be initialized until then.
+ */
+
+/* COPYRIGHT (c) 1989-2008.
* On-Line Applications Research Corporation (OAR).
*
* The license and distribution terms for this file may be
@@ -29,115 +39,319 @@
#include <rtems/rtems/support.h>
#include <rtems/score/thread.h>
-/*
- * The following chains contain the list of interval timers that are
+/**
+ * This chain contains the list of interval timers that are
* executed in the context of the Timer Server.
- *
- * NOTE: These are prototyped in rtems/timer/timer.h but since we
- * do not actually use them until after the Timer Server is
- * initiated, we can actually declare them here and avoid forcing
- * them into the minimum footprint.
*/
-
Chain_Control _Timer_Ticks_chain;
+
+/**
+ * This chain contains the list of time of day timers that are
+ * executed in the context of the Timer Server.
+ */
Chain_Control _Timer_Seconds_chain;
-/*
- * These variables keep track of the last time the Timer Server actually
- * processed the chain.
+/**
+ * This chain holds the set of timers to be inserted when the
+ * server runs again.
*/
+Chain_Control _Timer_To_be_inserted;
-Watchdog_Interval _Timer_Server_seconds_last_time;
+/**
+ * This variables keeps track of the last time the Timer Server actually
+ * processed the ticks chain.
+ */
Watchdog_Interval _Timer_Server_ticks_last_time;
-/*
- * The timer used to control when the Timer Server wakes up to service
- * "when" timers.
+/**
+ * This variable keeps track of the last time the Timer Server actually
+ * processed the seconds chain.
*/
+Watchdog_Interval _Timer_Server_seconds_last_time;
+/**
+ * This is the timer used to control when the Timer Server wakes up to
+ * service "when" timers.
+ *
+ * @note The timer in the Timer Server TCB is used for ticks timer.
+ */
Watchdog_Control _Timer_Seconds_timer;
-/*PAGE
+/**
+ * This method is used to temporarily disable updates to the
+ * Ticks Timer Chain managed by the Timer Server.
+ */
+#define _Timer_Server_stop_ticks_timer() \
+ _Watchdog_Remove( &_Timer_Server->Timer )
+
+/**
+ * This method is used to temporarily disable updates to the
+ * Seconds Timer Chain managed by the Timer Server.
+ */
+#define _Timer_Server_stop_seconds_timer() \
+ _Watchdog_Remove( &_Timer_Seconds_timer );
+
+/**
+ * This method resets a timer and places it on the Ticks chain. It
+ * is assumed that the timer has already been canceled.
+ */
+#define _Timer_Server_reset_ticks_timer() \
+ do { \
+ if ( !_Chain_Is_empty( &_Timer_Ticks_chain ) ) { \
+ _Watchdog_Insert_ticks( &_Timer_Server->Timer, \
+ ((Watchdog_Control *)_Timer_Ticks_chain.first)->delta_interval ); \
+ } \
+ } while (0)
+
+/**
+ * This method resets a timer and places it on the Seconds chain. It
+ * is assumed that the timer has already been canceled.
+ */
+#define _Timer_Server_reset_seconds_timer() \
+ do { \
+ if ( !_Chain_Is_empty( &_Timer_Seconds_chain ) ) { \
+ _Watchdog_Insert_seconds( &_Timer_Seconds_timer, \
+ ((Watchdog_Control *)_Timer_Seconds_chain.first)->delta_interval ); \
+ } \
+ } while (0)
+
+/**
+ * @brief _Timer_Server_process_insertions
+ *
+ * This method processes the set of timers scheduled for insertion
+ * onto one of the Timer Server chains.
+ *
+ * @note It is only to be called from the Timer Server task.
+ */
+static void _Timer_Server_process_insertions(void)
+{
+ Timer_Control *the_timer;
+
+ while ( 1 ) {
+ the_timer = (Timer_Control *) _Chain_Get( &_Timer_To_be_inserted );
+ if ( the_timer == NULL )
+ break;
+
+ if ( the_timer->the_class == TIMER_INTERVAL_ON_TASK ) {
+ _Watchdog_Insert( &_Timer_Ticks_chain, &the_timer->Ticker );
+ } else if ( the_timer->the_class == TIMER_TIME_OF_DAY_ON_TASK ) {
+ _Watchdog_Insert( &_Timer_Seconds_chain, &the_timer->Ticker );
+ }
+ }
+}
+
+/**
+ * @brief _Timer_Server_process_ticks_chain
+ *
+ * This routine is responsible for adjusting the list of task-based
+ * interval timers to reflect the passage of time.
+ *
+ * @param[in] to_fire will contain the set of timers that are to be fired.
+ *
+ * @note It is only to be called from the Timer Server task.
+ */
+static void _Timer_Server_process_ticks_chain(
+ Chain_Control *to_fire
+)
+{
+ Watchdog_Interval snapshot;
+ Watchdog_Interval ticks;
+
+ snapshot = _Watchdog_Ticks_since_boot;
+ if ( snapshot >= _Timer_Server_ticks_last_time )
+ ticks = snapshot - _Timer_Server_ticks_last_time;
+ else
+ ticks = (0xFFFFFFFF - _Timer_Server_ticks_last_time) + snapshot;
+
+ _Timer_Server_ticks_last_time = snapshot;
+ _Watchdog_Adjust_to_chain( &_Timer_Ticks_chain, ticks, to_fire );
+}
+
+/**
+ * @brief _Timer_Server_process_seconds_chain
*
- * _Timer_Server_body
+ * This routine is responsible for adjusting the list of task-based
+ * time of day timers to reflect the passage of time.
+ *
+ * @param[in] to_fire will contain the set of timers that are to be fired.
+ *
+ * @note It is only to be called from the Timer Server task.
+ */
+static void _Timer_Server_process_seconds_chain(
+ Chain_Control *to_fire
+)
+{
+ Watchdog_Interval snapshot;
+ Watchdog_Interval ticks;
+
+ /*
+ * Process the seconds chain. Start by checking that the Time
+ * of Day (TOD) has not been set backwards. If it has then
+ * we want to adjust the _Timer_Seconds_chain to indicate this.
+ */
+ snapshot = _TOD_Seconds_since_epoch;
+ if ( snapshot > _Timer_Server_seconds_last_time ) {
+ /*
+ * This path is for normal forward movement and cases where the
+ * TOD has been set forward.
+ */
+ ticks = snapshot - _Timer_Server_seconds_last_time;
+ _Watchdog_Adjust_to_chain( &_Timer_Seconds_chain, ticks, to_fire );
+
+ } else if ( snapshot < _Timer_Server_seconds_last_time ) {
+ /*
+ * The current TOD is before the last TOD which indicates that
+ * TOD has been set backwards.
+ */
+ ticks = _Timer_Server_seconds_last_time - snapshot;
+ _Watchdog_Adjust( &_Timer_Seconds_chain, WATCHDOG_BACKWARD, ticks );
+ }
+ _Timer_Server_seconds_last_time = snapshot;
+}
+
+/**
+ * @brief _Timer_Server_body
*
* This is the server for task based timers. This task executes whenever
* a task-based timer should fire. It services both "after" and "when"
* timers. It is not created automatically but must be created explicitly
* by the application before task-based timers may be initiated.
*
- * Input parameters:
- * Ignored - the task argument is ignored
- *
- * Output parameters: NONE
+ * @param[in] ignored is the the task argument that is ignored
*/
-
Thread _Timer_Server_body(
uint32_t ignored
)
{
+ Chain_Control to_fire;
+
+ _Chain_Initialize_empty( &to_fire );
+
/*
* Initialize the "last time" markers to indicate the timer that
* the server was initiated.
*/
-
_Timer_Server_ticks_last_time = _Watchdog_Ticks_since_boot;
_Timer_Server_seconds_last_time = _TOD_Seconds_since_epoch;
+ /*
+ * Insert the timers that were inserted before we got to run.
+ * This should be done with dispatching disabled.
+ */
_Thread_Disable_dispatch();
+ _Timer_Server_process_insertions();
+ _Thread_Enable_dispatch();
+
while(1) {
/*
* Block until there is something to do.
*/
-
+ _Thread_Disable_dispatch();
_Thread_Set_state( _Timer_Server, STATES_DELAYING );
_Timer_Server_reset_ticks_timer();
_Timer_Server_reset_seconds_timer();
_Thread_Enable_dispatch();
+ /********************************************************************
+ ********************************************************************
+ **** TIMER SERVER BLOCKS HERE ****
+ ********************************************************************
+ ********************************************************************/
+
+ /*
+ * Disable dispatching while processing the timers since we want
+ * the removal of the timers from the chain to be atomic.
+ *
+ * NOTE: Dispatching is disabled for interrupt based TSRs.
+ * Dispatching is enabled for task based TSRs so they
+ * can temporarily malloc memory or block.
+ * _ISR_Nest_level is 0 for task-based TSRs and non-zero
+ * for the others.
+ */
+ _Thread_Disable_dispatch();
+
/*
* At this point, at least one of the timers this task relies
* upon has fired. Stop them both while we process any outstanding
* timers. Before we block, we will restart them.
*/
+ _Timer_Server_stop_ticks_timer();
+ _Timer_Server_stop_seconds_timer();
- _Timer_Server_stop_ticks_timer();
- _Timer_Server_stop_seconds_timer();
+ /*
+ * Remove all the timers that need to fire so we can invoke them
+ * outside the critical section.
+ */
+ _Timer_Server_process_ticks_chain( &to_fire );
+ _Timer_Server_process_seconds_chain( &to_fire );
/*
- * Disable dispatching while processing the timers since we want
- * to mimic the environment that non-task-based TSRs execute in.
- * This ensures that the primary difference is that _ISR_Nest_level
- * is 0 for task-based timers and non-zero for the others.
+ * Insert the timers that have been requested to be inserted.
*/
+ _Timer_Server_process_insertions();
- _Thread_Disable_dispatch();
- _Timer_Server_process_ticks_chain();
- _Timer_Server_process_seconds_chain();
+ /*
+ * Enable dispatching to process the set that are ready "to fire."
+ */
+ _Thread_Enable_dispatch();
+
+ /*
+ * Now we actually invoke the TSR for all the timers that fired.
+ * This is done with dispatching
+ */
+ while (1) {
+ Watchdog_Control *watch;
+ ISR_Level level;
+
+ _ISR_Disable( level );
+ watch = (Watchdog_Control *) _Chain_Get_unprotected( &to_fire );
+ if ( watch == NULL ) {
+ _ISR_Enable( level );
+ break;
+ }
+
+ watch->state = WATCHDOG_INACTIVE;
+ _ISR_Enable( level );
+
+ (*watch->routine)( watch->id, watch->user_data );
+ }
}
return 0; /* unreached - only to remove warnings */
}
-/*PAGE
+/**
+ * This method schedules the insertion of timers on the proper list. It
+ * wakes up the Timer Server task to process the insertion.
*
- * rtems_timer_initiate_server
+ * @param[in] the_timer is the timer to insert
+ *
+ * @note It is highly likely the executing task will be preempted after
+ * the directive invoking this is executed.
+ */
+static void _Timer_Server_schedule_operation_method(
+ Timer_Control *the_timer
+)
+{
+ _Chain_Append( &_Timer_To_be_inserted, &the_timer->Object.Node );
+ _Watchdog_Remove( &_Timer_Server->Timer );
+ _Thread_Delay_ended( _Timer_Server->Object.id, NULL );
+}
+
+/**
+ * @brief rtems_timer_initiate_server
*
* This directive creates and starts the server for task-based timers.
* It must be invoked before any task-based timers can be initiated.
*
- * Input parameters:
- * priority - timer server priority
- * stack_size - stack size in bytes
- * attribute_set - timer server attributes
+ * @param[in] priority is the timer server priority
+ * @param[in] stack_size is the stack size in bytes
+ * @param[in] attribute_set is the timer server attributes
*
- * Output parameters:
- * RTEMS_SUCCESSFUL - if successful
- * error code - if unsuccessful
+ * @return This method returns RTEMS_SUCCESSFUL if successful and an
+ * error code otherwise.
*/
-
-
rtems_status_code rtems_timer_initiate_server(
uint32_t priority,
uint32_t stack_size,
@@ -151,11 +365,10 @@ rtems_status_code rtems_timer_initiate_server(
bool tmpInitialized;
/*
- * Make sure the requested priority is valid. The if is
+ * Make sure the requested priority is valid. The if is
* structured so we check it is invalid before looking for
* a specific invalid value as the default.
*/
-
_priority = priority;
if ( !_RTEMS_tasks_Priority_is_valid( priority ) ) {
if ( priority != RTEMS_TIMER_SERVER_DEFAULT_PRIORITY )
@@ -166,7 +379,6 @@ rtems_status_code rtems_timer_initiate_server(
/*
* Just to make sure this is only called once.
*/
-
_Thread_Disable_dispatch();
tmpInitialized = initialized;
initialized = true;
@@ -176,6 +388,11 @@ rtems_status_code rtems_timer_initiate_server(
return RTEMS_INCORRECT_STATE;
/*
+ * Initialize the set of timers to be inserted by the server.
+ */
+ _Chain_Initialize_empty( &_Timer_To_be_inserted );
+
+ /*
* Create the Timer Server with the name the name of "TIME". The attribute
* RTEMS_SYSTEM_TASK allows us to set a priority to 0 which will makes it
* higher than any other task in the system. It can be viewed as a low
@@ -189,7 +406,6 @@ rtems_status_code rtems_timer_initiate_server(
* Otherwise, the priority ceiling for the mutex used to protect the
* GNAT run-time is violated.
*/
-
status = rtems_task_create(
_Objects_Build_name('T','I','M','E'), /* "TIME" */
_priority, /* create with priority 1 since 0 is illegal */
@@ -217,7 +433,6 @@ rtems_status_code rtems_timer_initiate_server(
* NOTE: Setting the pointer to the Timer Server TCB to a value other than
* NULL indicates that task-based timer support is initialized.
*/
-
_Timer_Server = (Thread_Control *)_Objects_Get_local_object(
&_RTEMS_tasks_Information,
_Objects_Get_index(id)
@@ -226,7 +441,6 @@ rtems_status_code rtems_timer_initiate_server(
/*
* Initialize the timer lists that the server will manage.
*/
-
_Chain_Initialize_empty( &_Timer_Ticks_chain );
_Chain_Initialize_empty( &_Timer_Seconds_chain );
@@ -234,13 +448,18 @@ rtems_status_code rtems_timer_initiate_server(
* Initialize the timers that will be used to control when the
* Timer Server wakes up and services the task-based timers.
*/
-
_Watchdog_Initialize( &_Timer_Server->Timer, _Thread_Delay_ended, id, NULL );
_Watchdog_Initialize( &_Timer_Seconds_timer, _Thread_Delay_ended, id, NULL );
+
/*
- * Start the timer server
+ * Initialize the pointer to the timer reset method so applications
+ * that do not use the Timer Server do not have to pull it in.
*/
+ _Timer_Server_schedule_operation = _Timer_Server_schedule_operation_method;
+ /*
+ * Start the timer server
+ */
status = rtems_task_start(
id, /* the id from create */
(rtems_task_entry) _Timer_Server_body, /* the timer server entry point */
@@ -259,75 +478,3 @@ rtems_status_code rtems_timer_initiate_server(
return status;
}
-
-/*PAGE
- *
- * _Timer_Server_process_ticks_chain
- *
- * This routine is responsible for adjusting the list of task-based
- * interval timers to reflect the passage of time.
- *
- * Input parameters: NONE
- *
- * Output parameters: NONE
- */
-
-void _Timer_Server_process_ticks_chain(void)
-{
- Watchdog_Interval snapshot;
- Watchdog_Interval ticks;
-
- snapshot = _Watchdog_Ticks_since_boot;
- if ( snapshot >= _Timer_Server_ticks_last_time )
- ticks = snapshot - _Timer_Server_ticks_last_time;
- else
- ticks = (0xFFFFFFFF - _Timer_Server_ticks_last_time) + snapshot;
-
- _Timer_Server_ticks_last_time = snapshot;
- _Watchdog_Adjust( &_Timer_Ticks_chain, WATCHDOG_FORWARD, ticks );
-}
-
-/*PAGE
- *
- * _Timer_Server_process_seconds_chain
- *
- * This routine is responsible for adjusting the list of task-based
- * time of day timers to reflect the passage of time.
- *
- * Input parameters: NONE
- *
- * Output parameters: NONE
- */
-
-void _Timer_Server_process_seconds_chain(void)
-{
- Watchdog_Interval snapshot;
- Watchdog_Interval ticks;
-
- /*
- * Process the seconds chain. Start by checking that the Time
- * of Day (TOD) has not been set backwards. If it has then
- * we want to adjust the _Timer_Seconds_chain to indicate this.
- */
-
- snapshot = _TOD_Seconds_since_epoch;
- if ( snapshot > _Timer_Server_seconds_last_time ) {
- /*
- * This path is for normal forward movement and cases where the
- * TOD has been set forward.
- */
-
- ticks = snapshot - _Timer_Server_seconds_last_time;
- _Watchdog_Adjust( &_Timer_Seconds_chain, WATCHDOG_FORWARD, ticks );
-
- } else if ( snapshot < _Timer_Server_seconds_last_time ) {
- /*
- * The current TOD is before the last TOD which indicates that
- * TOD has been set backwards.
- */
-
- ticks = _Timer_Server_seconds_last_time - snapshot;
- _Watchdog_Adjust( &_Timer_Seconds_chain, WATCHDOG_BACKWARD, ticks );
- }
- _Timer_Server_seconds_last_time = snapshot;
-}
diff --git a/cpukit/rtems/src/timerserverfireafter.c b/cpukit/rtems/src/timerserverfireafter.c
index 568f53be1e..d23edee60c 100644
--- a/cpukit/rtems/src/timerserverfireafter.c
+++ b/cpukit/rtems/src/timerserverfireafter.c
@@ -92,10 +92,12 @@ rtems_status_code rtems_timer_server_fire_after(
the_timer->Ticker.initial = ticks;
_ISR_Enable( level );
- _Timer_Server_stop_ticks_timer();
- _Timer_Server_process_ticks_chain();
- _Watchdog_Insert( &_Timer_Ticks_chain, &the_timer->Ticker );
- _Timer_Server_reset_ticks_timer();
+ /*
+ * _Timer_Server_schedule_operation != NULL because we checked that
+ * _Timer_Server was != NULL above. Both are set at the same time.
+ */
+
+ (*_Timer_Server_schedule_operation)( the_timer );
_Thread_Enable_dispatch();
return RTEMS_SUCCESSFUL;
diff --git a/cpukit/rtems/src/timerserverfirewhen.c b/cpukit/rtems/src/timerserverfirewhen.c
index cece25e926..a1f2caee6f 100644
--- a/cpukit/rtems/src/timerserverfirewhen.c
+++ b/cpukit/rtems/src/timerserverfirewhen.c
@@ -79,10 +79,12 @@ rtems_status_code rtems_timer_server_fire_when(
_Watchdog_Initialize( &the_timer->Ticker, routine, id, user_data );
the_timer->Ticker.initial = seconds - _TOD_Seconds_since_epoch;
- _Timer_Server_stop_seconds_timer();
- _Timer_Server_process_seconds_chain();
- _Watchdog_Insert( &_Timer_Seconds_chain, &the_timer->Ticker );
- _Timer_Server_reset_seconds_timer();
+ /*
+ * _Timer_Server_schedule_operation != NULL because we checked that
+ * _Timer_Server was != NULL above. Both are set at the same time.
+ */
+
+ (*_Timer_Server_schedule_operation)( the_timer );
_Thread_Enable_dispatch();
return RTEMS_SUCCESSFUL;
diff --git a/cpukit/score/Makefile.am b/cpukit/score/Makefile.am
index 0ea422fce6..ab38b23237 100644
--- a/cpukit/score/Makefile.am
+++ b/cpukit/score/Makefile.am
@@ -173,8 +173,8 @@ libscore_a_SOURCES += src/coretod.c src/coretodset.c src/coretodget.c \
## WATCHDOG_C_FILES
libscore_a_SOURCES += src/watchdog.c src/watchdogadjust.c \
- src/watchdoginsert.c src/watchdogremove.c src/watchdogtickle.c \
- src/watchdogreport.c src/watchdogreportchain.c
+ src/watchdogadjusttochain.c src/watchdoginsert.c src/watchdogremove.c \
+ src/watchdogtickle.c src/watchdogreport.c src/watchdogreportchain.c
## USEREXT_C_FILES
libscore_a_SOURCES += src/userextaddapiset.c src/userextaddset.c \
diff --git a/cpukit/score/include/rtems/score/watchdog.h b/cpukit/score/include/rtems/score/watchdog.h
index 5cc1498d5b..f542a51fae 100644
--- a/cpukit/score/include/rtems/score/watchdog.h
+++ b/cpukit/score/include/rtems/score/watchdog.h
@@ -220,6 +220,25 @@ void _Watchdog_Adjust (
Watchdog_Interval units
);
+/** @brief Watchdog Adjust to Chain
+ *
+ * This routine adjusts the @a header watchdog chain in the forward
+ * @a direction for @a units_arg ticks.
+ *
+ * @param[in] header is the watchdog chain to adjust
+ * @param[in] units is the number of units to adjust @a header
+ * @param[in] to_fire is a pointer to an initialized Chain_Control to which
+ * all watchdog instances that are to be fired will be placed.
+ *
+ * @note This always adjusts forward.
+ */
+void _Watchdog_Adjust_to_chain(
+ Chain_Control *header,
+ Watchdog_Interval units_arg,
+ Chain_Control *to_fire
+
+);
+
/** @brief Watchdog Insert
*
* This routine inserts @a the_watchdog into the @a header watchdog chain
diff --git a/cpukit/score/src/watchdogadjusttochain.c b/cpukit/score/src/watchdogadjusttochain.c
new file mode 100644
index 0000000000..5a03208ee0
--- /dev/null
+++ b/cpukit/score/src/watchdogadjusttochain.c
@@ -0,0 +1,67 @@
+/**
+ * @file watchdogadjusttochain.c
+ *
+ * This is used by the Timer Server task.
+ */
+
+/* COPYRIGHT (c) 1989-2008.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ *
+ * $Id$
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/system.h>
+#include <rtems/score/isr.h>
+#include <rtems/score/watchdog.h>
+
+void _Watchdog_Adjust_to_chain(
+ Chain_Control *header,
+ Watchdog_Interval units_arg,
+ Chain_Control *to_fire
+
+)
+{
+ Watchdog_Interval units = units_arg;
+ ISR_Level level;
+ Chain_Node *node;
+
+ if ( !units ) {
+ return;
+ }
+ _ISR_Disable( level );
+
+ if ( !_Chain_Is_empty( header ) ) {
+ while ( units ) {
+ if ( units < _Watchdog_First( header )->delta_interval ) {
+ _Watchdog_First( header )->delta_interval -= units;
+ break;
+ } else {
+ units -= _Watchdog_First( header )->delta_interval;
+ _Watchdog_First( header )->delta_interval = 0;
+
+ do {
+ node = _Chain_Get_unprotected( header );
+ _Chain_Append_unprotected( to_fire, node );
+
+ _ISR_Flash( level );
+
+ } while ( !_Chain_Is_empty( header ) &&
+ _Watchdog_First( header )->delta_interval == 0 );
+
+ if ( _Chain_Is_empty( header ) )
+ break;
+ }
+ }
+
+ }
+ _ISR_Enable( level );
+}
+