From 03b900d3ed120ea919ea3eded7edbece3488cff3 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Thu, 18 Feb 2016 08:36:26 +0100 Subject: score: Replace watchdog handler implementation Use a red-black tree instead of delta chains. Close #2344. Update #2554. Update #2555. Close #2606. --- cpukit/rtems/src/eventseize.c | 11 +- cpukit/rtems/src/eventsurrender.c | 2 +- cpukit/rtems/src/ratemoncancel.c | 5 +- cpukit/rtems/src/ratemoncreate.c | 3 +- cpukit/rtems/src/ratemondelete.c | 5 +- cpukit/rtems/src/ratemonperiod.c | 38 ++- cpukit/rtems/src/ratemontimeout.c | 50 ++-- cpukit/rtems/src/taskwakeafter.c | 9 +- cpukit/rtems/src/taskwakewhen.c | 18 +- cpukit/rtems/src/timercancel.c | 31 +-- cpukit/rtems/src/timercreate.c | 179 +++++++++++++-- cpukit/rtems/src/timerdelete.c | 14 +- cpukit/rtems/src/timerfireafter.c | 64 +----- cpukit/rtems/src/timerfirewhen.c | 50 +--- cpukit/rtems/src/timergetinfo.c | 13 +- cpukit/rtems/src/timerreset.c | 41 ++-- cpukit/rtems/src/timerserver.c | 394 ++++++++------------------------ cpukit/rtems/src/timerserverfireafter.c | 68 +----- cpukit/rtems/src/timerserverfirewhen.c | 70 +----- 19 files changed, 387 insertions(+), 678 deletions(-) (limited to 'cpukit/rtems/src') diff --git a/cpukit/rtems/src/eventseize.c b/cpukit/rtems/src/eventseize.c index 3dc554f61b..0be6bd6f45 100644 --- a/cpukit/rtems/src/eventseize.c +++ b/cpukit/rtems/src/eventseize.c @@ -90,13 +90,12 @@ void _Event_Seize( if ( ticks ) { _Thread_Wait_set_timeout_code( executing, RTEMS_TIMEOUT ); - _Watchdog_Initialize( - &executing->Timer, + _Thread_Timer_insert_relative( + executing, + cpu_self, _Thread_Timeout, - 0, - executing + ticks ); - _Watchdog_Insert_ticks( &executing->Timer, ticks ); } _Thread_Set_state( executing, block_state ); @@ -113,7 +112,7 @@ void _Event_Seize( wait_class | THREAD_WAIT_STATE_BLOCKED ); if ( !success ) { - _Watchdog_Remove_ticks( &executing->Timer ); + _Thread_Timer_remove( executing ); _Thread_Unblock( executing ); } diff --git a/cpukit/rtems/src/eventsurrender.c b/cpukit/rtems/src/eventsurrender.c index 5726cc8d9d..7c4fe2e3f0 100644 --- a/cpukit/rtems/src/eventsurrender.c +++ b/cpukit/rtems/src/eventsurrender.c @@ -121,7 +121,7 @@ void _Event_Surrender( cpu_self = _Thread_Dispatch_disable_critical( lock_context ); _Thread_Lock_release_default( the_thread, lock_context ); - _Watchdog_Remove_ticks( &the_thread->Timer ); + _Thread_Timer_remove( the_thread ); _Thread_Unblock( the_thread ); _Thread_Dispatch_enable( cpu_self ); diff --git a/cpukit/rtems/src/ratemoncancel.c b/cpukit/rtems/src/ratemoncancel.c index 67b230fbfc..2e4d5322db 100644 --- a/cpukit/rtems/src/ratemoncancel.c +++ b/cpukit/rtems/src/ratemoncancel.c @@ -29,6 +29,7 @@ rtems_status_code rtems_rate_monotonic_cancel( { Rate_monotonic_Control *the_period; Objects_Locations location; + ISR_Level level; the_period = _Rate_monotonic_Get( id, &location ); switch ( location ) { @@ -38,7 +39,9 @@ rtems_status_code rtems_rate_monotonic_cancel( _Objects_Put( &the_period->Object ); return RTEMS_NOT_OWNER_OF_RESOURCE; } - _Watchdog_Remove_ticks( &the_period->Timer ); + _ISR_Disable( level ); + _Watchdog_Per_CPU_remove_relative( &the_period->Timer ); + _ISR_Enable( level ); the_period->state = RATE_MONOTONIC_INACTIVE; _Scheduler_Release_job( the_period->owner, 0 ); _Objects_Put( &the_period->Object ); diff --git a/cpukit/rtems/src/ratemoncreate.c b/cpukit/rtems/src/ratemoncreate.c index 1ac4a36b6e..1a5c9b2615 100644 --- a/cpukit/rtems/src/ratemoncreate.c +++ b/cpukit/rtems/src/ratemoncreate.c @@ -65,7 +65,8 @@ rtems_status_code rtems_rate_monotonic_create( the_period->owner = _Thread_Get_executing(); the_period->state = RATE_MONOTONIC_INACTIVE; - _Watchdog_Preinitialize( &the_period->Timer ); + _Watchdog_Preinitialize( &the_period->Timer, _Per_CPU_Get_by_index( 0 ) ); + _Watchdog_Initialize( &the_period->Timer, _Rate_monotonic_Timeout ); _Rate_monotonic_Reset_statistics( the_period ); diff --git a/cpukit/rtems/src/ratemondelete.c b/cpukit/rtems/src/ratemondelete.c index 77cf3fe306..09b9ab6712 100644 --- a/cpukit/rtems/src/ratemondelete.c +++ b/cpukit/rtems/src/ratemondelete.c @@ -29,6 +29,7 @@ rtems_status_code rtems_rate_monotonic_delete( { Rate_monotonic_Control *the_period; Objects_Locations location; + ISR_Level level; _Objects_Allocator_lock(); the_period = _Rate_monotonic_Get( id, &location ); @@ -37,7 +38,9 @@ rtems_status_code rtems_rate_monotonic_delete( case OBJECTS_LOCAL: _Scheduler_Release_job( the_period->owner, 0 ); _Objects_Close( &_Rate_monotonic_Information, &the_period->Object ); - _Watchdog_Remove_ticks( &the_period->Timer ); + _ISR_Disable( level ); + _Watchdog_Per_CPU_remove_relative( &the_period->Timer ); + _ISR_Enable( level ); the_period->state = RATE_MONOTONIC_INACTIVE; _Objects_Put( &the_period->Object ); _Rate_monotonic_Free( the_period ); diff --git a/cpukit/rtems/src/ratemonperiod.c b/cpukit/rtems/src/ratemonperiod.c index 6afe1016bf..58be148f19 100644 --- a/cpukit/rtems/src/ratemonperiod.c +++ b/cpukit/rtems/src/ratemonperiod.c @@ -77,12 +77,11 @@ bool _Rate_monotonic_Get_status( return true; } -void _Rate_monotonic_Initiate_statistics( - Rate_monotonic_Control *the_period -) +void _Rate_monotonic_Restart( Rate_monotonic_Control *the_period ) { Thread_Control *owning_thread = the_period->owner; Timestamp_Control uptime; + ISR_Level level; _TOD_Get_uptime( &uptime ); @@ -113,7 +112,15 @@ void _Rate_monotonic_Initiate_statistics( _Timestamp_Add_to( &the_period->cpu_usage_period_initiated, &ran ); } - _Scheduler_Release_job( the_period->owner, the_period->next_length ); + _Scheduler_Release_job( owning_thread, the_period->next_length ); + + _ISR_Disable( level ); + _Watchdog_Per_CPU_insert_relative( + &the_period->Timer, + _Per_CPU_Get(), + the_period->next_length + ); + _ISR_Enable( level ); } static void _Rate_monotonic_Update_statistics( @@ -238,22 +245,9 @@ rtems_status_code rtems_rate_monotonic_period( if ( the_period->state == RATE_MONOTONIC_INACTIVE ) { _ISR_Enable( level ); - the_period->next_length = length; - - /* - * Baseline statistics information for the beginning of a period. - */ - _Rate_monotonic_Initiate_statistics( the_period ); - the_period->state = RATE_MONOTONIC_ACTIVE; - _Watchdog_Initialize( - &the_period->Timer, - _Rate_monotonic_Timeout, - id, - NULL - ); - - _Watchdog_Insert_ticks( &the_period->Timer, length ); + the_period->next_length = length; + _Rate_monotonic_Restart( the_period ); _Objects_Put( &the_period->Object ); return RTEMS_SUCCESSFUL; } @@ -308,7 +302,11 @@ rtems_status_code rtems_rate_monotonic_period( the_period->state = RATE_MONOTONIC_ACTIVE; the_period->next_length = length; - _Watchdog_Insert_ticks( &the_period->Timer, length ); + _Watchdog_Per_CPU_insert_relative( + &the_period->Timer, + _Per_CPU_Get(), + length + ); _Scheduler_Release_job( the_period->owner, the_period->next_length ); _Objects_Put( &the_period->Object ); return RTEMS_TIMEOUT; diff --git a/cpukit/rtems/src/ratemontimeout.c b/cpukit/rtems/src/ratemontimeout.c index 08f9bd17d7..7c25595a16 100644 --- a/cpukit/rtems/src/ratemontimeout.c +++ b/cpukit/rtems/src/ratemontimeout.c @@ -22,46 +22,30 @@ #include #include -void _Rate_monotonic_Timeout( - Objects_Id id, - void *ignored -) +void _Rate_monotonic_Timeout( Watchdog_Control *watchdog ) { Rate_monotonic_Control *the_period; - Objects_Locations location; Thread_Control *the_thread; /* * When we get here, the Timer is already off the chain so we do not * have to worry about that -- hence no _Watchdog_Remove(). */ - the_period = _Rate_monotonic_Get( id, &location ); - switch ( location ) { - - case OBJECTS_LOCAL: - the_thread = the_period->owner; - if ( _States_Is_waiting_for_period( the_thread->current_state ) && - the_thread->Wait.id == the_period->Object.id ) { - _Thread_Unblock( the_thread ); - - _Rate_monotonic_Initiate_statistics( the_period ); - - _Watchdog_Insert_ticks( &the_period->Timer, the_period->next_length ); - } else if ( the_period->state == RATE_MONOTONIC_OWNER_IS_BLOCKING ) { - the_period->state = RATE_MONOTONIC_EXPIRED_WHILE_BLOCKING; - - _Rate_monotonic_Initiate_statistics( the_period ); - - _Watchdog_Insert_ticks( &the_period->Timer, the_period->next_length ); - } else - the_period->state = RATE_MONOTONIC_EXPIRED; - _Objects_Put_without_thread_dispatch( &the_period->Object ); - break; - -#if defined(RTEMS_MULTIPROCESSING) - case OBJECTS_REMOTE: /* impossible */ -#endif - case OBJECTS_ERROR: - break; + the_period = RTEMS_CONTAINER_OF( watchdog, Rate_monotonic_Control, Timer ); + the_thread = the_period->owner; + + _Thread_Disable_dispatch(); + + if ( _States_Is_waiting_for_period( the_thread->current_state ) && + the_thread->Wait.id == the_period->Object.id ) { + _Thread_Unblock( the_thread ); + _Rate_monotonic_Restart( the_period ); + } else if ( the_period->state == RATE_MONOTONIC_OWNER_IS_BLOCKING ) { + the_period->state = RATE_MONOTONIC_EXPIRED_WHILE_BLOCKING; + _Rate_monotonic_Restart( the_period ); + } else { + the_period->state = RATE_MONOTONIC_EXPIRED; } + + _Thread_Unnest_dispatch(); } diff --git a/cpukit/rtems/src/taskwakeafter.c b/cpukit/rtems/src/taskwakeafter.c index b7f328f5bc..fa5f6f4eed 100644 --- a/cpukit/rtems/src/taskwakeafter.c +++ b/cpukit/rtems/src/taskwakeafter.c @@ -41,13 +41,12 @@ rtems_status_code rtems_task_wake_after( } else { _Thread_Set_state( executing, STATES_DELAYING ); _Thread_Wait_flags_set( executing, THREAD_WAIT_STATE_BLOCKED ); - _Watchdog_Initialize( - &executing->Timer, + _Thread_Timer_insert_relative( + executing, + cpu_self, _Thread_Timeout, - 0, - executing + ticks ); - _Watchdog_Insert_ticks( &executing->Timer, ticks ); } _Thread_Dispatch_enable( cpu_self ); return RTEMS_SUCCESSFUL; diff --git a/cpukit/rtems/src/taskwakewhen.c b/cpukit/rtems/src/taskwakewhen.c index cf0b303cd3..5d6d45afcf 100644 --- a/cpukit/rtems/src/taskwakewhen.c +++ b/cpukit/rtems/src/taskwakewhen.c @@ -28,9 +28,9 @@ rtems_status_code rtems_task_wake_when( rtems_time_of_day *time_buffer ) { - Watchdog_Interval seconds; - Thread_Control *executing; - Per_CPU_Control *cpu_self; + uint32_t seconds; + Thread_Control *executing; + Per_CPU_Control *cpu_self; if ( !_TOD_Is_set() ) return RTEMS_NOT_DEFINED; @@ -52,15 +52,11 @@ rtems_status_code rtems_task_wake_when( executing = _Thread_Executing; _Thread_Set_state( executing, STATES_WAITING_FOR_TIME ); _Thread_Wait_flags_set( executing, THREAD_WAIT_STATE_BLOCKED ); - _Watchdog_Initialize( - &executing->Timer, + _Thread_Timer_insert_absolute( + executing, + cpu_self, _Thread_Timeout, - 0, - executing - ); - _Watchdog_Insert_seconds( - &executing->Timer, - seconds - _TOD_Seconds_since_epoch() + _Watchdog_Ticks_from_seconds( seconds ) ); _Thread_Dispatch_enable( cpu_self ); return RTEMS_SUCCESSFUL; diff --git a/cpukit/rtems/src/timercancel.c b/cpukit/rtems/src/timercancel.c index 1e737a25bb..5d4343e776 100644 --- a/cpukit/rtems/src/timercancel.c +++ b/cpukit/rtems/src/timercancel.c @@ -14,39 +14,24 @@ #include "config.h" #endif -#include -#include -#include -#include #include -#include - -/* - * rtems_timer_cancel - * - * This directive allows a thread to cancel a timer. - * - * Input parameters: - * id - timer id - * - * Output parameters: - * RTEMS_SUCCESSFUL - if successful - * error code - if unsuccessful - */ rtems_status_code rtems_timer_cancel( rtems_id id ) { - Timer_Control *the_timer; - Objects_Locations location; + Timer_Control *the_timer; + Objects_Locations location; + ISR_lock_Context lock_context; + Per_CPU_Control *cpu; - the_timer = _Timer_Get( id, &location ); + the_timer = _Timer_Get( id, &location, &lock_context ); switch ( location ) { case OBJECTS_LOCAL: - _Timer_Cancel( the_timer ); - _Objects_Put( &the_timer->Object ); + cpu = _Timer_Acquire_critical( the_timer, &lock_context ); + _Timer_Cancel( cpu, the_timer ); + _Timer_Release( cpu, &lock_context ); return RTEMS_SUCCESSFUL; #if defined(RTEMS_MULTIPROCESSING) diff --git a/cpukit/rtems/src/timercreate.c b/cpukit/rtems/src/timercreate.c index 5c718b94c9..80c1356278 100644 --- a/cpukit/rtems/src/timercreate.c +++ b/cpukit/rtems/src/timercreate.c @@ -18,40 +18,173 @@ #include "config.h" #endif -#include +#include +#include #include #include #include +#include #include -#include +#include #include -void _Timer_Cancel( Timer_Control *the_timer ) +RTEMS_STATIC_ASSERT( + PER_CPU_WATCHDOG_ABSOLUTE == TIMER_CLASS_BIT_TIME_OF_DAY, + TIMER_CLASS_BIT_TIME_OF_DAY +); + +void _Timer_Routine_adaptor( Watchdog_Control *the_watchdog ) { - Timer_server_Control *timer_server; - ISR_Level level; + Timer_Control *the_timer; + Per_CPU_Control *cpu; - /* The timer class must not change during the cancel operation */ - _ISR_Disable( level ); + the_timer = RTEMS_CONTAINER_OF( the_watchdog, Timer_Control, Ticker ); + cpu = _Watchdog_Get_CPU( &the_timer->Ticker ); + the_timer->stop_time = _Timer_Get_CPU_ticks( cpu ); - switch ( the_timer->the_class ) { - case TIMER_INTERVAL: - _Watchdog_Remove_ticks( &the_timer->Ticker ); - break; - case TIMER_TIME_OF_DAY: - _Watchdog_Remove_seconds( &the_timer->Ticker ); - break; - case TIMER_INTERVAL_ON_TASK: - case TIMER_TIME_OF_DAY_ON_TASK: - timer_server = _Timer_server; - (*timer_server->cancel)( timer_server, the_timer ); - break; - default: - _Assert( the_timer->the_class == TIMER_DORMANT ); + ( *the_timer->routine )( the_timer->Object.id, the_timer->user_data ); +} + +rtems_status_code _Timer_Fire( + rtems_id id, + rtems_interval interval, + rtems_timer_service_routine_entry routine, + void *user_data, + Timer_Classes the_class, + Watchdog_Service_routine_entry adaptor +) +{ + Timer_Control *the_timer; + Objects_Locations location; + ISR_lock_Context lock_context; + Per_CPU_Control *cpu; + + the_timer = _Timer_Get( id, &location, &lock_context ); + switch ( location ) { + + case OBJECTS_LOCAL: + cpu = _Timer_Acquire_critical( the_timer, &lock_context ); + _Timer_Cancel( cpu, the_timer ); + _Watchdog_Initialize( &the_timer->Ticker, adaptor ); + the_timer->the_class = the_class; + the_timer->routine = routine; + the_timer->user_data = user_data; + the_timer->initial = interval; + the_timer->start_time = _Timer_Get_CPU_ticks( cpu ); + + if ( _Timer_Is_interval_class( the_class ) ) { + _Watchdog_Insert( + &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_RELATIVE ], + &the_timer->Ticker, + cpu->Watchdog.ticks + interval + ); + } else { + _Watchdog_Insert( + &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_ABSOLUTE ], + &the_timer->Ticker, + _Watchdog_Ticks_from_seconds( interval ) + ); + } + + _Timer_Release( cpu, &lock_context ); + return RTEMS_SUCCESSFUL; + +#if defined(RTEMS_MULTIPROCESSING) + case OBJECTS_REMOTE: /* should never return this */ +#endif + case OBJECTS_ERROR: break; } - _ISR_Enable( level ); + return RTEMS_INVALID_ID; +} + +rtems_status_code _Timer_Fire_after( + rtems_id id, + rtems_interval ticks, + rtems_timer_service_routine_entry routine, + void *user_data, + Timer_Classes the_class, + Watchdog_Service_routine_entry adaptor +) +{ + if ( ticks == 0 ) + return RTEMS_INVALID_NUMBER; + + if ( !routine ) + return RTEMS_INVALID_ADDRESS; + + return _Timer_Fire( + id, + ticks, + routine, + user_data, + the_class, + adaptor + ); +} + +rtems_status_code _Timer_Fire_when( + rtems_id id, + const rtems_time_of_day *wall_time, + rtems_timer_service_routine_entry routine, + void *user_data, + Timer_Classes the_class, + Watchdog_Service_routine_entry adaptor +) +{ + rtems_interval seconds; + + if ( !_TOD_Is_set() ) + return RTEMS_NOT_DEFINED; + + if ( !routine ) + return RTEMS_INVALID_ADDRESS; + + if ( !_TOD_Validate( wall_time ) ) + return RTEMS_INVALID_CLOCK; + + seconds = _TOD_To_seconds( wall_time ); + if ( seconds <= _TOD_Seconds_since_epoch() ) + return RTEMS_INVALID_CLOCK; + + return _Timer_Fire( + id, + seconds, + routine, + user_data, + the_class, + adaptor + ); +} + +void _Timer_Cancel( Per_CPU_Control *cpu, Timer_Control *the_timer ) +{ + Timer_Classes the_class; + + the_class = the_timer->the_class; + + if ( _Watchdog_Is_scheduled( &the_timer->Ticker ) ) { + the_timer->stop_time = _Timer_Get_CPU_ticks( cpu ); + _Watchdog_Remove( + &cpu->Watchdog.Header[ _Timer_Watchdog_header_index( the_class ) ], + &the_timer->Ticker + ); + } else if ( _Timer_Is_on_task_class( the_class ) ) { + Timer_server_Control *timer_server; + ISR_lock_Context lock_context; + + timer_server = _Timer_server; + _Assert( timer_server != NULL ); + _Timer_server_Acquire_critical( timer_server, &lock_context ); + + if ( _Watchdog_Get_state( &the_timer->Ticker ) == WATCHDOG_PENDING ) { + _Watchdog_Set_state( &the_timer->Ticker, WATCHDOG_INACTIVE ); + _Chain_Extract_unprotected( &the_timer->Ticker.Node.Chain ); + } + + _Timer_server_Release_critical( timer_server, &lock_context ); + } } rtems_status_code rtems_timer_create( @@ -75,7 +208,7 @@ rtems_status_code rtems_timer_create( } the_timer->the_class = TIMER_DORMANT; - _Watchdog_Preinitialize( &the_timer->Ticker ); + _Watchdog_Preinitialize( &the_timer->Ticker, _Per_CPU_Get_snapshot() ); _Objects_Open( &_Timer_Information, diff --git a/cpukit/rtems/src/timerdelete.c b/cpukit/rtems/src/timerdelete.c index 0849ec5ba6..9c413976c4 100644 --- a/cpukit/rtems/src/timerdelete.c +++ b/cpukit/rtems/src/timerdelete.c @@ -18,12 +18,7 @@ #include "config.h" #endif -#include -#include -#include -#include #include -#include rtems_status_code rtems_timer_delete( rtems_id id @@ -31,15 +26,18 @@ rtems_status_code rtems_timer_delete( { Timer_Control *the_timer; Objects_Locations location; + ISR_lock_Context lock_context; + Per_CPU_Control *cpu; _Objects_Allocator_lock(); - the_timer = _Timer_Get( id, &location ); + the_timer = _Timer_Get( id, &location, &lock_context ); switch ( location ) { case OBJECTS_LOCAL: _Objects_Close( &_Timer_Information, &the_timer->Object ); - _Timer_Cancel( the_timer ); - _Objects_Put( &the_timer->Object ); + cpu = _Timer_Acquire_critical( the_timer, &lock_context ); + _Timer_Cancel( cpu, the_timer ); + _Timer_Release( cpu, &lock_context ); _Timer_Free( the_timer ); _Objects_Allocator_unlock(); return RTEMS_SUCCESSFUL; diff --git a/cpukit/rtems/src/timerfireafter.c b/cpukit/rtems/src/timerfireafter.c index 84cf46bc37..82bd878cec 100644 --- a/cpukit/rtems/src/timerfireafter.c +++ b/cpukit/rtems/src/timerfireafter.c @@ -18,12 +18,7 @@ #include "config.h" #endif -#include -#include -#include -#include #include -#include rtems_status_code rtems_timer_fire_after( rtems_id id, @@ -32,55 +27,12 @@ rtems_status_code rtems_timer_fire_after( void *user_data ) { - Timer_Control *the_timer; - Objects_Locations location; - ISR_Level level; - - if ( ticks == 0 ) - return RTEMS_INVALID_NUMBER; - - if ( !routine ) - return RTEMS_INVALID_ADDRESS; - - the_timer = _Timer_Get( id, &location ); - switch ( location ) { - - case OBJECTS_LOCAL: - _Timer_Cancel( the_timer ); - - _ISR_Disable( level ); - - /* - * Check to see if the watchdog has just been inserted by a - * higher priority interrupt. If so, abandon this insert. - */ - - if ( the_timer->Ticker.state != WATCHDOG_INACTIVE ) { - _ISR_Enable( level ); - _Objects_Put( &the_timer->Object ); - return RTEMS_SUCCESSFUL; - } - - /* - * OK. Now we now the timer was not rescheduled by an interrupt - * so we can atomically initialize it as in use. - */ - - the_timer->the_class = TIMER_INTERVAL; - _Watchdog_Initialize( &the_timer->Ticker, routine, id, user_data ); - _ISR_Enable( level ); - - - _Watchdog_Insert_ticks( &the_timer->Ticker, ticks ); - _Objects_Put( &the_timer->Object ); - return RTEMS_SUCCESSFUL; - -#if defined(RTEMS_MULTIPROCESSING) - case OBJECTS_REMOTE: /* should never return this */ -#endif - case OBJECTS_ERROR: - break; - } - - return RTEMS_INVALID_ID; + return _Timer_Fire_after( + id, + ticks, + routine, + user_data, + TIMER_INTERVAL, + _Timer_Routine_adaptor + ); } diff --git a/cpukit/rtems/src/timerfirewhen.c b/cpukit/rtems/src/timerfirewhen.c index 1acbaf9b8f..eddeb16c4f 100644 --- a/cpukit/rtems/src/timerfirewhen.c +++ b/cpukit/rtems/src/timerfirewhen.c @@ -19,9 +19,6 @@ #endif #include -#include -#include -#include rtems_status_code rtems_timer_fire_when( rtems_id id, @@ -30,43 +27,12 @@ rtems_status_code rtems_timer_fire_when( void *user_data ) { - Timer_Control *the_timer; - Objects_Locations location; - rtems_interval seconds; - - if ( !_TOD_Is_set() ) - return RTEMS_NOT_DEFINED; - - if ( !_TOD_Validate( wall_time ) ) - return RTEMS_INVALID_CLOCK; - - if ( !routine ) - return RTEMS_INVALID_ADDRESS; - - seconds = _TOD_To_seconds( wall_time ); - if ( seconds <= _TOD_Seconds_since_epoch() ) - return RTEMS_INVALID_CLOCK; - - the_timer = _Timer_Get( id, &location ); - switch ( location ) { - - case OBJECTS_LOCAL: - _Timer_Cancel( the_timer ); - the_timer->the_class = TIMER_TIME_OF_DAY; - _Watchdog_Initialize( &the_timer->Ticker, routine, id, user_data ); - _Watchdog_Insert_seconds( - &the_timer->Ticker, - seconds - _TOD_Seconds_since_epoch() - ); - _Objects_Put( &the_timer->Object ); - return RTEMS_SUCCESSFUL; - -#if defined(RTEMS_MULTIPROCESSING) - case OBJECTS_REMOTE: /* should never return this */ -#endif - case OBJECTS_ERROR: - break; - } - - return RTEMS_INVALID_ID; + return _Timer_Fire_when( + id, + wall_time, + routine, + user_data, + TIMER_TIME_OF_DAY, + _Timer_Routine_adaptor + ); } diff --git a/cpukit/rtems/src/timergetinfo.c b/cpukit/rtems/src/timergetinfo.c index 17c32e6cf4..a11861c63e 100644 --- a/cpukit/rtems/src/timergetinfo.c +++ b/cpukit/rtems/src/timergetinfo.c @@ -32,19 +32,22 @@ rtems_status_code rtems_timer_get_information( { Timer_Control *the_timer; Objects_Locations location; + ISR_lock_Context lock_context; + Per_CPU_Control *cpu; if ( !the_info ) return RTEMS_INVALID_ADDRESS; - the_timer = _Timer_Get( id, &location ); + the_timer = _Timer_Get( id, &location, &lock_context ); switch ( location ) { case OBJECTS_LOCAL: + cpu = _Timer_Acquire_critical( the_timer, &lock_context ); the_info->the_class = the_timer->the_class; - the_info->initial = the_timer->Ticker.initial; - the_info->start_time = the_timer->Ticker.start_time; - the_info->stop_time = the_timer->Ticker.stop_time; - _Objects_Put( &the_timer->Object ); + the_info->initial = the_timer->initial; + the_info->start_time = the_timer->start_time; + the_info->stop_time = the_timer->stop_time; + _Timer_Release( cpu, &lock_context ); return RTEMS_SUCCESSFUL; #if defined(RTEMS_MULTIPROCESSING) diff --git a/cpukit/rtems/src/timerreset.c b/cpukit/rtems/src/timerreset.c index 7ab172ea4f..72c912baa3 100644 --- a/cpukit/rtems/src/timerreset.c +++ b/cpukit/rtems/src/timerreset.c @@ -44,40 +44,29 @@ rtems_status_code rtems_timer_reset( { Timer_Control *the_timer; Objects_Locations location; - rtems_status_code status = RTEMS_SUCCESSFUL; + ISR_lock_Context lock_context; + Per_CPU_Control *cpu; + rtems_status_code status; - the_timer = _Timer_Get( id, &location ); + the_timer = _Timer_Get( id, &location, &lock_context ); switch ( location ) { case OBJECTS_LOCAL: - if ( the_timer->the_class == TIMER_INTERVAL ) { - _Watchdog_Reset_ticks( &the_timer->Ticker ); - } else if ( the_timer->the_class == TIMER_INTERVAL_ON_TASK ) { - Timer_server_Control *timer_server = _Timer_server; + cpu = _Timer_Acquire_critical( the_timer, &lock_context ); - /* - * There is no way for a timer to have this class unless - * it was scheduled as a server fire. That requires that - * the Timer Server be initiated. So this error cannot - * occur unless something is internally wrong. - */ - #if defined(RTEMS_DEBUG) - if ( !timer_server ) { - _Objects_Put( &the_timer->Object ); - return RTEMS_INCORRECT_STATE; - } - #endif - (*timer_server->cancel)( timer_server, the_timer ); - (*timer_server->schedule_operation)( timer_server, the_timer ); + if ( _Timer_Is_interval_class( the_timer->the_class ) ) { + _Timer_Cancel( cpu, the_timer ); + _Watchdog_Insert( + &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_RELATIVE ], + &the_timer->Ticker, + cpu->Watchdog.ticks + the_timer->initial + ); + status = RTEMS_SUCCESSFUL; } else { - /* - * Must be dormant or time of day timer (e.g. TIMER_DORMANT, - * TIMER_TIME_OF_DAY, or TIMER_TIME_OF_DAY_ON_TASK). We - * can only reset active interval timers. - */ status = RTEMS_NOT_DEFINED; } - _Objects_Put( &the_timer->Object ); + + _Timer_Release( cpu, &lock_context ); return status; #if defined(RTEMS_MULTIPROCESSING) diff --git a/cpukit/rtems/src/timerserver.c b/cpukit/rtems/src/timerserver.c index 7d757809b8..cf06319434 100644 --- a/cpukit/rtems/src/timerserver.c +++ b/cpukit/rtems/src/timerserver.c @@ -15,7 +15,7 @@ /* COPYRIGHT (c) 1989-2008. * On-Line Applications Research Corporation (OAR). * - * Copyright (c) 2009-2015 embedded brains GmbH. + * Copyright (c) 2009, 2016 embedded brains GmbH. * * The license and distribution terms for this file may be * found in the file LICENSE in this distribution or at @@ -34,193 +34,48 @@ static Timer_server_Control _Timer_server_Default; -static void _Timer_server_Cancel_method( +static void _Timer_server_Acquire( Timer_server_Control *ts, - Timer_Control *timer + ISR_lock_Context *lock_context ) { - if ( timer->the_class == TIMER_INTERVAL_ON_TASK ) { - _Watchdog_Remove( &ts->Interval_watchdogs.Header, &timer->Ticker ); - } else if ( timer->the_class == TIMER_TIME_OF_DAY_ON_TASK ) { - _Watchdog_Remove( &ts->TOD_watchdogs.Header, &timer->Ticker ); - } -} - -static Watchdog_Interval _Timer_server_Get_ticks( void ) -{ - return _Watchdog_Ticks_since_boot; + _ISR_lock_ISR_disable_and_acquire( &ts->Lock, lock_context ); } -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( +static void _Timer_server_Release( Timer_server_Control *ts, - Timer_Control *timer + ISR_lock_Context *lock_context ) { - if ( timer->the_class == TIMER_INTERVAL_ON_TASK ) { - _Timer_server_Insert_timer( - &ts->Interval_watchdogs, - 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 - ); - } + _ISR_lock_Release_and_ISR_enable( &ts->Lock, lock_context ); } -static void _Timer_server_Update_current_snapshot( - Timer_server_Watchdogs *watchdogs, - Watchdog_Interval (*get_ticks)( void ) -) +void _Timer_server_Routine_adaptor( Watchdog_Control *the_watchdog ) { - ISR_lock_Context lock_context; + Timer_Control *the_timer; + ISR_lock_Context lock_context; + Per_CPU_Control *cpu; + Timer_server_Control *ts; + bool wakeup; - _Watchdog_Acquire( &watchdogs->Header, &lock_context ); - watchdogs->current_snapshot = (*get_ticks)(); - watchdogs->system_watchdog_delta = 0; - _Watchdog_Release( &watchdogs->Header, &lock_context ); -} + ts = _Timer_server; + _Assert( ts != NULL ); + the_timer = RTEMS_CONTAINER_OF( the_watchdog, Timer_Control, Ticker ); -static void _Timer_server_Tickle( - Timer_server_Watchdogs *watchdogs, - Watchdog_Header *system_header, - Watchdog_Interval (*get_ticks)( void ), - bool ticks -) -{ - ISR_lock_Context lock_context; - Watchdog_Interval now; - Watchdog_Interval last; + _Timer_server_Acquire( ts, &lock_context ); - _Watchdog_Acquire( &watchdogs->Header, &lock_context ); + _Assert( _Watchdog_Get_state( &the_timer->Ticker ) == WATCHDOG_INACTIVE ); + _Watchdog_Set_state( &the_timer->Ticker, WATCHDOG_PENDING ); + cpu = _Watchdog_Get_CPU( &the_timer->Ticker ); + the_timer->stop_time = _Timer_Get_CPU_ticks( cpu ); + wakeup = _Chain_Is_empty( &ts->Pending ); + _Chain_Append_unprotected( &ts->Pending, &the_timer->Ticker.Node.Chain ); - now = watchdogs->current_snapshot; - last = watchdogs->last_snapshot; - watchdogs->last_snapshot = now; + _Timer_server_Release( ts, &lock_context ); - if ( ticks || now >= last ) { - _Watchdog_Adjust_forward_locked( - &watchdogs->Header, - now - last, - &lock_context - ); - } else { - _Watchdog_Adjust_backward_locked( - &watchdogs->Header, - last - now - ); + if ( wakeup ) { + (void) rtems_event_system_send( ts->server_id, RTEMS_EVENT_SYSTEM_SERVER ); } - - ++watchdogs->generation; - - _Watchdog_Release( &watchdogs->Header, &lock_context ); - - _Timer_server_Update_system_watchdog( watchdogs, system_header ); } /** @@ -239,21 +94,38 @@ static rtems_task _Timer_server_Body( Timer_server_Control *ts = (Timer_server_Control *) arg; while ( true ) { - rtems_event_set events; + ISR_lock_Context lock_context; + rtems_event_set events; - _Timer_server_Tickle( - &ts->Interval_watchdogs, - &_Watchdog_Ticks_header, - _Timer_server_Get_ticks, - true - ); + _Timer_server_Acquire( ts, &lock_context ); - _Timer_server_Tickle( - &ts->TOD_watchdogs, - &_Watchdog_Seconds_header, - _Timer_server_Get_seconds, - false - ); + while ( true ) { + Watchdog_Control *the_watchdog; + Timer_Control *the_timer; + rtems_timer_service_routine_entry routine; + Objects_Id id; + void *user_data; + + the_watchdog = (Watchdog_Control *) _Chain_Get_unprotected( &ts->Pending ); + if ( the_watchdog == NULL ) { + break; + } + + _Assert( _Watchdog_Get_state( the_watchdog ) == WATCHDOG_PENDING ); + _Watchdog_Set_state( the_watchdog, WATCHDOG_INACTIVE ); + the_timer = RTEMS_CONTAINER_OF( the_watchdog, Timer_Control, Ticker ); + routine = the_timer->routine; + id = the_timer->Object.id; + user_data = the_timer->user_data; + + _Timer_server_Release( ts, &lock_context ); + + ( *routine )( id, user_data ); + + _Timer_server_Acquire( ts, &lock_context ); + } + + _Timer_server_Release( ts, &lock_context ); (void) rtems_event_system_receive( RTEMS_EVENT_SYSTEM_SERVER, @@ -264,98 +136,34 @@ static rtems_task _Timer_server_Body( } } -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_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_Preinitialize( &watchdogs->System_watchdog ); - _Watchdog_Initialize( - &watchdogs->System_watchdog, - _Timer_server_Wakeup, - id, - ts - ); -} - -/** - * @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. - * - * @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 - * - * @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, - rtems_attribute attribute_set +static rtems_status_code _Timer_server_Initiate( + rtems_task_priority priority, + size_t stack_size, + rtems_attribute attribute_set ) { - rtems_id id; rtems_status_code status; - rtems_task_priority _priority; - static bool initialized = false; - bool tmpInitialized; - Timer_server_Control *ts = &_Timer_server_Default; + rtems_id id; + Timer_server_Control *ts; + + /* + * Just to make sure this is only called once. + */ + if ( _Timer_server != NULL ) { + return RTEMS_INCORRECT_STATE; + } /* * 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 ) return RTEMS_INVALID_PRIORITY; - _priority = PRIORITY_PSEUDO_ISR; + priority = PRIORITY_PSEUDO_ISR; } - /* - * Just to make sure this is only called once. - */ - _Once_Lock(); - tmpInitialized = initialized; - initialized = true; - _Once_Unlock(); - - if ( tmpInitialized ) - return RTEMS_INCORRECT_STATE; - /* * 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 @@ -371,19 +179,18 @@ rtems_status_code rtems_timer_initiate_server( * 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 */ - stack_size, /* let user specify stack size */ + rtems_build_name('T','I','M','E'), + priority, + stack_size, rtems_configuration_is_smp_enabled() ? RTEMS_DEFAULT_MODES : /* no preempt is not supported for SMP */ RTEMS_NO_PREEMPT, /* no preempt is like an interrupt */ /* user may want floating point but we need */ /* system task specified for 0 priority */ attribute_set | RTEMS_SYSTEM_TASK, - &id /* get the id back */ + &id ); - if (status) { - initialized = false; + if (status != RTEMS_SUCCESSFUL) { return status; } @@ -392,26 +199,10 @@ rtems_status_code rtems_timer_initiate_server( * Timer Server so we do not have to have a critical section. */ - _Timer_server_Initialize_watchdogs( - ts, - id, - &ts->Interval_watchdogs, - _Timer_server_Get_ticks - ); - - _Timer_server_Initialize_watchdogs( - ts, - id, - &ts->TOD_watchdogs, - _Timer_server_Get_seconds - ); - - /* - * Initialize the pointer to the timer server methods so applications that - * do not use the Timer Server do not have to pull it in. - */ - ts->cancel = _Timer_server_Cancel_method; - ts->schedule_operation = _Timer_server_Schedule_operation_method; + ts = &_Timer_server_Default; + _ISR_lock_Initialize( &ts->Lock, "Timer Server" ); + _Chain_Initialize_empty( &ts->Pending ); + ts->server_id = id; /* * The default timer server is now available. @@ -426,19 +217,22 @@ rtems_status_code rtems_timer_initiate_server( _Timer_server_Body, (rtems_task_argument) ts ); + _Assert( status == RTEMS_SUCCESSFUL ); - #if defined(RTEMS_DEBUG) - /* - * One would expect a call to rtems_task_delete() here to clean up - * but there is actually no way (in normal circumstances) that the - * start can fail. The id and starting address are known to be - * be good. If this service fails, something is weirdly wrong on the - * target such as a stray write in an ISR or incorrect memory layout. - */ - if (status) { - initialized = false; - } - #endif + return status; +} + +rtems_status_code rtems_timer_initiate_server( + rtems_task_priority priority, + size_t stack_size, + rtems_attribute attribute_set +) +{ + rtems_status_code status; + + _Once_Lock(); + status = _Timer_server_Initiate( priority, stack_size, attribute_set ); + _Once_Unlock(); return status; } diff --git a/cpukit/rtems/src/timerserverfireafter.c b/cpukit/rtems/src/timerserverfireafter.c index 0636782ae0..ce1fd05848 100644 --- a/cpukit/rtems/src/timerserverfireafter.c +++ b/cpukit/rtems/src/timerserverfireafter.c @@ -18,12 +18,7 @@ #include "config.h" #endif -#include -#include -#include -#include #include -#include rtems_status_code rtems_timer_server_fire_after( rtems_id id, @@ -32,60 +27,19 @@ rtems_status_code rtems_timer_server_fire_after( void *user_data ) { - Timer_Control *the_timer; - Objects_Locations location; - ISR_Level level; - Timer_server_Control *timer_server = _Timer_server; + Timer_server_Control *timer_server; + + timer_server = _Timer_server; if ( !timer_server ) return RTEMS_INCORRECT_STATE; - if ( !routine ) - return RTEMS_INVALID_ADDRESS; - - if ( ticks == 0 ) - return RTEMS_INVALID_NUMBER; - - the_timer = _Timer_Get( id, &location ); - switch ( location ) { - - case OBJECTS_LOCAL: - _Timer_Cancel( the_timer ); - - _ISR_Disable( level ); - - /* - * Check to see if the watchdog has just been inserted by a - * higher priority interrupt. If so, abandon this insert. - */ - - if ( the_timer->Ticker.state != WATCHDOG_INACTIVE ) { - _ISR_Enable( level ); - _Objects_Put( &the_timer->Object ); - return RTEMS_SUCCESSFUL; - } - - /* - * OK. Now we now the timer was not rescheduled by an interrupt - * so we can atomically initialize it as in use. - */ - - the_timer->the_class = TIMER_INTERVAL_ON_TASK; - _Watchdog_Initialize( &the_timer->Ticker, routine, id, user_data ); - the_timer->Ticker.initial = ticks; - _ISR_Enable( level ); - - (*timer_server->schedule_operation)( timer_server, the_timer ); - - _Objects_Put( &the_timer->Object ); - return RTEMS_SUCCESSFUL; - -#if defined(RTEMS_MULTIPROCESSING) - case OBJECTS_REMOTE: /* should never return this */ -#endif - case OBJECTS_ERROR: - break; - } - - return RTEMS_INVALID_ID; + return _Timer_Fire_after( + id, + ticks, + routine, + user_data, + TIMER_INTERVAL_ON_TASK, + _Timer_server_Routine_adaptor + ); } diff --git a/cpukit/rtems/src/timerserverfirewhen.c b/cpukit/rtems/src/timerserverfirewhen.c index 0069af1c3b..f96a470b7c 100644 --- a/cpukit/rtems/src/timerserverfirewhen.c +++ b/cpukit/rtems/src/timerserverfirewhen.c @@ -19,26 +19,6 @@ #endif #include -#include -#include -#include - -/* - * rtems_timer_server_fire_when - * - * This directive allows a thread to start a timer which will by - * executed by the Timer Server when it fires. - * - * Input parameters: - * id - timer id - * wall_time - time of day to fire timer - * routine - routine to schedule - * user_data - passed as argument to routine when it is fired - * - * Output parameters: - * RTEMS_SUCCESSFUL - if successful - * error code - if unsuccessful - */ rtems_status_code rtems_timer_server_fire_when( rtems_id id, @@ -47,47 +27,19 @@ rtems_status_code rtems_timer_server_fire_when( void *user_data ) { - Timer_Control *the_timer; - Objects_Locations location; - rtems_interval seconds; - Timer_server_Control *timer_server = _Timer_server; + Timer_server_Control *timer_server; + + timer_server = _Timer_server; if ( !timer_server ) return RTEMS_INCORRECT_STATE; - if ( !_TOD_Is_set() ) - return RTEMS_NOT_DEFINED; - - if ( !routine ) - return RTEMS_INVALID_ADDRESS; - - if ( !_TOD_Validate( wall_time ) ) - return RTEMS_INVALID_CLOCK; - - seconds = _TOD_To_seconds( wall_time ); - if ( seconds <= _TOD_Seconds_since_epoch() ) - return RTEMS_INVALID_CLOCK; - - the_timer = _Timer_Get( id, &location ); - switch ( location ) { - - case OBJECTS_LOCAL: - _Timer_Cancel( the_timer ); - the_timer->the_class = TIMER_TIME_OF_DAY_ON_TASK; - _Watchdog_Initialize( &the_timer->Ticker, routine, id, user_data ); - the_timer->Ticker.initial = seconds - _TOD_Seconds_since_epoch(); - - (*timer_server->schedule_operation)( timer_server, the_timer ); - - _Objects_Put( &the_timer->Object ); - return RTEMS_SUCCESSFUL; - -#if defined(RTEMS_MULTIPROCESSING) - case OBJECTS_REMOTE: /* should never return this */ -#endif - case OBJECTS_ERROR: - break; - } - - return RTEMS_INVALID_ID; + return _Timer_Fire_when( + id, + wall_time, + routine, + user_data, + TIMER_TIME_OF_DAY_ON_TASK, + _Timer_server_Routine_adaptor + ); } -- cgit v1.2.3