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:
Joel Sherrill
2008-12-03 20:58:29 +00:00
parent 3a8335b671
commit 109ace3a1f
10 changed files with 408 additions and 235 deletions
+11
View File
@@ -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
+15 -92
View File
@@ -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>
+1
View File
@@ -62,4 +62,5 @@ void _Timer_Manager_initialization(
*/
_Timer_Server = NULL;
_Timer_Server_schedule_operation = NULL;
}
+5 -4
View File
@@ -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:
File diff suppressed because it is too large Load Diff
+6 -4
View File
@@ -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;
+6 -4
View File
@@ -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;
+2 -2
View File
@@ -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 \
@@ -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
View 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 );
}