mirror of
https://gitlab.rtems.org/rtems/rtos/rtems.git
synced 2025-12-26 06:08:20 +00:00
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.
This commit is contained in:
@@ -1,3 +1,14 @@
|
||||
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
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
/**@{*/
|
||||
|
||||
@@ -125,32 +130,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.
|
||||
@@ -173,18 +152,6 @@ void _Timer_Manager_initialization(
|
||||
uint32_t maximum_timers
|
||||
);
|
||||
|
||||
/**
|
||||
* @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
|
||||
*
|
||||
@@ -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;
|
||||
typedef void (*Timer_Server_schedule_operation_t)(
|
||||
Timer_Control *the_timer
|
||||
);
|
||||
|
||||
/**
|
||||
* This method is used to temporarily disable updates to the
|
||||
* Ticks Timer Chain managed by the Timer Server.
|
||||
* This variable will point to the schedule operation method once the
|
||||
* timer server is initialized.
|
||||
*/
|
||||
#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)
|
||||
|
||||
/**
|
||||
* 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)
|
||||
RTEMS_TIMER_EXTERN Timer_Server_schedule_operation_t
|
||||
_Timer_Server_schedule_operation;
|
||||
|
||||
#ifndef __RTEMS_APPLICATION__
|
||||
#include <rtems/rtems/timer.inl>
|
||||
|
||||
@@ -62,4 +62,5 @@ void _Timer_Manager_initialization(
|
||||
*/
|
||||
|
||||
_Timer_Server = NULL;
|
||||
_Timer_Server_schedule_operation = NULL;
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -1,8 +1,18 @@
|
||||
/*
|
||||
* Timer Manager - rtems_timer_initiate_server directive along with
|
||||
* the Timer Server Body and support routines
|
||||
/**
|
||||
* @file timerserver.c
|
||||
*
|
||||
* COPYRIGHT (c) 1989-2008.
|
||||
* Timer Manager - rtems_timer_initiate_server directive along with
|
||||
* the Timer Server Body and support routines
|
||||
*
|
||||
* @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
|
||||
*
|
||||
* _Timer_Server_body
|
||||
* 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
|
||||
*
|
||||
* 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();
|
||||
|
||||
/*
|
||||
* 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.
|
||||
* 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 );
|
||||
|
||||
_Thread_Disable_dispatch();
|
||||
_Timer_Server_process_ticks_chain();
|
||||
_Timer_Server_process_seconds_chain();
|
||||
/*
|
||||
* Insert the timers that have been requested to be inserted.
|
||||
*/
|
||||
_Timer_Server_process_insertions();
|
||||
|
||||
/*
|
||||
* 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;
|
||||
@@ -175,6 +387,11 @@ rtems_status_code rtems_timer_initiate_server(
|
||||
if ( tmpInitialized )
|
||||
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
|
||||
@@ -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 );
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -173,7 +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/watchdogadjusttochain.c src/watchdoginsert.c src/watchdogremove.c \
|
||||
src/watchdogtickle.c
|
||||
|
||||
## USEREXT_C_FILES
|
||||
libscore_a_SOURCES += src/userextaddapiset.c src/userextaddset.c \
|
||||
|
||||
@@ -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
|
||||
|
||||
67
cpukit/score/src/watchdogadjusttochain.c
Normal file
67
cpukit/score/src/watchdogadjusttochain.c
Normal file
@@ -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 );
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user