forked from Imagelibrary/rtems
score: New timer server implementation
Use mostly the standard watchdog operations. Use a system event for synchronization. This implementation is simpler and offers better SMP performance. Close #2131.
This commit is contained in:
@@ -318,6 +318,11 @@ rtems_status_code rtems_event_receive (
|
||||
*/
|
||||
#define RTEMS_EVENT_SYSTEM_NETWORK_CLOSE RTEMS_EVENT_26
|
||||
|
||||
/**
|
||||
* @brief Reserved system event for the timer server.
|
||||
*/
|
||||
#define RTEMS_EVENT_SYSTEM_TIMER_SERVER RTEMS_EVENT_30
|
||||
|
||||
/**
|
||||
* @brief Reserved system event for transient usage.
|
||||
*/
|
||||
|
||||
@@ -64,25 +64,44 @@ typedef struct {
|
||||
*/
|
||||
Watchdog_Control System_watchdog;
|
||||
|
||||
/**
|
||||
* @brief Remaining delta of the system watchdog.
|
||||
*/
|
||||
Watchdog_Interval system_watchdog_delta;
|
||||
|
||||
/**
|
||||
* @brief Unique identifier of the context which deals currently with the
|
||||
* system watchdog.
|
||||
*/
|
||||
Thread_Control *system_watchdog_helper;
|
||||
|
||||
/**
|
||||
* @brief Each insert and tickle operation increases the generation count so
|
||||
* that the system watchdog dealer notices updates of the watchdog chain.
|
||||
*/
|
||||
uint32_t generation;
|
||||
|
||||
/**
|
||||
* @brief Watchdog header managed by the timer server.
|
||||
*/
|
||||
Watchdog_Header Header;
|
||||
|
||||
/**
|
||||
* @brief Last known time snapshot of the timer server.
|
||||
* @brief Last time snapshot of the timer server.
|
||||
*
|
||||
* The units may be ticks or seconds.
|
||||
*/
|
||||
Watchdog_Interval volatile last_snapshot;
|
||||
Watchdog_Interval last_snapshot;
|
||||
|
||||
/**
|
||||
* @brief Current time snapshot of the timer server.
|
||||
*
|
||||
* The units may be ticks or seconds.
|
||||
*/
|
||||
Watchdog_Interval current_snapshot;
|
||||
} Timer_server_Watchdogs;
|
||||
|
||||
struct Timer_server_Control {
|
||||
/**
|
||||
* @brief Timer server thread.
|
||||
*/
|
||||
Thread_Control *thread;
|
||||
|
||||
/**
|
||||
* @brief The cancel method of the timer server.
|
||||
*/
|
||||
@@ -102,26 +121,6 @@ struct Timer_server_Control {
|
||||
* @brief TOD watchdogs triggered by the timer server.
|
||||
*/
|
||||
Timer_server_Watchdogs TOD_watchdogs;
|
||||
|
||||
/**
|
||||
* @brief Chain of timers scheduled for insert.
|
||||
*
|
||||
* This pointer is not @c NULL whenever the interval and TOD chains are
|
||||
* processed. After the processing this list will be checked and if
|
||||
* necessary the processing will be restarted. Processing of these chains
|
||||
* can be only interrupted through interrupts.
|
||||
*/
|
||||
Chain_Control *volatile insert_chain;
|
||||
|
||||
/**
|
||||
* @brief Indicates that the timer server is active or not.
|
||||
*
|
||||
* The server is active after the delay on a system watchdog. The activity
|
||||
* period of the server ends when no more watchdogs managed by the server
|
||||
* fire. The system watchdogs must not be manipulated when the server is
|
||||
* active.
|
||||
*/
|
||||
bool volatile active;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
/* COPYRIGHT (c) 1989-2008.
|
||||
* On-Line Applications Research Corporation (OAR).
|
||||
*
|
||||
* Copyright (c) 2009 embedded brains GmbH.
|
||||
* Copyright (c) 2009-2015 embedded brains GmbH.
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
@@ -26,190 +26,13 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <rtems.h>
|
||||
#include <rtems/rtems/timerimpl.h>
|
||||
#include <rtems/rtems/tasksimpl.h>
|
||||
#include <rtems/score/isrlevel.h>
|
||||
#include <rtems/score/threadimpl.h>
|
||||
#include <rtems/score/todimpl.h>
|
||||
|
||||
static Timer_server_Control _Timer_server_Default;
|
||||
|
||||
static void _Timer_server_Stop_interval_system_watchdog(
|
||||
Timer_server_Control *ts
|
||||
)
|
||||
{
|
||||
_Watchdog_Remove_ticks( &ts->Interval_watchdogs.System_watchdog );
|
||||
}
|
||||
|
||||
static void _Timer_server_Reset_interval_system_watchdog(
|
||||
Timer_server_Control *ts
|
||||
)
|
||||
{
|
||||
ISR_Level level;
|
||||
|
||||
_Timer_server_Stop_interval_system_watchdog( ts );
|
||||
|
||||
_ISR_Disable( level );
|
||||
if ( !_Watchdog_Is_empty( &ts->Interval_watchdogs.Header ) ) {
|
||||
Watchdog_Interval delta_interval =
|
||||
_Watchdog_First( &ts->Interval_watchdogs.Header )->delta_interval;
|
||||
_ISR_Enable( level );
|
||||
|
||||
/*
|
||||
* The unit is TICKS here.
|
||||
*/
|
||||
_Watchdog_Insert_ticks(
|
||||
&ts->Interval_watchdogs.System_watchdog,
|
||||
delta_interval
|
||||
);
|
||||
} else {
|
||||
_ISR_Enable( level );
|
||||
}
|
||||
}
|
||||
|
||||
static void _Timer_server_Stop_tod_system_watchdog(
|
||||
Timer_server_Control *ts
|
||||
)
|
||||
{
|
||||
_Watchdog_Remove_seconds( &ts->TOD_watchdogs.System_watchdog );
|
||||
}
|
||||
|
||||
static void _Timer_server_Reset_tod_system_watchdog(
|
||||
Timer_server_Control *ts
|
||||
)
|
||||
{
|
||||
ISR_Level level;
|
||||
|
||||
_Timer_server_Stop_tod_system_watchdog( ts );
|
||||
|
||||
_ISR_Disable( level );
|
||||
if ( !_Watchdog_Is_empty( &ts->TOD_watchdogs.Header ) ) {
|
||||
Watchdog_Interval delta_interval =
|
||||
_Watchdog_First( &ts->TOD_watchdogs.Header )->delta_interval;
|
||||
_ISR_Enable( level );
|
||||
|
||||
/*
|
||||
* The unit is SECONDS here.
|
||||
*/
|
||||
_Watchdog_Insert_seconds(
|
||||
&ts->TOD_watchdogs.System_watchdog,
|
||||
delta_interval
|
||||
);
|
||||
} else {
|
||||
_ISR_Enable( level );
|
||||
}
|
||||
}
|
||||
|
||||
static void _Timer_server_Insert_timer(
|
||||
Timer_server_Control *ts,
|
||||
Timer_Control *timer
|
||||
)
|
||||
{
|
||||
if ( timer->the_class == TIMER_INTERVAL_ON_TASK ) {
|
||||
_Watchdog_Insert( &ts->Interval_watchdogs.Header, &timer->Ticker );
|
||||
} else if ( timer->the_class == TIMER_TIME_OF_DAY_ON_TASK ) {
|
||||
_Watchdog_Insert( &ts->TOD_watchdogs.Header, &timer->Ticker );
|
||||
}
|
||||
}
|
||||
|
||||
static void _Timer_server_Insert_timer_and_make_snapshot(
|
||||
Timer_server_Control *ts,
|
||||
Timer_Control *timer
|
||||
)
|
||||
{
|
||||
Watchdog_Control *first_watchdog;
|
||||
Watchdog_Interval delta_interval;
|
||||
Watchdog_Interval last_snapshot;
|
||||
Watchdog_Interval snapshot;
|
||||
Watchdog_Interval delta;
|
||||
ISR_Level level;
|
||||
|
||||
/*
|
||||
* We have to update the time snapshots here, because otherwise we may have
|
||||
* problems with the integer range of the delta values. The time delta DT
|
||||
* from the last snapshot to now may be arbitrarily long. The last snapshot
|
||||
* is the reference point for the delta chain. Thus if we do not update the
|
||||
* reference point we have to add DT to the initial delta of the watchdog
|
||||
* being inserted. This could result in an integer overflow.
|
||||
*/
|
||||
|
||||
_Thread_Disable_dispatch();
|
||||
|
||||
if ( timer->the_class == TIMER_INTERVAL_ON_TASK ) {
|
||||
/*
|
||||
* We have to advance the last known ticks value of the server and update
|
||||
* the watchdog chain accordingly.
|
||||
*/
|
||||
_ISR_Disable( level );
|
||||
snapshot = _Watchdog_Ticks_since_boot;
|
||||
last_snapshot = ts->Interval_watchdogs.last_snapshot;
|
||||
if ( !_Watchdog_Is_empty( &ts->Interval_watchdogs.Header ) ) {
|
||||
first_watchdog = _Watchdog_First( &ts->Interval_watchdogs.Header );
|
||||
|
||||
/*
|
||||
* We assume adequate unsigned arithmetic here.
|
||||
*/
|
||||
delta = snapshot - last_snapshot;
|
||||
|
||||
delta_interval = first_watchdog->delta_interval;
|
||||
if (delta_interval > delta) {
|
||||
delta_interval -= delta;
|
||||
} else {
|
||||
delta_interval = 0;
|
||||
}
|
||||
first_watchdog->delta_interval = delta_interval;
|
||||
}
|
||||
ts->Interval_watchdogs.last_snapshot = snapshot;
|
||||
_ISR_Enable( level );
|
||||
|
||||
_Watchdog_Insert( &ts->Interval_watchdogs.Header, &timer->Ticker );
|
||||
|
||||
if ( !ts->active ) {
|
||||
_Timer_server_Reset_interval_system_watchdog( ts );
|
||||
}
|
||||
} else if ( timer->the_class == TIMER_TIME_OF_DAY_ON_TASK ) {
|
||||
/*
|
||||
* We have to advance the last known seconds value of the server and update
|
||||
* the watchdog chain accordingly.
|
||||
*/
|
||||
_ISR_Disable( level );
|
||||
snapshot = (Watchdog_Interval) _TOD_Seconds_since_epoch();
|
||||
last_snapshot = ts->TOD_watchdogs.last_snapshot;
|
||||
if ( !_Watchdog_Is_empty( &ts->TOD_watchdogs.Header ) ) {
|
||||
first_watchdog = _Watchdog_First( &ts->TOD_watchdogs.Header );
|
||||
delta_interval = first_watchdog->delta_interval;
|
||||
if ( snapshot > last_snapshot ) {
|
||||
/*
|
||||
* We advanced in time.
|
||||
*/
|
||||
delta = snapshot - last_snapshot;
|
||||
if (delta_interval > delta) {
|
||||
delta_interval -= delta;
|
||||
} else {
|
||||
delta_interval = 0;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Someone put us in the past.
|
||||
*/
|
||||
delta = last_snapshot - snapshot;
|
||||
delta_interval += delta;
|
||||
}
|
||||
first_watchdog->delta_interval = delta_interval;
|
||||
}
|
||||
ts->TOD_watchdogs.last_snapshot = snapshot;
|
||||
_ISR_Enable( level );
|
||||
|
||||
_Watchdog_Insert( &ts->TOD_watchdogs.Header, &timer->Ticker );
|
||||
|
||||
if ( !ts->active ) {
|
||||
_Timer_server_Reset_tod_system_watchdog( ts );
|
||||
}
|
||||
}
|
||||
|
||||
_Thread_Enable_dispatch();
|
||||
}
|
||||
|
||||
static void _Timer_server_Cancel_method(
|
||||
Timer_server_Control *ts,
|
||||
Timer_Control *timer
|
||||
@@ -222,148 +45,181 @@ static void _Timer_server_Cancel_method(
|
||||
}
|
||||
}
|
||||
|
||||
static Watchdog_Interval _Timer_server_Get_ticks( void )
|
||||
{
|
||||
return _Watchdog_Ticks_since_boot;
|
||||
}
|
||||
|
||||
static Watchdog_Interval _Timer_server_Get_seconds( void )
|
||||
{
|
||||
return _TOD_Seconds_since_epoch();
|
||||
}
|
||||
|
||||
static void _Timer_server_Update_system_watchdog(
|
||||
Timer_server_Watchdogs *watchdogs,
|
||||
Watchdog_Header *system_header
|
||||
)
|
||||
{
|
||||
ISR_lock_Context lock_context;
|
||||
|
||||
_Watchdog_Acquire( &watchdogs->Header, &lock_context );
|
||||
|
||||
if ( watchdogs->system_watchdog_helper == NULL ) {
|
||||
Thread_Control *executing;
|
||||
uint32_t my_generation;
|
||||
|
||||
executing = _Thread_Executing;
|
||||
watchdogs->system_watchdog_helper = executing;
|
||||
|
||||
do {
|
||||
my_generation = watchdogs->generation;
|
||||
|
||||
if ( !_Watchdog_Is_empty( &watchdogs->Header ) ) {
|
||||
Watchdog_Control *first;
|
||||
Watchdog_Interval delta;
|
||||
|
||||
first = _Watchdog_First( &watchdogs->Header );
|
||||
delta = first->delta_interval;
|
||||
|
||||
if (
|
||||
watchdogs->System_watchdog.state == WATCHDOG_INACTIVE
|
||||
|| delta != watchdogs->system_watchdog_delta
|
||||
) {
|
||||
watchdogs->system_watchdog_delta = delta;
|
||||
_Watchdog_Release( &watchdogs->Header, &lock_context );
|
||||
|
||||
_Watchdog_Remove( system_header, &watchdogs->System_watchdog );
|
||||
watchdogs->System_watchdog.initial = delta;
|
||||
_Watchdog_Insert( system_header, &watchdogs->System_watchdog );
|
||||
|
||||
_Watchdog_Acquire( &watchdogs->Header, &lock_context );
|
||||
}
|
||||
}
|
||||
} while ( watchdogs->generation != my_generation );
|
||||
|
||||
watchdogs->system_watchdog_helper = NULL;
|
||||
}
|
||||
|
||||
_Watchdog_Release( &watchdogs->Header, &lock_context );
|
||||
}
|
||||
|
||||
static void _Timer_server_Insert_timer(
|
||||
Timer_server_Watchdogs *watchdogs,
|
||||
Timer_Control *timer,
|
||||
Watchdog_Header *system_header,
|
||||
Watchdog_Interval (*get_ticks)( void )
|
||||
)
|
||||
{
|
||||
ISR_lock_Context lock_context;
|
||||
Watchdog_Interval now;
|
||||
Watchdog_Interval delta;
|
||||
|
||||
_Watchdog_Acquire( &watchdogs->Header, &lock_context );
|
||||
|
||||
now = (*get_ticks)();
|
||||
delta = now - watchdogs->last_snapshot;
|
||||
watchdogs->last_snapshot = now;
|
||||
watchdogs->current_snapshot = now;
|
||||
|
||||
if ( watchdogs->system_watchdog_delta > delta ) {
|
||||
watchdogs->system_watchdog_delta -= delta;
|
||||
} else {
|
||||
watchdogs->system_watchdog_delta = 0;
|
||||
}
|
||||
|
||||
if ( !_Watchdog_Is_empty( &watchdogs->Header ) ) {
|
||||
Watchdog_Control *first = _Watchdog_First( &watchdogs->Header );
|
||||
|
||||
if ( first->delta_interval > delta ) {
|
||||
first->delta_interval -= delta;
|
||||
} else {
|
||||
first->delta_interval = 0;
|
||||
}
|
||||
}
|
||||
|
||||
_Watchdog_Insert_locked(
|
||||
&watchdogs->Header,
|
||||
&timer->Ticker,
|
||||
&lock_context
|
||||
);
|
||||
|
||||
++watchdogs->generation;
|
||||
|
||||
_Watchdog_Release( &watchdogs->Header, &lock_context );
|
||||
|
||||
_Timer_server_Update_system_watchdog( watchdogs, system_header );
|
||||
}
|
||||
|
||||
static void _Timer_server_Schedule_operation_method(
|
||||
Timer_server_Control *ts,
|
||||
Timer_Control *timer
|
||||
)
|
||||
{
|
||||
if ( ts->insert_chain == NULL ) {
|
||||
_Timer_server_Insert_timer_and_make_snapshot( ts, timer );
|
||||
} else {
|
||||
/*
|
||||
* We interrupted a critical section of the timer server. The timer
|
||||
* server is not preemptible, so we must be in interrupt context here. No
|
||||
* thread dispatch will happen until the timer server finishes its
|
||||
* critical section. We have to use the protected chain methods because
|
||||
* we may be interrupted by a higher priority interrupt.
|
||||
*/
|
||||
_Chain_Append( ts->insert_chain, &timer->Object.Node );
|
||||
}
|
||||
}
|
||||
|
||||
static void _Timer_server_Process_interval_watchdogs(
|
||||
Timer_server_Watchdogs *watchdogs,
|
||||
Chain_Control *fire_chain
|
||||
)
|
||||
{
|
||||
Watchdog_Interval snapshot = _Watchdog_Ticks_since_boot;
|
||||
|
||||
/*
|
||||
* We assume adequate unsigned arithmetic here.
|
||||
*/
|
||||
Watchdog_Interval delta = snapshot - watchdogs->last_snapshot;
|
||||
|
||||
watchdogs->last_snapshot = snapshot;
|
||||
|
||||
_Watchdog_Adjust_to_chain( &watchdogs->Header, delta, fire_chain );
|
||||
}
|
||||
|
||||
static void _Timer_server_Process_tod_watchdogs(
|
||||
Timer_server_Watchdogs *watchdogs,
|
||||
Chain_Control *fire_chain
|
||||
)
|
||||
{
|
||||
Watchdog_Interval snapshot = (Watchdog_Interval) _TOD_Seconds_since_epoch();
|
||||
Watchdog_Interval last_snapshot = watchdogs->last_snapshot;
|
||||
Watchdog_Interval delta;
|
||||
|
||||
/*
|
||||
* 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 watchdogs->Header to indicate this.
|
||||
*/
|
||||
if ( snapshot > last_snapshot ) {
|
||||
/*
|
||||
* This path is for normal forward movement and cases where the
|
||||
* TOD has been set forward.
|
||||
*/
|
||||
delta = snapshot - last_snapshot;
|
||||
_Watchdog_Adjust_to_chain( &watchdogs->Header, delta, fire_chain );
|
||||
|
||||
} else if ( snapshot < last_snapshot ) {
|
||||
/*
|
||||
* The current TOD is before the last TOD which indicates that
|
||||
* TOD has been set backwards.
|
||||
*/
|
||||
delta = last_snapshot - snapshot;
|
||||
_Watchdog_Adjust_backward( &watchdogs->Header, delta );
|
||||
}
|
||||
|
||||
watchdogs->last_snapshot = snapshot;
|
||||
}
|
||||
|
||||
static void _Timer_server_Process_insertions( Timer_server_Control *ts )
|
||||
{
|
||||
while ( true ) {
|
||||
Timer_Control *timer = (Timer_Control *) _Chain_Get( ts->insert_chain );
|
||||
|
||||
if ( timer == NULL ) {
|
||||
break;
|
||||
}
|
||||
|
||||
_Timer_server_Insert_timer( ts, timer );
|
||||
}
|
||||
}
|
||||
|
||||
static void _Timer_server_Get_watchdogs_that_fire_now(
|
||||
Timer_server_Control *ts,
|
||||
Chain_Control *insert_chain,
|
||||
Chain_Control *fire_chain
|
||||
)
|
||||
{
|
||||
/*
|
||||
* Afterwards all timer inserts are directed to this chain and the interval
|
||||
* and TOD chains will be no more modified by other parties.
|
||||
*/
|
||||
ts->insert_chain = insert_chain;
|
||||
|
||||
while ( true ) {
|
||||
ISR_Level level;
|
||||
|
||||
/*
|
||||
* Remove all the watchdogs that need to fire so we can invoke them.
|
||||
*/
|
||||
_Timer_server_Process_interval_watchdogs(
|
||||
if ( timer->the_class == TIMER_INTERVAL_ON_TASK ) {
|
||||
_Timer_server_Insert_timer(
|
||||
&ts->Interval_watchdogs,
|
||||
fire_chain
|
||||
timer,
|
||||
&_Watchdog_Ticks_header,
|
||||
_Timer_server_Get_ticks
|
||||
);
|
||||
} else if ( timer->the_class == TIMER_TIME_OF_DAY_ON_TASK ) {
|
||||
_Timer_server_Insert_timer(
|
||||
&ts->TOD_watchdogs,
|
||||
timer,
|
||||
&_Watchdog_Seconds_header,
|
||||
_Timer_server_Get_seconds
|
||||
);
|
||||
_Timer_server_Process_tod_watchdogs( &ts->TOD_watchdogs, fire_chain );
|
||||
|
||||
/*
|
||||
* The insertions have to take place here, because they reference the
|
||||
* current time. The previous process methods take a snapshot of the
|
||||
* current time. In case someone inserts a watchdog with an initial value
|
||||
* of zero it will be processed in the next iteration of the timer server
|
||||
* body loop.
|
||||
*/
|
||||
_Timer_server_Process_insertions( ts );
|
||||
|
||||
_ISR_Disable( level );
|
||||
if ( _Chain_Is_empty( insert_chain ) ) {
|
||||
ts->insert_chain = NULL;
|
||||
_ISR_Enable( level );
|
||||
|
||||
break;
|
||||
} else {
|
||||
_ISR_Enable( level );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* FIXME: This locking approach for SMP is improvable! */
|
||||
|
||||
static void _Timer_server_SMP_lock_aquire( void )
|
||||
static void _Timer_server_Update_current_snapshot(
|
||||
Timer_server_Watchdogs *watchdogs,
|
||||
Watchdog_Interval (*get_ticks)( void )
|
||||
)
|
||||
{
|
||||
#if defined( RTEMS_SMP )
|
||||
_Thread_Disable_dispatch();
|
||||
#endif
|
||||
ISR_lock_Context lock_context;
|
||||
|
||||
_Watchdog_Acquire( &watchdogs->Header, &lock_context );
|
||||
watchdogs->current_snapshot = (*get_ticks)();
|
||||
watchdogs->system_watchdog_delta = 0;
|
||||
_Watchdog_Release( &watchdogs->Header, &lock_context );
|
||||
}
|
||||
|
||||
static void _Timer_server_SMP_lock_release( void )
|
||||
static void _Timer_server_Tickle(
|
||||
Timer_server_Watchdogs *watchdogs,
|
||||
Watchdog_Header *system_header,
|
||||
Watchdog_Interval (*get_ticks)( void ),
|
||||
bool ticks
|
||||
)
|
||||
{
|
||||
#if defined( RTEMS_SMP )
|
||||
_Thread_Enable_dispatch();
|
||||
#endif
|
||||
ISR_lock_Context lock_context;
|
||||
Watchdog_Interval now;
|
||||
Watchdog_Interval last;
|
||||
|
||||
_Watchdog_Acquire( &watchdogs->Header, &lock_context );
|
||||
|
||||
now = watchdogs->current_snapshot;
|
||||
last = watchdogs->last_snapshot;
|
||||
watchdogs->last_snapshot = now;
|
||||
|
||||
if ( ticks || now >= last ) {
|
||||
_Watchdog_Adjust_forward_locked(
|
||||
&watchdogs->Header,
|
||||
now - last,
|
||||
&lock_context
|
||||
);
|
||||
} else {
|
||||
_Watchdog_Adjust_backward_locked(
|
||||
&watchdogs->Header,
|
||||
last - now
|
||||
);
|
||||
}
|
||||
|
||||
++watchdogs->generation;
|
||||
|
||||
_Watchdog_Release( &watchdogs->Header, &lock_context );
|
||||
|
||||
_Timer_server_Update_system_watchdog( watchdogs, system_header );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -380,83 +236,75 @@ static rtems_task _Timer_server_Body(
|
||||
)
|
||||
{
|
||||
Timer_server_Control *ts = (Timer_server_Control *) arg;
|
||||
Chain_Control insert_chain;
|
||||
Chain_Control fire_chain;
|
||||
|
||||
_Chain_Initialize_empty( &insert_chain );
|
||||
_Chain_Initialize_empty( &fire_chain );
|
||||
|
||||
_Timer_server_SMP_lock_aquire();
|
||||
|
||||
while ( true ) {
|
||||
_Timer_server_Get_watchdogs_that_fire_now( ts, &insert_chain, &fire_chain );
|
||||
rtems_event_set events;
|
||||
|
||||
if ( !_Chain_Is_empty( &fire_chain ) ) {
|
||||
/*
|
||||
* Fire the watchdogs.
|
||||
*/
|
||||
while ( true ) {
|
||||
Watchdog_Control *watchdog;
|
||||
ISR_Level level;
|
||||
_Timer_server_Tickle(
|
||||
&ts->Interval_watchdogs,
|
||||
&_Watchdog_Ticks_header,
|
||||
_Timer_server_Get_ticks,
|
||||
true
|
||||
);
|
||||
|
||||
/*
|
||||
* It is essential that interrupts are disable here since an interrupt
|
||||
* service routine may remove a watchdog from the chain.
|
||||
*/
|
||||
_ISR_Disable( level );
|
||||
watchdog = (Watchdog_Control *) _Chain_Get_unprotected( &fire_chain );
|
||||
if ( watchdog != NULL ) {
|
||||
watchdog->state = WATCHDOG_INACTIVE;
|
||||
_ISR_Enable( level );
|
||||
} else {
|
||||
_ISR_Enable( level );
|
||||
_Timer_server_Tickle(
|
||||
&ts->TOD_watchdogs,
|
||||
&_Watchdog_Seconds_header,
|
||||
_Timer_server_Get_seconds,
|
||||
false
|
||||
);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
_Timer_server_SMP_lock_release();
|
||||
|
||||
/*
|
||||
* The timer server may block here and wait for resources or time.
|
||||
* The system watchdogs are inactive and will remain inactive since
|
||||
* the active flag of the timer server is true.
|
||||
*/
|
||||
(*watchdog->routine)( watchdog->id, watchdog->user_data );
|
||||
|
||||
_Timer_server_SMP_lock_aquire();
|
||||
}
|
||||
} else {
|
||||
ts->active = false;
|
||||
|
||||
/*
|
||||
* Block until there is something to do.
|
||||
*/
|
||||
#if !defined( RTEMS_SMP )
|
||||
_Thread_Disable_dispatch();
|
||||
#endif
|
||||
_Thread_Set_state( ts->thread, STATES_DELAYING );
|
||||
_Timer_server_Reset_interval_system_watchdog( ts );
|
||||
_Timer_server_Reset_tod_system_watchdog( ts );
|
||||
#if !defined( RTEMS_SMP )
|
||||
_Thread_Enable_dispatch();
|
||||
#endif
|
||||
|
||||
_Timer_server_SMP_lock_release();
|
||||
_Timer_server_SMP_lock_aquire();
|
||||
|
||||
ts->active = true;
|
||||
|
||||
/*
|
||||
* Maybe an interrupt did reset the system timers, so we have to stop
|
||||
* them here. Since we are active now, there will be no more resets
|
||||
* until we are inactive again.
|
||||
*/
|
||||
_Timer_server_Stop_interval_system_watchdog( ts );
|
||||
_Timer_server_Stop_tod_system_watchdog( ts );
|
||||
}
|
||||
(void) rtems_event_system_receive(
|
||||
RTEMS_EVENT_SYSTEM_TIMER_SERVER,
|
||||
RTEMS_EVENT_ALL | RTEMS_WAIT,
|
||||
RTEMS_NO_TIMEOUT,
|
||||
&events
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
static void _Timer_server_Wakeup(
|
||||
Objects_Id id,
|
||||
void *arg
|
||||
)
|
||||
{
|
||||
Timer_server_Control *ts = arg;
|
||||
|
||||
_Timer_server_Update_current_snapshot(
|
||||
&ts->Interval_watchdogs,
|
||||
_Timer_server_Get_ticks
|
||||
);
|
||||
|
||||
_Timer_server_Update_current_snapshot(
|
||||
&ts->TOD_watchdogs,
|
||||
_Timer_server_Get_seconds
|
||||
);
|
||||
|
||||
(void) rtems_event_system_send( id, RTEMS_EVENT_SYSTEM_TIMER_SERVER );
|
||||
}
|
||||
|
||||
static void _Timer_server_Initialize_watchdogs(
|
||||
Timer_server_Control *ts,
|
||||
rtems_id id,
|
||||
Timer_server_Watchdogs *watchdogs,
|
||||
Watchdog_Interval (*get_ticks)( void )
|
||||
)
|
||||
{
|
||||
Watchdog_Interval now;
|
||||
|
||||
now = (*get_ticks)();
|
||||
watchdogs->last_snapshot = now;
|
||||
watchdogs->current_snapshot = now;
|
||||
|
||||
_Watchdog_Header_initialize( &watchdogs->Header );
|
||||
_Watchdog_Initialize(
|
||||
&watchdogs->System_watchdog,
|
||||
_Timer_server_Wakeup,
|
||||
id,
|
||||
ts
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief rtems_timer_initiate_server
|
||||
*
|
||||
@@ -542,36 +390,18 @@ rtems_status_code rtems_timer_initiate_server(
|
||||
* Timer Server so we do not have to have a critical section.
|
||||
*/
|
||||
|
||||
/*
|
||||
* We work with the TCB pointer, not the ID, so we need to convert
|
||||
* to a TCB pointer from here out.
|
||||
*/
|
||||
ts->thread = (Thread_Control *)_Objects_Get_local_object(
|
||||
&_RTEMS_tasks_Information,
|
||||
_Objects_Get_index(id)
|
||||
_Timer_server_Initialize_watchdogs(
|
||||
ts,
|
||||
id,
|
||||
&ts->Interval_watchdogs,
|
||||
_Timer_server_Get_ticks
|
||||
);
|
||||
|
||||
/*
|
||||
* Initialize the timer lists that the server will manage.
|
||||
*/
|
||||
_Watchdog_Header_initialize( &ts->Interval_watchdogs.Header );
|
||||
_Watchdog_Header_initialize( &ts->TOD_watchdogs.Header );
|
||||
|
||||
/*
|
||||
* Initialize the timers that will be used to control when the
|
||||
* Timer Server wakes up and services the task-based timers.
|
||||
*/
|
||||
_Watchdog_Initialize(
|
||||
&ts->Interval_watchdogs.System_watchdog,
|
||||
_Thread_Delay_ended,
|
||||
0,
|
||||
ts->thread
|
||||
);
|
||||
_Watchdog_Initialize(
|
||||
&ts->TOD_watchdogs.System_watchdog,
|
||||
_Thread_Delay_ended,
|
||||
0,
|
||||
ts->thread
|
||||
_Timer_server_Initialize_watchdogs(
|
||||
ts,
|
||||
id,
|
||||
&ts->TOD_watchdogs,
|
||||
_Timer_server_Get_seconds
|
||||
);
|
||||
|
||||
/*
|
||||
@@ -581,12 +411,6 @@ rtems_status_code rtems_timer_initiate_server(
|
||||
ts->cancel = _Timer_server_Cancel_method;
|
||||
ts->schedule_operation = _Timer_server_Schedule_operation_method;
|
||||
|
||||
ts->Interval_watchdogs.last_snapshot = _Watchdog_Ticks_since_boot;
|
||||
ts->TOD_watchdogs.last_snapshot = (Watchdog_Interval) _TOD_Seconds_since_epoch();
|
||||
|
||||
ts->insert_chain = NULL;
|
||||
ts->active = false;
|
||||
|
||||
/*
|
||||
* The default timer server is now available.
|
||||
*/
|
||||
|
||||
@@ -324,7 +324,7 @@ 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/watchdogadjusttochain.c src/watchdoginsert.c src/watchdogremove.c
|
||||
src/watchdoginsert.c src/watchdogremove.c
|
||||
libscore_a_SOURCES += src/watchdogtickssinceboot.c
|
||||
|
||||
## USEREXT_C_FILES
|
||||
|
||||
@@ -164,6 +164,22 @@ void _Watchdog_Adjust_backward(
|
||||
Watchdog_Interval units
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Adjusts the watchdogs in backward direction in a locked context.
|
||||
*
|
||||
* The caller must be the owner of the watchdog lock and will be the owner
|
||||
* after the call.
|
||||
*
|
||||
* @param[in] header The watchdog header.
|
||||
* @param[in] units The units of ticks to adjust.
|
||||
*
|
||||
* @see _Watchdog_Adjust_forward().
|
||||
*/
|
||||
void _Watchdog_Adjust_backward_locked(
|
||||
Watchdog_Header *header,
|
||||
Watchdog_Interval units
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Adjusts the header watchdog chain in the forward direction for units
|
||||
* ticks.
|
||||
@@ -179,24 +195,22 @@ void _Watchdog_Adjust_forward(
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Adjusts the @a header watchdog chain in the forward
|
||||
* @a direction for @a units_arg ticks.
|
||||
* @brief Adjusts the watchdogs in forward direction in a locked context.
|
||||
*
|
||||
* This routine adjusts the @a header watchdog chain in the forward
|
||||
* @a direction for @a units_arg ticks.
|
||||
* The caller must be the owner of the watchdog lock and will be the owner
|
||||
* after the call. This function may release and acquire the watchdog lock
|
||||
* internally.
|
||||
*
|
||||
* @param[in] header is the watchdog chain to adjust
|
||||
* @param[in] units_arg 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.
|
||||
* @param[in] header The watchdog header.
|
||||
* @param[in] units The units of ticks to adjust.
|
||||
* @param[in] lock_context The lock context.
|
||||
*
|
||||
* @note This always adjusts forward.
|
||||
* @see _Watchdog_Adjust_forward().
|
||||
*/
|
||||
void _Watchdog_Adjust_to_chain(
|
||||
void _Watchdog_Adjust_forward_locked(
|
||||
Watchdog_Header *header,
|
||||
Watchdog_Interval units_arg,
|
||||
Chain_Control *to_fire
|
||||
|
||||
Watchdog_Interval units,
|
||||
ISR_lock_Context *lock_context
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -215,6 +229,25 @@ void _Watchdog_Insert (
|
||||
Watchdog_Control *the_watchdog
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Inserts the watchdog in a locked context.
|
||||
*
|
||||
* The caller must be the owner of the watchdog lock and will be the owner
|
||||
* after the call. This function may release and acquire the watchdog lock
|
||||
* internally.
|
||||
*
|
||||
* @param[in] header The watchdog header.
|
||||
* @param[in] the_watchdog The watchdog.
|
||||
* @param[in] lock_context The lock context.
|
||||
*
|
||||
* @see _Watchdog_Insert().
|
||||
*/
|
||||
void _Watchdog_Insert_locked(
|
||||
Watchdog_Header *header,
|
||||
Watchdog_Control *the_watchdog,
|
||||
ISR_lock_Context *lock_context
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief This routine is invoked at appropriate intervals to update
|
||||
* the @a header watchdog chain.
|
||||
|
||||
@@ -19,8 +19,16 @@
|
||||
#endif
|
||||
|
||||
#include <rtems/score/watchdogimpl.h>
|
||||
#include <rtems/score/chainimpl.h>
|
||||
#include <rtems/score/isrlevel.h>
|
||||
|
||||
void _Watchdog_Adjust_backward_locked(
|
||||
Watchdog_Header *header,
|
||||
Watchdog_Interval units
|
||||
)
|
||||
{
|
||||
if ( !_Watchdog_Is_empty( header ) ) {
|
||||
_Watchdog_First( header )->delta_interval += units;
|
||||
}
|
||||
}
|
||||
|
||||
void _Watchdog_Adjust_backward(
|
||||
Watchdog_Header *header,
|
||||
@@ -30,23 +38,16 @@ void _Watchdog_Adjust_backward(
|
||||
ISR_lock_Context lock_context;
|
||||
|
||||
_Watchdog_Acquire( header, &lock_context );
|
||||
|
||||
if ( !_Watchdog_Is_empty( header ) ) {
|
||||
_Watchdog_First( header )->delta_interval += units;
|
||||
}
|
||||
|
||||
_Watchdog_Adjust_backward_locked( header, units );
|
||||
_Watchdog_Release( header, &lock_context );
|
||||
}
|
||||
|
||||
void _Watchdog_Adjust_forward(
|
||||
void _Watchdog_Adjust_forward_locked(
|
||||
Watchdog_Header *header,
|
||||
Watchdog_Interval units
|
||||
Watchdog_Interval units,
|
||||
ISR_lock_Context *lock_context
|
||||
)
|
||||
{
|
||||
ISR_lock_Context lock_context;
|
||||
|
||||
_Watchdog_Acquire( header, &lock_context );
|
||||
|
||||
while ( !_Watchdog_Is_empty( header ) && units > 0 ) {
|
||||
Watchdog_Control *first = _Watchdog_First( header );
|
||||
|
||||
@@ -57,13 +58,23 @@ void _Watchdog_Adjust_forward(
|
||||
units -= first->delta_interval;
|
||||
first->delta_interval = 1;
|
||||
|
||||
_Watchdog_Release( header, &lock_context );
|
||||
_Watchdog_Release( header, lock_context );
|
||||
|
||||
_Watchdog_Tickle( header );
|
||||
|
||||
_Watchdog_Acquire( header, &lock_context );
|
||||
_Watchdog_Acquire( header, lock_context );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _Watchdog_Adjust_forward(
|
||||
Watchdog_Header *header,
|
||||
Watchdog_Interval units
|
||||
)
|
||||
{
|
||||
ISR_lock_Context lock_context;
|
||||
|
||||
_Watchdog_Acquire( header, &lock_context );
|
||||
_Watchdog_Adjust_forward_locked( header, units, &lock_context );
|
||||
_Watchdog_Release( header, &lock_context );
|
||||
}
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @brief Watchdog Adjust to Chain
|
||||
* @ingroup ScoreWatchdog
|
||||
*/
|
||||
|
||||
/*
|
||||
* COPYRIGHT (c) 1989-2009.
|
||||
* 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.org/license/LICENSE.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <rtems/score/watchdogimpl.h>
|
||||
#include <rtems/score/isrlevel.h>
|
||||
|
||||
void _Watchdog_Adjust_to_chain(
|
||||
Watchdog_Header *header,
|
||||
Watchdog_Interval units_arg,
|
||||
Chain_Control *to_fire
|
||||
|
||||
)
|
||||
{
|
||||
Watchdog_Interval units = units_arg;
|
||||
ISR_lock_Context lock_context;
|
||||
Watchdog_Control *first;
|
||||
|
||||
_Watchdog_Acquire( header, &lock_context );
|
||||
|
||||
while ( 1 ) {
|
||||
if ( _Watchdog_Is_empty( header ) ) {
|
||||
break;
|
||||
}
|
||||
first = _Watchdog_First( header );
|
||||
|
||||
/*
|
||||
* If it is longer than "units" until the first element on the chain
|
||||
* fires, then bump it and quit.
|
||||
*/
|
||||
if ( units < first->delta_interval ) {
|
||||
first->delta_interval -= units;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* The first set happens in less than units, so take all of them
|
||||
* off the chain and adjust units to reflect this.
|
||||
*/
|
||||
units -= first->delta_interval;
|
||||
first->delta_interval = 0;
|
||||
|
||||
while ( 1 ) {
|
||||
_Chain_Extract_unprotected( &first->Node );
|
||||
_Chain_Append_unprotected( to_fire, &first->Node );
|
||||
|
||||
_Watchdog_Flash( header, &lock_context );
|
||||
|
||||
if ( _Watchdog_Is_empty( header ) )
|
||||
break;
|
||||
first = _Watchdog_First( header );
|
||||
if ( first->delta_interval != 0 )
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_Watchdog_Release( header, &lock_context );
|
||||
}
|
||||
|
||||
@@ -47,15 +47,12 @@ static void _Watchdog_Insert_fixup(
|
||||
}
|
||||
}
|
||||
|
||||
void _Watchdog_Insert(
|
||||
void _Watchdog_Insert_locked(
|
||||
Watchdog_Header *header,
|
||||
Watchdog_Control *the_watchdog
|
||||
Watchdog_Control *the_watchdog,
|
||||
ISR_lock_Context *lock_context
|
||||
)
|
||||
{
|
||||
ISR_lock_Context lock_context;
|
||||
|
||||
_Watchdog_Acquire( header, &lock_context );
|
||||
|
||||
if ( the_watchdog->state == WATCHDOG_INACTIVE ) {
|
||||
Watchdog_Iterator iterator;
|
||||
Chain_Node *current;
|
||||
@@ -86,7 +83,7 @@ void _Watchdog_Insert(
|
||||
iterator.delta_interval = delta - delta_next;
|
||||
iterator.current = next;
|
||||
|
||||
_Watchdog_Flash( header, &lock_context );
|
||||
_Watchdog_Flash( header, lock_context );
|
||||
|
||||
if ( the_watchdog->state != WATCHDOG_BEING_INSERTED ) {
|
||||
goto abort_insert;
|
||||
@@ -105,6 +102,16 @@ abort_insert:
|
||||
|
||||
_Chain_Extract_unprotected( &iterator.Node );
|
||||
}
|
||||
}
|
||||
|
||||
void _Watchdog_Insert(
|
||||
Watchdog_Header *header,
|
||||
Watchdog_Control *the_watchdog
|
||||
)
|
||||
{
|
||||
ISR_lock_Context lock_context;
|
||||
|
||||
_Watchdog_Acquire( header, &lock_context );
|
||||
_Watchdog_Insert_locked( header, the_watchdog, &lock_context );
|
||||
_Watchdog_Release( header, &lock_context );
|
||||
}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
/*
|
||||
* Copyright (c) 2009
|
||||
* embedded brains GmbH
|
||||
* Obere Lagerstr. 30
|
||||
* D-82178 Puchheim
|
||||
* Germany
|
||||
* <rtems@embedded-brains.de>
|
||||
* Copyright (c) 2009-2014 embedded brains GmbH.
|
||||
*
|
||||
* embedded brains GmbH
|
||||
* Dornierstr. 4
|
||||
* 82178 Puchheim
|
||||
* Germany
|
||||
* <rtems@embedded-brains.de>
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
@@ -22,141 +23,91 @@
|
||||
|
||||
const char rtems_test_name[] = "SPINTRCRITICAL 17";
|
||||
|
||||
/* forward declarations to avoid warnings */
|
||||
rtems_task Init(rtems_task_argument argument);
|
||||
typedef struct {
|
||||
rtems_id timer1;
|
||||
rtems_id timer2;
|
||||
bool done;
|
||||
} test_context;
|
||||
|
||||
#define TIMER_COUNT 4
|
||||
static test_context ctx_instance;
|
||||
|
||||
#define TIMER_TRIGGER 0
|
||||
#define TIMER_RESET 1
|
||||
#define TIMER_NEVER_INTERVAL 2
|
||||
#define TIMER_NEVER_TOD 3
|
||||
|
||||
static rtems_id timer [TIMER_COUNT];
|
||||
|
||||
static rtems_time_of_day tod;
|
||||
|
||||
static volatile bool case_hit;
|
||||
|
||||
static void never_callback(rtems_id timer, void *arg)
|
||||
static void never(rtems_id timer_id, void *arg)
|
||||
{
|
||||
rtems_test_assert(false);
|
||||
rtems_test_assert(0);
|
||||
}
|
||||
|
||||
static void reset_tod_timer(void)
|
||||
static void fire(rtems_id timer_id, void *arg)
|
||||
{
|
||||
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||
/* The arg is NULL */
|
||||
test_context *ctx = &ctx_instance;
|
||||
rtems_status_code sc;
|
||||
|
||||
sc = rtems_timer_server_fire_when(
|
||||
timer [TIMER_NEVER_TOD],
|
||||
&tod,
|
||||
never_callback,
|
||||
NULL
|
||||
);
|
||||
directive_failed_with_level(sc, "rtems_timer_server_fire_after", -1);
|
||||
}
|
||||
if (!ctx->done) {
|
||||
ctx->done =
|
||||
_Timer_server->Interval_watchdogs.system_watchdog_helper != NULL;
|
||||
|
||||
static void reset_callback(rtems_id timer_id, void *arg)
|
||||
{
|
||||
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||
|
||||
sc = rtems_timer_reset(timer [TIMER_RESET]);
|
||||
directive_failed_with_level(sc, "rtems_timer_reset", -1);
|
||||
|
||||
sc = rtems_timer_reset(timer [TIMER_NEVER_INTERVAL]);
|
||||
directive_failed_with_level(sc, "rtems_timer_reset", -1);
|
||||
|
||||
reset_tod_timer();
|
||||
|
||||
if (!case_hit) {
|
||||
case_hit = _Timer_server->insert_chain != NULL;
|
||||
if (ctx->done) {
|
||||
sc = rtems_timer_server_fire_after(ctx->timer2, 100, never, NULL);
|
||||
rtems_test_assert(sc == RTEMS_SUCCESSFUL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void trigger_callback(rtems_id timer_id, void *arg)
|
||||
static bool test_body(void *arg)
|
||||
{
|
||||
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||
test_context *ctx = arg;
|
||||
rtems_status_code sc;
|
||||
|
||||
if (case_hit) {
|
||||
TEST_END();
|
||||
sc = rtems_timer_reset(ctx->timer1);
|
||||
rtems_test_assert(sc == RTEMS_SUCCESSFUL);
|
||||
|
||||
rtems_test_exit(0);
|
||||
} else if (interrupt_critical_section_test_support_delay()) {
|
||||
puts("test case not hit, give up");
|
||||
|
||||
rtems_test_exit(0);
|
||||
}
|
||||
|
||||
sc = rtems_timer_reset(timer [TIMER_TRIGGER]);
|
||||
directive_failed(sc, "rtems_timer_reset");
|
||||
return ctx->done;
|
||||
}
|
||||
|
||||
rtems_task Init( rtems_task_argument ignored )
|
||||
static void Init(rtems_task_argument ignored)
|
||||
{
|
||||
rtems_status_code sc = RTEMS_SUCCESSFUL;
|
||||
size_t i = 0;
|
||||
test_context *ctx = &ctx_instance;
|
||||
rtems_status_code sc;
|
||||
|
||||
TEST_BEGIN();
|
||||
|
||||
build_time(&tod, 4, 12, 2009, 9, 34, 11, 0);
|
||||
sc = rtems_clock_set(&tod);
|
||||
directive_failed(sc, "rtems_clock_set");
|
||||
sc = rtems_timer_create(
|
||||
rtems_build_name('T', 'I', 'M', '1'),
|
||||
&ctx->timer1
|
||||
);
|
||||
rtems_test_assert(sc == RTEMS_SUCCESSFUL);
|
||||
|
||||
++tod.year;
|
||||
|
||||
for (i = 0; i < TIMER_COUNT; ++i) {
|
||||
sc = rtems_timer_create(
|
||||
rtems_build_name('T', 'I', 'M', '0' + i),
|
||||
&timer [i]
|
||||
);
|
||||
directive_failed(sc, "rtems_timer_create");
|
||||
}
|
||||
sc = rtems_timer_create(
|
||||
rtems_build_name('T', 'I', 'M', '2'),
|
||||
&ctx->timer2
|
||||
);
|
||||
rtems_test_assert(sc == RTEMS_SUCCESSFUL);
|
||||
|
||||
sc = rtems_timer_initiate_server(
|
||||
RTEMS_MINIMUM_PRIORITY,
|
||||
RTEMS_MINIMUM_STACK_SIZE,
|
||||
RTEMS_DEFAULT_ATTRIBUTES
|
||||
);
|
||||
directive_failed(sc, "rtems_timer_initiate_server");
|
||||
rtems_test_assert(sc == RTEMS_SUCCESSFUL);
|
||||
|
||||
sc = rtems_timer_server_fire_after(
|
||||
timer [TIMER_NEVER_INTERVAL],
|
||||
2,
|
||||
never_callback,
|
||||
NULL
|
||||
);
|
||||
directive_failed(sc, "rtems_timer_server_fire_after");
|
||||
sc = rtems_timer_server_fire_after(ctx->timer1, 1000, never, NULL);
|
||||
rtems_test_assert(sc == RTEMS_SUCCESSFUL);
|
||||
|
||||
reset_tod_timer();
|
||||
interrupt_critical_section_test(test_body, ctx, fire);
|
||||
rtems_test_assert(ctx->done);
|
||||
|
||||
sc = rtems_timer_fire_after(
|
||||
timer [TIMER_RESET],
|
||||
1,
|
||||
reset_callback,
|
||||
NULL
|
||||
);
|
||||
directive_failed(sc, "rtems_timer_fire_after");
|
||||
|
||||
sc = rtems_timer_server_fire_after(
|
||||
timer [TIMER_TRIGGER],
|
||||
1,
|
||||
trigger_callback,
|
||||
NULL
|
||||
);
|
||||
directive_failed(sc, "rtems_timer_server_fire_after");
|
||||
|
||||
interrupt_critical_section_test_support_initialize(NULL);
|
||||
|
||||
rtems_task_delete(RTEMS_SELF);
|
||||
TEST_END();
|
||||
rtems_test_exit(0);
|
||||
}
|
||||
|
||||
#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
|
||||
#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
|
||||
|
||||
#define CONFIGURE_MICROSECONDS_PER_TICK 2000
|
||||
#define CONFIGURE_MICROSECONDS_PER_TICK 1000
|
||||
|
||||
#define CONFIGURE_MAXIMUM_TASKS 2
|
||||
#define CONFIGURE_MAXIMUM_TIMERS 4
|
||||
#define CONFIGURE_MAXIMUM_TIMERS 3
|
||||
#define CONFIGURE_MAXIMUM_USER_EXTENSIONS 1
|
||||
|
||||
#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright (c) 2009 embedded brains GmbH.
|
||||
# Copyright (c) 2009-2015 embedded brains GmbH.
|
||||
#
|
||||
# The license and distribution terms for this file may be
|
||||
# found in the file LICENSE in this distribution or at
|
||||
@@ -11,9 +11,7 @@ test set name: spintrcritical17
|
||||
|
||||
directives:
|
||||
|
||||
_Timer_server_Get_watchdogs_that_fire_now
|
||||
_Timer_server_Schedule_operation_method
|
||||
_Timer_server_Process_insertions
|
||||
_Timer_server_Update_system_watchdog
|
||||
|
||||
concepts:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user