summaryrefslogtreecommitdiffstats
path: root/cpukit/rtems
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2016-02-18 08:36:26 +0100
committerSebastian Huber <sebastian.huber@embedded-brains.de>2016-03-04 13:36:10 +0100
commit03b900d3ed120ea919ea3eded7edbece3488cff3 (patch)
tree182781fc14fe15fd67caeb80e46f1c58495839c2 /cpukit/rtems
parentscore: Distribute clock tick to all online CPUs (diff)
downloadrtems-03b900d3ed120ea919ea3eded7edbece3488cff3.tar.bz2
score: Replace watchdog handler implementation
Use a red-black tree instead of delta chains. Close #2344. Update #2554. Update #2555. Close #2606.
Diffstat (limited to 'cpukit/rtems')
-rw-r--r--cpukit/rtems/include/rtems/rtems/ratemonimpl.h24
-rw-r--r--cpukit/rtems/include/rtems/rtems/timer.h59
-rw-r--r--cpukit/rtems/include/rtems/rtems/timerimpl.h216
-rw-r--r--cpukit/rtems/src/eventseize.c11
-rw-r--r--cpukit/rtems/src/eventsurrender.c2
-rw-r--r--cpukit/rtems/src/ratemoncancel.c5
-rw-r--r--cpukit/rtems/src/ratemoncreate.c3
-rw-r--r--cpukit/rtems/src/ratemondelete.c5
-rw-r--r--cpukit/rtems/src/ratemonperiod.c38
-rw-r--r--cpukit/rtems/src/ratemontimeout.c50
-rw-r--r--cpukit/rtems/src/taskwakeafter.c9
-rw-r--r--cpukit/rtems/src/taskwakewhen.c18
-rw-r--r--cpukit/rtems/src/timercancel.c31
-rw-r--r--cpukit/rtems/src/timercreate.c179
-rw-r--r--cpukit/rtems/src/timerdelete.c14
-rw-r--r--cpukit/rtems/src/timerfireafter.c64
-rw-r--r--cpukit/rtems/src/timerfirewhen.c50
-rw-r--r--cpukit/rtems/src/timergetinfo.c13
-rw-r--r--cpukit/rtems/src/timerreset.c41
-rw-r--r--cpukit/rtems/src/timerserver.c394
-rw-r--r--cpukit/rtems/src/timerserverfireafter.c68
-rw-r--r--cpukit/rtems/src/timerserverfirewhen.c70
22 files changed, 544 insertions, 820 deletions
diff --git a/cpukit/rtems/include/rtems/rtems/ratemonimpl.h b/cpukit/rtems/include/rtems/rtems/ratemonimpl.h
index 490912eb21..f184c44ba9 100644
--- a/cpukit/rtems/include/rtems/rtems/ratemonimpl.h
+++ b/cpukit/rtems/include/rtems/rtems/ratemonimpl.h
@@ -129,19 +129,13 @@ RTEMS_INLINE_ROUTINE bool _Rate_monotonic_Is_expired (
/**
* @brief Rate Monotonic Timeout
*
- * This routine is invoked when the period represented
- * by ID expires. If the thread which owns this period is blocked
- * waiting for the period to expire, then it is readied and the
- * period is restarted. If the owning thread is not waiting for the
- * period to expire, then the period is placed in the EXPIRED
- * state and not restarted.
- *
- * @param[in] id is the period id
- */
-void _Rate_monotonic_Timeout(
- rtems_id id,
- void *ignored
-);
+ * This routine is invoked when the period represented by the watchdog expires.
+ * If the thread which owns this period is blocked waiting for the period to
+ * expire, then it is readied and the period is restarted. If the owning thread
+ * is not waiting for the period to expire, then the period is placed in the
+ * EXPIRED state and not restarted.
+ */
+void _Rate_monotonic_Timeout( Watchdog_Control *watchdog );
/**
* @brief _Rate_monotonic_Get_status(
@@ -165,7 +159,7 @@ bool _Rate_monotonic_Get_status(
);
/**
- * @brief Initiate Rate Monotonic Statistics
+ * @brief Restart Rate Monotonic Period
*
* This routine is invoked when a period is initiated via an explicit
* call to rtems_rate_monotonic_period for the period's first iteration
@@ -173,7 +167,7 @@ bool _Rate_monotonic_Get_status(
*
* @param[in] the_period points to the period being operated upon.
*/
-void _Rate_monotonic_Initiate_statistics(
+void _Rate_monotonic_Restart(
Rate_monotonic_Control *the_period
);
diff --git a/cpukit/rtems/include/rtems/rtems/timer.h b/cpukit/rtems/include/rtems/rtems/timer.h
index 7cc90511ca..032c49525a 100644
--- a/cpukit/rtems/include/rtems/rtems/timer.h
+++ b/cpukit/rtems/include/rtems/rtems/timer.h
@@ -31,7 +31,7 @@
* COPYRIGHT (c) 1989-2011.
* On-Line Applications Research Corporation (OAR).
*
- * Copyright (c) 2009 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
@@ -43,6 +43,7 @@
#include <rtems/rtems/attr.h>
#include <rtems/rtems/status.h>
+#include <rtems/rtems/tasks.h>
#include <rtems/rtems/types.h>
#ifdef __cplusplus
@@ -63,39 +64,49 @@ extern "C" {
*/
/**@{*/
+#define TIMER_CLASS_BIT_TIME_OF_DAY 0x1
+
+#define TIMER_CLASS_BIT_ON_TASK 0x2
+
+#define TIMER_CLASS_BIT_NOT_DORMANT 0x4
+
/**
* The following enumerated type details the classes to which a timer
* may belong.
*/
typedef enum {
/**
+ * This value indicates the timer is currently not in use.
+ */
+ TIMER_DORMANT,
+
+ /**
* This value indicates the timer is currently in use as an interval
* timer which will fire in the clock tick ISR.
*/
- TIMER_INTERVAL,
+ TIMER_INTERVAL = TIMER_CLASS_BIT_NOT_DORMANT,
/**
* This value indicates the timer is currently in use as an interval
* timer which will fire in the timer server task.
*/
- TIMER_INTERVAL_ON_TASK,
+ TIMER_INTERVAL_ON_TASK =
+ TIMER_CLASS_BIT_NOT_DORMANT | TIMER_CLASS_BIT_ON_TASK,
/**
* This value indicates the timer is currently in use as an time of day
* timer which will fire in the clock tick ISR.
*/
- TIMER_TIME_OF_DAY,
+ TIMER_TIME_OF_DAY =
+ TIMER_CLASS_BIT_NOT_DORMANT | TIMER_CLASS_BIT_TIME_OF_DAY,
/**
* This value indicates the timer is currently in use as an time of day
* timer which will fire in the timer server task.
*/
- TIMER_TIME_OF_DAY_ON_TASK,
-
- /**
- * This value indicates the timer is currently not in use.
- */
- TIMER_DORMANT
+ TIMER_TIME_OF_DAY_ON_TASK =
+ TIMER_CLASS_BIT_NOT_DORMANT | TIMER_CLASS_BIT_TIME_OF_DAY |
+ TIMER_CLASS_BIT_ON_TASK
} Timer_Classes;
/**
@@ -124,6 +135,16 @@ typedef struct {
Watchdog_Control Ticker;
/** This field indicates what type of timer this currently is. */
Timer_Classes the_class;
+ /** This field is the timer service routine. */
+ rtems_timer_service_routine_entry routine;
+ /** This field is the timer service routine user data. */
+ void *user_data;
+ /** This field is the timer interval in ticks or seconds. */
+ Watchdog_Interval initial;
+ /** This field is the timer start time point in ticks. */
+ Watchdog_Interval start_time;
+ /** This field is the timer stop time point in ticks. */
+ Watchdog_Interval stop_time;
} Timer_Control;
/**
@@ -296,16 +317,22 @@ rtems_status_code rtems_timer_reset(
);
/**
- * @brief rtems_timer_initiate_server
+ * @brief Initiates the timer server.
*
- * This routine implements the rtems_timer_initiate_server directive.
- * It creates and starts the server that executes task-based timers.
+ * This directive creates and starts the server for task-based timers.
* It must be invoked before any task-based timers can be initiated.
+ *
+ * @param priority The timer server task priority.
+ * @param stack_size The stack size in bytes for the timer server task.
+ * @param attribute_set The timer server task 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
+ rtems_task_priority priority,
+ size_t stack_size,
+ rtems_attribute attribute_set
);
/**
diff --git a/cpukit/rtems/include/rtems/rtems/timerimpl.h b/cpukit/rtems/include/rtems/rtems/timerimpl.h
index 55be6343c3..e4b4ca2ec4 100644
--- a/cpukit/rtems/include/rtems/rtems/timerimpl.h
+++ b/cpukit/rtems/include/rtems/rtems/timerimpl.h
@@ -10,6 +10,8 @@
* COPYRIGHT (c) 1989-2011.
* On-Line Applications Research Corporation (OAR).
*
+ * Copyright (c) 2016 embedded brains GmbH.
+ *
* 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.
@@ -35,81 +37,13 @@ extern "C" {
* @{
*/
-typedef struct Timer_server_Control Timer_server_Control;
+typedef struct Timer_server_Control {
+ ISR_LOCK_MEMBER( Lock )
-/**
- * @brief Method used for task based timers.
- */
-typedef void (*Timer_server_Method)(
- Timer_server_Control *timer_server,
- Timer_Control *timer
-);
+ Chain_Control Pending;
-typedef struct {
- /**
- * @brief This watchdog that will be registered in the system tick mechanic
- * for timer server wake-up.
- */
- 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 time snapshot of the timer server.
- *
- * The units may be ticks or seconds.
- */
- 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 The cancel method of the timer server.
- */
- Timer_server_Method cancel;
-
- /**
- * @brief The schedule operation method of the timer server.
- */
- Timer_server_Method schedule_operation;
-
- /**
- * @brief Interval watchdogs triggered by the timer server.
- */
- Timer_server_Watchdogs Interval_watchdogs;
-
- /**
- * @brief TOD watchdogs triggered by the timer server.
- */
- Timer_server_Watchdogs TOD_watchdogs;
-};
+ Objects_Id server_id;
+} Timer_server_Control;
/**
* @brief Pointer to default timer server control block.
@@ -148,64 +82,124 @@ RTEMS_INLINE_ROUTINE void _Timer_Free (
_Objects_Free( &_Timer_Information, &the_timer->Object );
}
-/**
- * @brief Timer_Get
- *
- * This function maps timer IDs to timer control blocks.
- * If ID corresponds to a local timer, then it returns
- * the timer control pointer which maps to ID and location
- * is set to OBJECTS_LOCAL. Otherwise, location is set
- * to OBJECTS_ERROR and the returned value is undefined.
- */
-RTEMS_INLINE_ROUTINE Timer_Control *_Timer_Get (
+RTEMS_INLINE_ROUTINE Timer_Control *_Timer_Get(
Objects_Id id,
- Objects_Locations *location
+ Objects_Locations *location,
+ ISR_lock_Context *lock_context
)
{
- return (Timer_Control *)
- _Objects_Get( &_Timer_Information, id, location );
+ return (Timer_Control *) _Objects_Get_isr_disable(
+ &_Timer_Information,
+ id,
+ location,
+ lock_context
+ );
}
-/**
- * @brief Timer_Is_interval_class
- *
- * This function returns TRUE if the class is that of an INTERVAL
- * timer, and FALSE otherwise.
- */
-RTEMS_INLINE_ROUTINE bool _Timer_Is_interval_class (
+RTEMS_INLINE_ROUTINE Per_CPU_Control *_Timer_Acquire_critical(
+ Timer_Control *the_timer,
+ ISR_lock_Context *lock_context
+)
+{
+ Per_CPU_Control *cpu;
+
+ cpu = _Watchdog_Get_CPU( &the_timer->Ticker );
+ _Watchdog_Per_CPU_acquire_critical( cpu, lock_context );
+
+ return cpu;
+}
+
+RTEMS_INLINE_ROUTINE void _Timer_Release(
+ Per_CPU_Control *cpu,
+ ISR_lock_Context *lock_context
+)
+{
+ _Watchdog_Per_CPU_release_critical( cpu, lock_context );
+ _ISR_lock_ISR_enable( lock_context );
+}
+
+RTEMS_INLINE_ROUTINE bool _Timer_Is_interval_class(
Timer_Classes the_class
)
{
- return (the_class == TIMER_INTERVAL) || (the_class == TIMER_INTERVAL_ON_TASK);
+ Timer_Classes mask =
+ TIMER_CLASS_BIT_NOT_DORMANT | TIMER_CLASS_BIT_TIME_OF_DAY;
+
+ return ( the_class & mask ) == TIMER_CLASS_BIT_NOT_DORMANT;
}
-/**
- * @brief Timer_Is_time_of_day_class
- *
- * This function returns TRUE if the class is that of an INTERVAL
- * timer, and FALSE otherwise.
- */
-RTEMS_INLINE_ROUTINE bool _Timer_Is_timer_of_day_class (
+RTEMS_INLINE_ROUTINE bool _Timer_Is_on_task_class(
Timer_Classes the_class
)
{
- return ( the_class == TIMER_TIME_OF_DAY );
+ Timer_Classes mask =
+ TIMER_CLASS_BIT_NOT_DORMANT | TIMER_CLASS_BIT_ON_TASK;
+
+ return ( the_class & mask ) == mask;
}
-/**
- * @brief Timer_Is_dormant_class
- *
- * This function returns TRUE if the class is that of a DORMANT
- * timer, and FALSE otherwise.
- */
-RTEMS_INLINE_ROUTINE bool _Timer_Is_dormant_class (
+RTEMS_INLINE_ROUTINE Per_CPU_Watchdog_index _Timer_Watchdog_header_index(
Timer_Classes the_class
)
{
- return ( the_class == TIMER_DORMANT );
+ return ( the_class & TIMER_CLASS_BIT_TIME_OF_DAY );
+}
+
+RTEMS_INLINE_ROUTINE Watchdog_Interval _Timer_Get_CPU_ticks(
+ const Per_CPU_Control *cpu
+)
+{
+ return (Watchdog_Interval) cpu->Watchdog.ticks;
}
-void _Timer_Cancel( Timer_Control *the_timer );
+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
+);
+
+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
+);
+
+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
+);
+
+void _Timer_Cancel( Per_CPU_Control *cpu, Timer_Control *the_timer );
+
+void _Timer_Routine_adaptor( Watchdog_Control *the_watchdog );
+
+void _Timer_server_Routine_adaptor( Watchdog_Control *the_watchdog );
+
+RTEMS_INLINE_ROUTINE void _Timer_server_Acquire_critical(
+ Timer_server_Control *timer_server,
+ ISR_lock_Context *lock_context
+)
+{
+ _ISR_lock_Acquire( &timer_server->Lock, lock_context );
+}
+
+RTEMS_INLINE_ROUTINE void _Timer_server_Release_critical(
+ Timer_server_Control *timer_server,
+ ISR_lock_Context *lock_context
+)
+{
+ _ISR_lock_Release( &timer_server->Lock, lock_context );
+}
/**@}*/
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 <rtems/score/threadimpl.h>
#include <rtems/score/watchdogimpl.h>
-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 <rtems/system.h>
-#include <rtems/rtems/status.h>
-#include <rtems/rtems/support.h>
-#include <rtems/score/thread.h>
#include <rtems/rtems/timerimpl.h>
-#include <rtems/score/watchdogimpl.h>
-
-/*
- * 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 <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,
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 <rtems/system.h>
-#include <rtems/rtems/status.h>
-#include <rtems/rtems/support.h>
-#include <rtems/score/thread.h>
#include <rtems/rtems/timerimpl.h>
-#include <rtems/score/watchdogimpl.h>
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 <rtems/system.h>
-#include <rtems/rtems/status.h>
-#include <rtems/rtems/support.h>
-#include <rtems/score/thread.h>
#include <rtems/rtems/timerimpl.h>
-#include <rtems/score/watchdogimpl.h>
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 <rtems/rtems/timerimpl.h>
-#include <rtems/rtems/clock.h>
-#include <rtems/score/todimpl.h>
-#include <rtems/score/watchdogimpl.h>
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,99 +136,35 @@ 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
* higher than any other task in the system. It can be viewed as a low
@@ -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 <rtems/system.h>
-#include <rtems/rtems/status.h>
-#include <rtems/rtems/support.h>
-#include <rtems/score/thread.h>
#include <rtems/rtems/timerimpl.h>
-#include <rtems/score/watchdogimpl.h>
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 <rtems/rtems/timerimpl.h>
-#include <rtems/rtems/clock.h>
-#include <rtems/score/todimpl.h>
-#include <rtems/score/watchdogimpl.h>
-
-/*
- * 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
+ );
}