summaryrefslogtreecommitdiffstats
path: root/cpukit/rtems/src/timercreate.c
diff options
context:
space:
mode:
Diffstat (limited to 'cpukit/rtems/src/timercreate.c')
-rw-r--r--cpukit/rtems/src/timercreate.c179
1 files changed, 156 insertions, 23 deletions
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 <rtems/system.h>
+#include <rtems/rtems/timerimpl.h>
+#include <rtems/rtems/clock.h>
#include <rtems/rtems/status.h>
#include <rtems/rtems/support.h>
#include <rtems/score/assert.h>
+#include <rtems/score/chainimpl.h>
#include <rtems/score/thread.h>
-#include <rtems/rtems/timerimpl.h>
+#include <rtems/score/todimpl.h>
#include <rtems/score/watchdogimpl.h>
-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,