summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cpukit/posix/Makefile.am3
-rw-r--r--cpukit/posix/include/rtems/posix/pthreadimpl.h5
-rw-r--r--cpukit/posix/include/rtems/posix/threadsup.h2
-rw-r--r--cpukit/posix/include/rtems/posix/timerimpl.h54
-rw-r--r--cpukit/posix/src/alarm.c96
-rw-r--r--cpukit/posix/src/nanosleep.c5
-rw-r--r--cpukit/posix/src/pthread.c31
-rw-r--r--cpukit/posix/src/pthreadcreate.c6
-rw-r--r--cpukit/posix/src/pthreadsetschedparam.c14
-rw-r--r--cpukit/posix/src/timercreate.c3
-rw-r--r--cpukit/posix/src/timerdelete.c12
-rw-r--r--cpukit/posix/src/timergetoverrun.c7
-rw-r--r--cpukit/posix/src/timergettime.c29
-rw-r--r--cpukit/posix/src/timerinserthelper.c66
-rw-r--r--cpukit/posix/src/timersettime.c152
-rw-r--r--cpukit/posix/src/timertsr.c89
-rw-r--r--cpukit/posix/src/ualarm.c155
-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
-rw-r--r--cpukit/sapi/src/exinit.c3
-rw-r--r--cpukit/score/Makefile.am5
-rw-r--r--cpukit/score/include/rtems/score/mrsp.h7
-rw-r--r--cpukit/score/include/rtems/score/mrspimpl.h32
-rw-r--r--cpukit/score/include/rtems/score/percpu.h53
-rw-r--r--cpukit/score/include/rtems/score/schedulerimpl.h16
-rw-r--r--cpukit/score/include/rtems/score/thread.h13
-rw-r--r--cpukit/score/include/rtems/score/threadimpl.h61
-rw-r--r--cpukit/score/include/rtems/score/todimpl.h17
-rw-r--r--cpukit/score/include/rtems/score/watchdog.h89
-rw-r--r--cpukit/score/include/rtems/score/watchdogimpl.h601
-rw-r--r--cpukit/score/src/condition.c2
-rw-r--r--cpukit/score/src/coretodset.c28
-rw-r--r--cpukit/score/src/coretodtickle.c36
-rw-r--r--cpukit/score/src/kern_tc.c3
-rw-r--r--cpukit/score/src/smp.c1
-rw-r--r--cpukit/score/src/threadinitialize.c4
-rw-r--r--cpukit/score/src/threadqenqueue.c10
-rw-r--r--cpukit/score/src/threadrestart.c12
-rw-r--r--cpukit/score/src/threadtimeout.c4
-rw-r--r--cpukit/score/src/watchdog.c36
-rw-r--r--cpukit/score/src/watchdogadjust.c80
-rw-r--r--cpukit/score/src/watchdoginsert.c132
-rw-r--r--cpukit/score/src/watchdogremove.c172
-rw-r--r--cpukit/score/src/watchdogtick.c78
-rw-r--r--testsuites/psxtests/psx04/init.c7
-rw-r--r--testsuites/smptests/Makefile.am1
-rw-r--r--testsuites/smptests/configure.ac1
-rw-r--r--testsuites/smptests/smpclock01/Makefile.am20
-rw-r--r--testsuites/smptests/smpclock01/init.c206
-rw-r--r--testsuites/smptests/smpclock01/smpclock01.doc11
-rw-r--r--testsuites/smptests/smpclock01/smpclock01.scn2
-rw-r--r--testsuites/smptests/smpwakeafter01/smpwakeafter01.scn224
-rw-r--r--testsuites/sptests/Makefile.am3
-rw-r--r--testsuites/sptests/configure.ac2
-rw-r--r--testsuites/sptests/sp31/task1.c22
-rw-r--r--testsuites/sptests/spintrcritical08/init.c26
-rw-r--r--testsuites/sptests/spintrcritical09/init.c27
-rw-r--r--testsuites/sptests/spintrcritical10/init.c6
-rw-r--r--testsuites/sptests/spintrcritical16/init.c2
-rw-r--r--testsuites/sptests/spintrcritical17/Makefile.am25
-rw-r--r--testsuites/sptests/spintrcritical17/init.c118
-rw-r--r--testsuites/sptests/spintrcritical17/spintrcritical17.doc18
-rw-r--r--testsuites/sptests/spintrcritical17/spintrcritical17.scn2
-rw-r--r--testsuites/sptests/spintrcritical20/init.c2
-rw-r--r--testsuites/sptests/spsize/size.c2
-rw-r--r--testsuites/sptests/sptimecounter01/init.c3
-rw-r--r--testsuites/sptests/sptimerserver01/Makefile.am19
-rw-r--r--testsuites/sptests/sptimerserver01/init.c129
-rw-r--r--testsuites/sptests/sptimerserver01/sptimerserver01.doc12
-rw-r--r--testsuites/sptests/sptimerserver01/sptimerserver01.scn2
-rw-r--r--testsuites/sptests/spwatchdog/init.c381
-rw-r--r--testsuites/tmtests/tmtimer01/tmtimer01.scn90
92 files changed, 2363 insertions, 2588 deletions
diff --git a/cpukit/posix/Makefile.am b/cpukit/posix/Makefile.am
index 40bc15339d..62a2a5aa3f 100644
--- a/cpukit/posix/Makefile.am
+++ b/cpukit/posix/Makefile.am
@@ -196,8 +196,7 @@ libposix_a_SOURCES += src/adjtime.c src/clockgetcpuclockid.c
## TIMER_C_FILES
libposix_a_SOURCES += src/ptimer.c src/timercreate.c src/timerdelete.c \
- src/timergetoverrun.c src/timergettime.c src/timersettime.c \
- src/timertsr.c src/timerinserthelper.c
+ src/timergetoverrun.c src/timergettime.c src/timersettime.c
## ITIMER_C_FILES
libposix_a_SOURCES += src/getitimer.c src/setitimer.c
diff --git a/cpukit/posix/include/rtems/posix/pthreadimpl.h b/cpukit/posix/include/rtems/posix/pthreadimpl.h
index 870b5f9460..16b0163384 100644
--- a/cpukit/posix/include/rtems/posix/pthreadimpl.h
+++ b/cpukit/posix/include/rtems/posix/pthreadimpl.h
@@ -114,10 +114,7 @@ void _POSIX_Threads_Sporadic_budget_callout(
* @param[in] argument is a pointer to the Thread_Control structure
* for the thread being replenished.
*/
-void _POSIX_Threads_Sporadic_budget_TSR(
- Objects_Id id,
- void *argument
-);
+void _POSIX_Threads_Sporadic_budget_TSR( Watchdog_Control *watchdog );
/**
* @brief Translate sched_param into SuperCore terms.
diff --git a/cpukit/posix/include/rtems/posix/threadsup.h b/cpukit/posix/include/rtems/posix/threadsup.h
index 55db35ddbd..7cd235409c 100644
--- a/cpukit/posix/include/rtems/posix/threadsup.h
+++ b/cpukit/posix/include/rtems/posix/threadsup.h
@@ -42,6 +42,8 @@ extern "C" {
* each thread in a system with POSIX configured.
*/
typedef struct {
+ /** Back pointer to thread of this POSIX API control. */
+ Thread_Control *thread;
/** This is the POSIX threads attribute set. */
pthread_attr_t Attributes;
/** This indicates whether the thread is attached or detached. */
diff --git a/cpukit/posix/include/rtems/posix/timerimpl.h b/cpukit/posix/include/rtems/posix/timerimpl.h
index 8b5b42e98a..2eefd7063c 100644
--- a/cpukit/posix/include/rtems/posix/timerimpl.h
+++ b/cpukit/posix/include/rtems/posix/timerimpl.h
@@ -21,6 +21,7 @@
#include <rtems/posix/timer.h>
#include <rtems/score/objectimpl.h>
+#include <rtems/score/watchdogimpl.h>
#ifdef __cplusplus
extern "C" {
@@ -51,24 +52,6 @@ extern "C" {
#endif
/**
- * @brief POSIX Timer Manager Timer Service Routine Helper
- *
- * This is the operation that is run when a timer expires.
- */
-void _POSIX_Timer_TSR(Objects_Id timer, void *data);
-
-/**
- * @brief POSIX Timer Watchdog Insertion Helper
- */
-bool _POSIX_Timer_Insert_helper(
- Watchdog_Control *timer,
- Watchdog_Interval ticks,
- Objects_Id id,
- Watchdog_Service_routine_entry TSR,
- void *arg
-);
-
-/**
* The following defines the information control block used to manage
* this class of objects.
*/
@@ -98,6 +81,8 @@ RTEMS_INLINE_ROUTINE void _POSIX_Timer_Free (
_Objects_Free( &_POSIX_Timer_Information, &the_timer->Object );
}
+void _POSIX_Timer_TSR( Watchdog_Control *the_watchdog );
+
/**
* @brief POSIX Timer Get
*
@@ -109,11 +94,38 @@ RTEMS_INLINE_ROUTINE void _POSIX_Timer_Free (
*/
RTEMS_INLINE_ROUTINE POSIX_Timer_Control *_POSIX_Timer_Get (
timer_t id,
- Objects_Locations *location
+ Objects_Locations *location,
+ ISR_lock_Context *lock_context
+)
+{
+ return (POSIX_Timer_Control *) _Objects_Get_isr_disable(
+ &_POSIX_Timer_Information,
+ (Objects_Id) id,
+ location,
+ lock_context
+ );
+}
+
+RTEMS_INLINE_ROUTINE Per_CPU_Control *_POSIX_Timer_Acquire_critical(
+ POSIX_Timer_Control *ptimer,
+ ISR_lock_Context *lock_context
+)
+{
+ Per_CPU_Control *cpu;
+
+ cpu = _Watchdog_Get_CPU( &ptimer->Timer );
+ _Watchdog_Per_CPU_acquire_critical( cpu, lock_context );
+
+ return cpu;
+}
+
+RTEMS_INLINE_ROUTINE void _POSIX_Timer_Release(
+ Per_CPU_Control *cpu,
+ ISR_lock_Context *lock_context
)
{
- return (POSIX_Timer_Control *)
- _Objects_Get( &_POSIX_Timer_Information, (Objects_Id) id, location );
+ _Watchdog_Per_CPU_release_critical( cpu, lock_context );
+ _ISR_lock_ISR_enable( lock_context );
}
#ifdef __cplusplus
diff --git a/cpukit/posix/src/alarm.c b/cpukit/posix/src/alarm.c
index e85622fdf1..10443e4760 100644
--- a/cpukit/posix/src/alarm.c
+++ b/cpukit/posix/src/alarm.c
@@ -22,29 +22,18 @@
#endif
#include <unistd.h>
+#include <signal.h>
-#include <rtems/posix/pthreadimpl.h>
-#include <rtems/posix/psignalimpl.h>
-#include <rtems/score/threaddispatch.h>
#include <rtems/score/todimpl.h>
#include <rtems/score/watchdogimpl.h>
-/*
- * _POSIX_signals_Alarm_TSR
- */
-static void _POSIX_signals_Alarm_TSR(
- Objects_Id id RTEMS_UNUSED,
- void *argument RTEMS_UNUSED
-)
+ISR_LOCK_DEFINE( static, _POSIX_signals_Alarm_lock, "POSIX Alarm" )
+
+static void _POSIX_signals_Alarm_TSR( Watchdog_Control *the_watchdog )
{
- #if defined(RTEMS_DEBUG)
- int status;
- #define KILL_STATUS status =
- #else
- #define KILL_STATUS (void)
- #endif
+ int status;
- KILL_STATUS kill( getpid(), SIGALRM );
+ status = kill( getpid(), SIGALRM );
#if defined(RTEMS_DEBUG)
/*
@@ -52,43 +41,62 @@ static void _POSIX_signals_Alarm_TSR(
* cautious.
*/
_Assert(status == 0);
+ #else
+ (void) status;
#endif
}
-static Watchdog_Control _POSIX_signals_Alarm_timer = WATCHDOG_INITIALIZER(
- _POSIX_signals_Alarm_TSR,
- 0,
- NULL
+static Watchdog_Control _POSIX_signals_Alarm_watchdog = WATCHDOG_INITIALIZER(
+ _POSIX_signals_Alarm_TSR
);
unsigned int alarm(
unsigned int seconds
)
{
- unsigned int remaining = 0;
- Watchdog_Control *the_timer;
- Watchdog_States state;
-
- the_timer = &_POSIX_signals_Alarm_timer;
-
- _Thread_Disable_dispatch();
-
- state = _Watchdog_Remove_seconds( the_timer );
- if ( state == WATCHDOG_ACTIVE ) {
- /*
- * The stop_time and start_time fields are snapshots of ticks since
- * boot. Since alarm() is dealing in seconds, we must account for
- * this.
- */
-
- remaining = the_timer->initial -
- ((the_timer->stop_time - the_timer->start_time) / TOD_TICKS_PER_SECOND);
+ unsigned int remaining;
+ Watchdog_Control *the_watchdog;
+ ISR_lock_Context lock_context;
+ ISR_lock_Context lock_context2;
+ Per_CPU_Control *cpu;
+ uint64_t now;
+ uint32_t ticks_per_second;
+ uint32_t ticks;
+
+ the_watchdog = &_POSIX_signals_Alarm_watchdog;
+ ticks_per_second = TOD_TICKS_PER_SECOND;
+ ticks = seconds * ticks_per_second;
+
+ _ISR_lock_ISR_disable_and_acquire(
+ &_POSIX_signals_Alarm_lock,
+ &lock_context
+ );
+
+ cpu = _Watchdog_Get_CPU( the_watchdog );
+ _Watchdog_Per_CPU_acquire_critical( cpu, &lock_context2 );
+ now = cpu->Watchdog.ticks;
+
+ remaining = (unsigned long) _Watchdog_Cancel(
+ &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_RELATIVE ],
+ the_watchdog,
+ now
+ );
+
+ if ( ticks != 0 ) {
+ cpu = _Per_CPU_Get();
+ _Watchdog_Set_CPU( the_watchdog, cpu );
+ _Watchdog_Insert(
+ &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_RELATIVE ],
+ the_watchdog,
+ now + ticks
+ );
}
- if ( seconds )
- _Watchdog_Insert_seconds( the_timer, seconds );
-
- _Thread_Enable_dispatch();
+ _Watchdog_Per_CPU_release_critical( cpu, &lock_context2 );
+ _ISR_lock_Release_and_ISR_enable(
+ &_POSIX_signals_Alarm_lock,
+ &lock_context
+ );
- return remaining;
+ return ( remaining + ticks_per_second - 1 ) / ticks_per_second;
}
diff --git a/cpukit/posix/src/nanosleep.c b/cpukit/posix/src/nanosleep.c
index 46697ae8fc..21bdb986b6 100644
--- a/cpukit/posix/src/nanosleep.c
+++ b/cpukit/posix/src/nanosleep.c
@@ -46,6 +46,7 @@ int nanosleep(
Per_CPU_Control *cpu_self;
Watchdog_Interval ticks;
+ Watchdog_Interval start;
Watchdog_Interval elapsed;
@@ -81,6 +82,8 @@ int nanosleep(
return 0;
}
+ start = _Watchdog_Ticks_since_boot;
+
/*
* Block for the desired amount of time
*/
@@ -96,7 +99,7 @@ int nanosleep(
* Calculate the time that passed while we were sleeping and how
* much remains from what we requested.
*/
- elapsed = executing->Timer.stop_time - executing->Timer.start_time;
+ elapsed = _Watchdog_Ticks_since_boot - start;
if ( elapsed >= ticks )
ticks = 0;
else
diff --git a/cpukit/posix/src/pthread.c b/cpukit/posix/src/pthread.c
index ac5fbe44bf..001ae7947a 100644
--- a/cpukit/posix/src/pthread.c
+++ b/cpukit/posix/src/pthread.c
@@ -104,18 +104,15 @@ static bool _POSIX_Threads_Sporadic_budget_TSR_filter(
/*
* _POSIX_Threads_Sporadic_budget_TSR
*/
-void _POSIX_Threads_Sporadic_budget_TSR(
- Objects_Id id RTEMS_UNUSED,
- void *argument
-)
+void _POSIX_Threads_Sporadic_budget_TSR( Watchdog_Control *watchdog )
{
uint32_t ticks;
- Thread_Control *the_thread;
POSIX_API_Control *api;
+ Thread_Control *the_thread;
+ ISR_Level level;
- the_thread = argument;
-
- api = the_thread->API_Extensions[ THREAD_API_POSIX ];
+ api = RTEMS_CONTAINER_OF( watchdog, POSIX_API_Control, Sporadic_timer );
+ the_thread = api->thread;
/* ticks is guaranteed to be at least one */
ticks = _Timespec_To_ticks( &api->schedparam.sched_ss_init_budget );
@@ -133,7 +130,15 @@ void _POSIX_Threads_Sporadic_budget_TSR(
/* ticks is guaranteed to be at least one */
ticks = _Timespec_To_ticks( &api->schedparam.sched_ss_repl_period );
- _Watchdog_Insert_ticks( &api->Sporadic_timer, ticks );
+ _Thread_Disable_dispatch();
+ _ISR_Disable( level );
+ _Watchdog_Per_CPU_insert_relative(
+ &api->Sporadic_timer,
+ _Per_CPU_Get(),
+ ticks
+ );
+ _ISR_Enable( level );
+ _Thread_Unnest_dispatch();
}
static bool _POSIX_Threads_Sporadic_budget_callout_filter(
@@ -198,6 +203,7 @@ static bool _POSIX_Threads_Create_extension(
api = created->API_Extensions[ THREAD_API_POSIX ];
/* XXX check all fields are touched */
+ api->thread = created;
_POSIX_Threads_Initialize_attributes( &api->Attributes );
api->detachstate = _POSIX_Threads_Default_attributes.detachstate;
api->schedpolicy = _POSIX_Threads_Default_attributes.schedpolicy;
@@ -229,11 +235,10 @@ static bool _POSIX_Threads_Create_extension(
_Thread_queue_Initialize( &api->Join_List, THREAD_QUEUE_DISCIPLINE_FIFO );
+ _Watchdog_Preinitialize( &api->Sporadic_timer, _Per_CPU_Get_by_index( 0 ) );
_Watchdog_Initialize(
&api->Sporadic_timer,
- _POSIX_Threads_Sporadic_budget_TSR,
- created->Object.id,
- created
+ _POSIX_Threads_Sporadic_budget_TSR
);
return true;
@@ -260,7 +265,7 @@ static void _POSIX_Threads_Terminate_extension(
*(void **)the_thread->Wait.return_argument = value_ptr;
if ( api->schedpolicy == SCHED_SPORADIC )
- _Watchdog_Remove_ticks( &api->Sporadic_timer );
+ _Watchdog_Per_CPU_remove_relative( &api->Sporadic_timer );
_Thread_queue_Destroy( &api->Join_List );
diff --git a/cpukit/posix/src/pthreadcreate.c b/cpukit/posix/src/pthreadcreate.c
index 3185ab6553..fc07b1f7e1 100644
--- a/cpukit/posix/src/pthreadcreate.c
+++ b/cpukit/posix/src/pthreadcreate.c
@@ -74,6 +74,7 @@ int pthread_create(
struct sched_param schedparam;
Objects_Name name;
int rc;
+ ISR_Level level;
if ( !start_routine )
return EFAULT;
@@ -246,10 +247,13 @@ int pthread_create(
#endif
if ( schedpolicy == SCHED_SPORADIC ) {
- _Watchdog_Insert_ticks(
+ _ISR_Disable( level );
+ _Watchdog_Per_CPU_insert_relative(
&api->Sporadic_timer,
+ _Per_CPU_Get(),
_Timespec_To_ticks( &api->schedparam.sched_ss_repl_period )
);
+ _ISR_Enable( level );
}
_Thread_Enable_dispatch();
diff --git a/cpukit/posix/src/pthreadsetschedparam.c b/cpukit/posix/src/pthreadsetschedparam.c
index c3be366818..c9560f59ac 100644
--- a/cpukit/posix/src/pthreadsetschedparam.c
+++ b/cpukit/posix/src/pthreadsetschedparam.c
@@ -44,6 +44,7 @@ int pthread_setschedparam(
Objects_Locations location;
int rc;
Priority_Control unused;
+ ISR_Level level;
/*
* Check all the parameters
@@ -69,8 +70,11 @@ int pthread_setschedparam(
case OBJECTS_LOCAL:
api = the_thread->API_Extensions[ THREAD_API_POSIX ];
- if ( api->schedpolicy == SCHED_SPORADIC )
- _Watchdog_Remove_ticks( &api->Sporadic_timer );
+ if ( api->schedpolicy == SCHED_SPORADIC ) {
+ _ISR_Disable( level );
+ _Watchdog_Per_CPU_remove_relative( &api->Sporadic_timer );
+ _ISR_Enable( level );
+ }
api->schedpolicy = policy;
api->schedparam = *param;
@@ -97,8 +101,10 @@ int pthread_setschedparam(
case SCHED_SPORADIC:
api->ss_high_priority = api->schedparam.sched_priority;
- _Watchdog_Remove_ticks( &api->Sporadic_timer );
- _POSIX_Threads_Sporadic_budget_TSR( 0, the_thread );
+ _ISR_Disable( level );
+ _Watchdog_Per_CPU_remove_relative( &api->Sporadic_timer );
+ _ISR_Enable( level );
+ _POSIX_Threads_Sporadic_budget_TSR( &api->Sporadic_timer );
break;
}
diff --git a/cpukit/posix/src/timercreate.c b/cpukit/posix/src/timercreate.c
index 697f1ceee1..5123071d99 100644
--- a/cpukit/posix/src/timercreate.c
+++ b/cpukit/posix/src/timercreate.c
@@ -91,7 +91,8 @@ int timer_create(
ptimer->timer_data.it_interval.tv_sec = 0;
ptimer->timer_data.it_interval.tv_nsec = 0;
- _Watchdog_Preinitialize( &ptimer->Timer );
+ _Watchdog_Preinitialize( &ptimer->Timer, _Per_CPU_Get_snapshot() );
+ _Watchdog_Initialize( &ptimer->Timer, _POSIX_Timer_TSR );
_Objects_Open_u32(&_POSIX_Timer_Information, &ptimer->Object, 0);
*timerid = ptimer->Object.id;
diff --git a/cpukit/posix/src/timerdelete.c b/cpukit/posix/src/timerdelete.c
index 8438b0d5b0..c39de8e168 100644
--- a/cpukit/posix/src/timerdelete.c
+++ b/cpukit/posix/src/timerdelete.c
@@ -45,16 +45,22 @@ int timer_delete(
*/
POSIX_Timer_Control *ptimer;
Objects_Locations location;
+ ISR_lock_Context lock_context;
+ Per_CPU_Control *cpu;
_Objects_Allocator_lock();
- ptimer = _POSIX_Timer_Get( timerid, &location );
+ ptimer = _POSIX_Timer_Get( timerid, &location, &lock_context );
switch ( location ) {
case OBJECTS_LOCAL:
_Objects_Close( &_POSIX_Timer_Information, &ptimer->Object );
+ cpu = _POSIX_Timer_Acquire_critical( ptimer, &lock_context );
ptimer->state = POSIX_TIMER_STATE_FREE;
- _Watchdog_Remove_ticks( &ptimer->Timer );
- _Objects_Put( &ptimer->Object );
+ _Watchdog_Remove(
+ &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_RELATIVE ],
+ &ptimer->Timer
+ );
+ _POSIX_Timer_Release( cpu, &lock_context );
_POSIX_Timer_Free( ptimer );
_Objects_Allocator_unlock();
diff --git a/cpukit/posix/src/timergetoverrun.c b/cpukit/posix/src/timergetoverrun.c
index dd7669ee89..0a28fa7b5f 100644
--- a/cpukit/posix/src/timergetoverrun.c
+++ b/cpukit/posix/src/timergetoverrun.c
@@ -33,14 +33,17 @@ int timer_getoverrun(
int overrun;
POSIX_Timer_Control *ptimer;
Objects_Locations location;
+ ISR_lock_Context lock_context;
+ Per_CPU_Control *cpu;
- ptimer = _POSIX_Timer_Get( timerid, &location );
+ ptimer = _POSIX_Timer_Get( timerid, &location, &lock_context );
switch ( location ) {
case OBJECTS_LOCAL:
+ cpu = _POSIX_Timer_Acquire_critical( ptimer, &lock_context );
overrun = ptimer->overrun;
ptimer->overrun = 0;
- _Objects_Put( &ptimer->Object );
+ _POSIX_Timer_Release( cpu, &lock_context );
return overrun;
#if defined(RTEMS_MULTIPROCESSING)
diff --git a/cpukit/posix/src/timergettime.c b/cpukit/posix/src/timergettime.c
index f065cc927c..7f0015bf5e 100644
--- a/cpukit/posix/src/timergettime.c
+++ b/cpukit/posix/src/timergettime.c
@@ -42,31 +42,32 @@ int timer_gettime(
{
POSIX_Timer_Control *ptimer;
Objects_Locations location;
- struct timespec current_time;
- Watchdog_Interval left;
+ ISR_lock_Context lock_context;
+ Per_CPU_Control *cpu;
+ uint64_t now;
+ uint32_t remaining;
if ( !value )
rtems_set_errno_and_return_minus_one( EINVAL );
- /* Reads the current time */
- _TOD_Get_as_timespec( &current_time );
-
- ptimer = _POSIX_Timer_Get( timerid, &location );
+ ptimer = _POSIX_Timer_Get( timerid, &location, &lock_context );
switch ( location ) {
case OBJECTS_LOCAL:
- /* Calculates the time left before the timer finishes */
-
- left =
- (ptimer->Timer.start_time + ptimer->Timer.initial) - /* expire */
- _Watchdog_Ticks_since_boot; /* now */
+ cpu = _POSIX_Timer_Acquire_critical( ptimer, &lock_context );
+ now = cpu->Watchdog.ticks;
- _Timespec_From_ticks( left, &value->it_value );
+ if ( now < ptimer->Timer.expire ) {
+ remaining = (uint32_t) ( ptimer->Timer.expire - now );
+ } else {
+ remaining = 0;
+ }
- value->it_interval = ptimer->timer_data.it_interval;
+ _Timespec_From_ticks( remaining, &value->it_value );
+ value->it_interval = ptimer->timer_data.it_interval;
- _Objects_Put( &ptimer->Object );
+ _POSIX_Timer_Release( cpu, &lock_context );
return 0;
#if defined(RTEMS_MULTIPROCESSING)
diff --git a/cpukit/posix/src/timerinserthelper.c b/cpukit/posix/src/timerinserthelper.c
deleted file mode 100644
index b1f3373e06..0000000000
--- a/cpukit/posix/src/timerinserthelper.c
+++ /dev/null
@@ -1,66 +0,0 @@
-/**
- * @file
- *
- * @brief Helper Routine for POSIX TIMERS
- * @ingroup POSIXAPI
- */
-
-/*
- * Helper routine for POSIX timers
- *
- * COPYRIGHT (c) 1989-2007.
- * On-Line Applications Research Corporation (OAR).
- *
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
- */
-
-#if HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <time.h>
-
-#include <rtems/system.h>
-#include <rtems/seterr.h>
-#include <rtems/score/isr.h>
-#include <rtems/score/watchdogimpl.h>
-#include <rtems/posix/timerimpl.h>
-#include <rtems/posix/ptimer.h>
-
-bool _POSIX_Timer_Insert_helper(
- Watchdog_Control *timer,
- Watchdog_Interval ticks,
- Objects_Id id,
- Watchdog_Service_routine_entry TSR,
- void *arg
-)
-{
- ISR_lock_Context lock_context;
- Watchdog_Header *header;
-
- _Watchdog_Remove_ticks( timer );
-
- header = &_Watchdog_Ticks_header;
- _Watchdog_Acquire( header, &lock_context );
-
- /*
- * Check to see if the watchdog has just been inserted by a
- * higher priority interrupt. If so, abandon this insert.
- */
- if ( timer->state != WATCHDOG_INACTIVE ) {
- _Watchdog_Release( header, &lock_context );
- return false;
- }
-
- /*
- * OK. Now we now the timer was not rescheduled by an interrupt
- * so we can atomically initialize it as in use.
- */
- _Watchdog_Initialize( timer, TSR, id, arg );
- timer->initial = ticks;
- _Watchdog_Insert_locked( header, timer, &lock_context );
- _Watchdog_Release( header, &lock_context );
- return true;
-}
diff --git a/cpukit/posix/src/timersettime.c b/cpukit/posix/src/timersettime.c
index fe54ff95c1..ac5c258eda 100644
--- a/cpukit/posix/src/timersettime.c
+++ b/cpukit/posix/src/timersettime.c
@@ -29,6 +29,76 @@
#include <rtems/score/watchdogimpl.h>
#include <rtems/seterr.h>
+static void _POSIX_Timer_Insert(
+ POSIX_Timer_Control *ptimer,
+ Per_CPU_Control *cpu,
+ Watchdog_Interval ticks
+)
+{
+ ptimer->ticks = ticks;
+
+ /* The state really did not change but just to be safe */
+ ptimer->state = POSIX_TIMER_STATE_CREATE_RUN;
+
+ /* Store the time when the timer was started again */
+ _TOD_Get_as_timespec( &ptimer->time );
+
+ _Watchdog_Insert(
+ &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_RELATIVE ],
+ &ptimer->Timer,
+ cpu->Watchdog.ticks + ticks
+ );
+}
+
+/*
+ * This is the operation that is run when a timer expires
+ */
+void _POSIX_Timer_TSR( Watchdog_Control *the_watchdog )
+{
+ POSIX_Timer_Control *ptimer;
+ ISR_lock_Context lock_context;
+ Per_CPU_Control *cpu;
+
+ ptimer = RTEMS_CONTAINER_OF( the_watchdog, POSIX_Timer_Control, Timer );
+ _ISR_lock_ISR_disable( &lock_context );
+ cpu = _POSIX_Timer_Acquire_critical( ptimer, &lock_context );
+
+ /* Increment the number of expirations. */
+ ptimer->overrun = ptimer->overrun + 1;
+
+ /* The timer must be reprogrammed */
+ if ( ( ptimer->timer_data.it_interval.tv_sec != 0 ) ||
+ ( ptimer->timer_data.it_interval.tv_nsec != 0 ) ) {
+ _POSIX_Timer_Insert( ptimer, cpu, ptimer->ticks );
+ } else {
+ /* Indicates that the timer is stopped */
+ ptimer->state = POSIX_TIMER_STATE_CREATE_STOP;
+ }
+
+ _POSIX_Timer_Release( cpu, &lock_context );
+
+ /*
+ * The sending of the signal to the process running the handling function
+ * specified for that signal is simulated
+ */
+
+ if ( pthread_kill ( ptimer->thread_id, ptimer->inf.sigev_signo ) ) {
+ _Assert( FALSE );
+ /*
+ * TODO: What if an error happens at run-time? This should never
+ * occur because the timer should be canceled if the thread
+ * is deleted. This method is being invoked from the Clock
+ * Tick ISR so even if we decide to take action on an error,
+ * we don't have many options. We shouldn't shut the system down.
+ */
+ }
+
+ /* After the signal handler returns, the count of expirations of the
+ * timer must be set to 0.
+ */
+ ptimer->overrun = 0;
+}
+
int timer_settime(
timer_t timerid,
int flags,
@@ -38,7 +108,8 @@ int timer_settime(
{
POSIX_Timer_Control *ptimer;
Objects_Locations location;
- bool activated;
+ ISR_lock_Context lock_context;
+ Per_CPU_Control *cpu;
uint32_t initial_period;
struct itimerspec normalize;
@@ -77,56 +148,47 @@ int timer_settime(
* or start it again
*/
- ptimer = _POSIX_Timer_Get( timerid, &location );
+ ptimer = _POSIX_Timer_Get( timerid, &location, &lock_context );
switch ( location ) {
case OBJECTS_LOCAL:
+ cpu = _POSIX_Timer_Acquire_critical( ptimer, &lock_context );
+
+ /* Stop the timer */
+ _Watchdog_Remove(
+ &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_RELATIVE ],
+ &ptimer->Timer
+ );
+
/* First, it verifies if the timer must be stopped */
if ( normalize.it_value.tv_sec == 0 && normalize.it_value.tv_nsec == 0 ) {
- /* Stop the timer */
- _Watchdog_Remove_ticks( &ptimer->Timer );
- /* The old data of the timer are returned */
- if ( ovalue )
- *ovalue = ptimer->timer_data;
- /* The new data are set */
- ptimer->timer_data = normalize;
- /* Indicates that the timer is created and stopped */
- ptimer->state = POSIX_TIMER_STATE_CREATE_STOP;
- /* Returns with success */
- _Objects_Put( &ptimer->Object );
+ /* The old data of the timer are returned */
+ if ( ovalue )
+ *ovalue = ptimer->timer_data;
+ /* The new data are set */
+ ptimer->timer_data = normalize;
+ /* Indicates that the timer is created and stopped */
+ ptimer->state = POSIX_TIMER_STATE_CREATE_STOP;
+ /* Returns with success */
+ _POSIX_Timer_Release( cpu, &lock_context );
return 0;
- }
-
- /* Convert from seconds and nanoseconds to ticks */
- ptimer->ticks = _Timespec_To_ticks( &value->it_interval );
- initial_period = _Timespec_To_ticks( &normalize.it_value );
-
-
- activated = _POSIX_Timer_Insert_helper(
- &ptimer->Timer,
- initial_period,
- ptimer->Object.id,
- _POSIX_Timer_TSR,
- ptimer
- );
- if ( !activated ) {
- _Objects_Put( &ptimer->Object );
- return 0;
- }
-
- /*
- * The timer has been started and is running. So we return the
- * old ones in "ovalue"
- */
- if ( ovalue )
- *ovalue = ptimer->timer_data;
- ptimer->timer_data = normalize;
-
- /* Indicate that the time is running */
- ptimer->state = POSIX_TIMER_STATE_CREATE_RUN;
- _TOD_Get_as_timespec( &ptimer->time );
- _Objects_Put( &ptimer->Object );
- return 0;
+ }
+
+ /* Convert from seconds and nanoseconds to ticks */
+ ptimer->ticks = _Timespec_To_ticks( &value->it_interval );
+ initial_period = _Timespec_To_ticks( &normalize.it_value );
+
+ _POSIX_Timer_Insert( ptimer, cpu, initial_period );
+
+ /*
+ * The timer has been started and is running. So we return the
+ * old ones in "ovalue"
+ */
+ if ( ovalue )
+ *ovalue = ptimer->timer_data;
+ ptimer->timer_data = normalize;
+ _POSIX_Timer_Release( cpu, &lock_context );
+ return 0;
#if defined(RTEMS_MULTIPROCESSING)
case OBJECTS_REMOTE:
diff --git a/cpukit/posix/src/timertsr.c b/cpukit/posix/src/timertsr.c
deleted file mode 100644
index 092bf16aa3..0000000000
--- a/cpukit/posix/src/timertsr.c
+++ /dev/null
@@ -1,89 +0,0 @@
-/**
- * @file
- *
- * @brief Operation that is run when a timer expires
- * @ingroup POSIX_INTERNAL_TIMERS Timers
- */
-
-/*
- * _POSIX_Timer_TSR
- *
- * COPYRIGHT (c) 1989-2007.
- * On-Line Applications Research Corporation (OAR).
- *
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
- */
-
-#if HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <time.h>
-#include <pthread.h>
-#include <signal.h>
-
-#include <rtems/posix/ptimer.h>
-#include <rtems/posix/timerimpl.h>
-#include <rtems/score/todimpl.h>
-
-/*
- * This is the operation that is run when a timer expires
- */
-void _POSIX_Timer_TSR(
- Objects_Id timer RTEMS_UNUSED,
- void *data)
-{
- POSIX_Timer_Control *ptimer;
- bool activated;
-
- ptimer = (POSIX_Timer_Control *)data;
-
- /* Increment the number of expirations. */
- ptimer->overrun = ptimer->overrun + 1;
-
- /* The timer must be reprogrammed */
- if ( ( ptimer->timer_data.it_interval.tv_sec != 0 ) ||
- ( ptimer->timer_data.it_interval.tv_nsec != 0 ) ) {
- activated = _POSIX_Timer_Insert_helper(
- &ptimer->Timer,
- ptimer->ticks,
- ptimer->Object.id,
- _POSIX_Timer_TSR,
- ptimer
- );
- if ( !activated )
- return;
-
- /* Store the time when the timer was started again */
- _TOD_Get_as_timespec( &ptimer->time );
-
- /* The state really did not change but just to be safe */
- ptimer->state = POSIX_TIMER_STATE_CREATE_RUN;
- } else {
- /* Indicates that the timer is stopped */
- ptimer->state = POSIX_TIMER_STATE_CREATE_STOP;
- }
-
- /*
- * The sending of the signal to the process running the handling function
- * specified for that signal is simulated
- */
-
- if ( pthread_kill ( ptimer->thread_id, ptimer->inf.sigev_signo ) ) {
- _Assert( FALSE );
- /*
- * TODO: What if an error happens at run-time? This should never
- * occur because the timer should be canceled if the thread
- * is deleted. This method is being invoked from the Clock
- * Tick ISR so even if we decide to take action on an error,
- * we don't have many options. We shouldn't shut the system down.
- */
- }
-
- /* After the signal handler returns, the count of expirations of the
- * timer must be set to 0.
- */
- ptimer->overrun = 0;
-}
diff --git a/cpukit/posix/src/ualarm.c b/cpukit/posix/src/ualarm.c
index 9607d3f62c..86fe1b05cc 100644
--- a/cpukit/posix/src/ualarm.c
+++ b/cpukit/posix/src/ualarm.c
@@ -21,39 +21,62 @@
#include <signal.h>
#include <unistd.h>
-#include <rtems/posix/pthreadimpl.h>
-#include <rtems/posix/psignalimpl.h>
-#include <rtems/score/threaddispatch.h>
#include <rtems/score/todimpl.h>
#include <rtems/score/watchdogimpl.h>
+#include <rtems/config.h>
-static void _POSIX_signals_Ualarm_TSR( Objects_Id id, void *argument );
+ISR_LOCK_DEFINE( static, _POSIX_signals_Ualarm_lock, "POSIX Ualarm" )
-static Watchdog_Control _POSIX_signals_Ualarm_timer = WATCHDOG_INITIALIZER(
- _POSIX_signals_Ualarm_TSR,
- 0,
- NULL
-);
-
-/*
- * _POSIX_signals_Ualarm_TSR
- */
+static uint32_t _POSIX_signals_Ualarm_interval;
-static void _POSIX_signals_Ualarm_TSR(
- Objects_Id id RTEMS_UNUSED,
- void *argument RTEMS_UNUSED
-)
+static void _POSIX_signals_Ualarm_TSR( Watchdog_Control *the_watchdog )
{
- /*
- * Send a SIGALRM but if there is a problem, ignore it.
- * It's OK, there isn't a way this should fail.
- */
- (void) kill( getpid(), SIGALRM );
+ int status;
+ ISR_lock_Context lock_context;
+
+ status = kill( getpid(), SIGALRM );
+
+ #if defined(RTEMS_DEBUG)
+ /*
+ * There is no reason to think this might fail but we should be
+ * cautious.
+ */
+ _Assert(status == 0);
+ #else
+ (void) status;
+ #endif
+
+ _ISR_lock_ISR_disable_and_acquire(
+ &_POSIX_signals_Ualarm_lock,
+ &lock_context
+ );
/*
* If the reset interval is non-zero, reschedule ourselves.
*/
- _Watchdog_Reset_ticks( &_POSIX_signals_Ualarm_timer );
+ if ( _POSIX_signals_Ualarm_interval != 0 ) {
+ _Watchdog_Per_CPU_insert_relative(
+ the_watchdog,
+ _Per_CPU_Get(),
+ _POSIX_signals_Ualarm_interval
+ );
+ }
+
+ _ISR_lock_Release_and_ISR_enable(
+ &_POSIX_signals_Ualarm_lock,
+ &lock_context
+ );
+}
+
+static Watchdog_Control _POSIX_signals_Ualarm_watchdog = WATCHDOG_INITIALIZER(
+ _POSIX_signals_Ualarm_TSR
+);
+
+static uint32_t _POSIX_signals_Ualarm_us_to_ticks( useconds_t us )
+{
+ uint32_t us_per_tick = rtems_configuration_get_microseconds_per_tick();
+
+ return ( us + us_per_tick - 1 ) / us_per_tick;
}
useconds_t ualarm(
@@ -61,51 +84,53 @@ useconds_t ualarm(
useconds_t interval
)
{
- useconds_t remaining = 0;
- Watchdog_Control *the_timer;
- Watchdog_Interval ticks;
- Watchdog_States state;
- struct timespec tp;
-
- the_timer = &_POSIX_signals_Ualarm_timer;
-
- _Thread_Disable_dispatch();
-
- state = _Watchdog_Remove_ticks( the_timer );
- if ( state == WATCHDOG_ACTIVE ) {
- /*
- * The stop_time and start_time fields are snapshots of ticks since
- * boot. Since alarm() is dealing in seconds, we must account for
- * this.
- */
-
- ticks = the_timer->initial;
- ticks -= (the_timer->stop_time - the_timer->start_time);
- /* remaining is now in ticks */
-
- _Timespec_From_ticks( ticks, &tp );
- remaining = tp.tv_sec * TOD_MICROSECONDS_PER_SECOND;
- remaining += tp.tv_nsec / 1000;
+ useconds_t remaining;
+ Watchdog_Control *the_watchdog;
+ ISR_lock_Context lock_context;
+ ISR_lock_Context lock_context2;
+ Per_CPU_Control *cpu;
+ uint64_t now;
+ uint32_t ticks_initial;
+ uint32_t ticks_interval;
+
+ the_watchdog = &_POSIX_signals_Ualarm_watchdog;
+ ticks_initial = _POSIX_signals_Ualarm_us_to_ticks( useconds );
+ ticks_interval = _POSIX_signals_Ualarm_us_to_ticks( interval );
+
+ _ISR_lock_ISR_disable_and_acquire(
+ &_POSIX_signals_Ualarm_lock,
+ &lock_context
+ );
+
+ cpu = _Watchdog_Get_CPU( the_watchdog );
+ _Watchdog_Per_CPU_acquire_critical( cpu, &lock_context2 );
+ now = cpu->Watchdog.ticks;
+
+ remaining = (useconds_t) _Watchdog_Cancel(
+ &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_RELATIVE ],
+ the_watchdog,
+ now
+ );
+
+ if ( ticks_initial != 0 ) {
+ _POSIX_signals_Ualarm_interval = ticks_interval;
+
+ cpu = _Per_CPU_Get();
+ _Watchdog_Set_CPU( the_watchdog, cpu );
+ _Watchdog_Insert(
+ &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_RELATIVE ],
+ the_watchdog,
+ now + ticks_initial
+ );
}
- /*
- * If useconds is non-zero, then the caller wants to schedule
- * the alarm repeatedly at that interval. If the interval is
- * less than a single clock tick, then fudge it to a clock tick.
- */
- if ( useconds ) {
- Watchdog_Interval ticks;
-
- tp.tv_sec = useconds / TOD_MICROSECONDS_PER_SECOND;
- tp.tv_nsec = (useconds % TOD_MICROSECONDS_PER_SECOND) * 1000;
- ticks = _Timespec_To_ticks( &tp );
- if ( ticks == 0 )
- ticks = 1;
-
- _Watchdog_Insert_ticks( the_timer, _Timespec_To_ticks( &tp ) );
- }
+ _Watchdog_Per_CPU_release_critical( cpu, &lock_context2 );
+ _ISR_lock_Release_and_ISR_enable(
+ &_POSIX_signals_Ualarm_lock,
+ &lock_context
+ );
- _Thread_Enable_dispatch();
+ remaining *= rtems_configuration_get_microseconds_per_tick();
return remaining;
}
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
+ );
}
diff --git a/cpukit/sapi/src/exinit.c b/cpukit/sapi/src/exinit.c
index 7df23161f3..350c774fc6 100644
--- a/cpukit/sapi/src/exinit.c
+++ b/cpukit/sapi/src/exinit.c
@@ -38,7 +38,6 @@
#include <rtems/score/timecounter.h>
#include <rtems/score/threadimpl.h>
#include <rtems/score/todimpl.h>
-#include <rtems/score/watchdogimpl.h>
#include <rtems/score/wkspace.h>
const char _Copyright_Notice[] =
@@ -87,8 +86,6 @@ static void rtems_initialize_data_structures(void)
_API_Mutex_Allocate( &_RTEMS_Allocator_Mutex );
_API_Mutex_Allocate( &_Once_Mutex );
- _Watchdog_Handler_initialization();
-
_Thread_Handler_initialization();
_Scheduler_Handler_initialization();
diff --git a/cpukit/score/Makefile.am b/cpukit/score/Makefile.am
index 3d3f1c1532..ea440b384e 100644
--- a/cpukit/score/Makefile.am
+++ b/cpukit/score/Makefile.am
@@ -327,14 +327,13 @@ libscore_a_SOURCES += src/timespecaddto.c src/timespecfromticks.c \
## TOD_C_FILES
libscore_a_SOURCES += src/coretod.c src/coretodset.c \
- src/coretodtickle.c \
src/coretodtickspersec.c \
src/coretodadjust.c
libscore_a_SOURCES += src/coretodabsolutetimeout.c
## WATCHDOG_C_FILES
-libscore_a_SOURCES += src/watchdog.c src/watchdogadjust.c \
- src/watchdoginsert.c src/watchdogremove.c
+libscore_a_SOURCES += src/watchdoginsert.c
+libscore_a_SOURCES += src/watchdogremove.c
libscore_a_SOURCES += src/watchdogtick.c
libscore_a_SOURCES += src/watchdogtickssinceboot.c
diff --git a/cpukit/score/include/rtems/score/mrsp.h b/cpukit/score/include/rtems/score/mrsp.h
index 08f96ac4ac..cb3de67e26 100644
--- a/cpukit/score/include/rtems/score/mrsp.h
+++ b/cpukit/score/include/rtems/score/mrsp.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014 embedded brains GmbH. All rights reserved.
+ * Copyright (c) 2014, 2016 embedded brains GmbH. All rights reserved.
*
* embedded brains GmbH
* Dornierstr. 4
@@ -128,6 +128,11 @@ typedef struct {
* MRSP_TIMEOUT. State changes are protected by the MrsP control lock.
*/
volatile MRSP_Status status;
+
+ /**
+ * @brief Watchdog for timeouts.
+ */
+ Watchdog_Control Watchdog;
} MRSP_Rival;
/**
diff --git a/cpukit/score/include/rtems/score/mrspimpl.h b/cpukit/score/include/rtems/score/mrspimpl.h
index bc9ed4b511..7638fb5975 100644
--- a/cpukit/score/include/rtems/score/mrspimpl.h
+++ b/cpukit/score/include/rtems/score/mrspimpl.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2015 embedded brains GmbH. All rights reserved.
+ * Copyright (c) 2014, 2016 embedded brains GmbH. All rights reserved.
*
* embedded brains GmbH
* Dornierstr. 4
@@ -159,18 +159,13 @@ RTEMS_INLINE_ROUTINE void _MRSP_Set_ceiling_priority(
mrsp->ceiling_priorities[ scheduler_index ] = ceiling_priority;
}
-RTEMS_INLINE_ROUTINE void _MRSP_Timeout(
- Objects_Id id,
- void *arg
-)
+RTEMS_INLINE_ROUTINE void _MRSP_Timeout( Watchdog_Control *watchdog )
{
- MRSP_Rival *rival = arg;
+ MRSP_Rival *rival = RTEMS_CONTAINER_OF( watchdog, MRSP_Rival, Watchdog );
MRSP_Control *mrsp = rival->resource;
Thread_Control *thread = rival->thread;
ISR_lock_Context lock_context;
- (void) id;
-
_ISR_lock_ISR_disable_and_acquire( &mrsp->Lock, &lock_context );
if ( rival->status == MRSP_WAIT_FOR_OWNERSHIP ) {
@@ -209,6 +204,7 @@ RTEMS_INLINE_ROUTINE MRSP_Status _MRSP_Wait_for_ownership(
bool initial_life_protection;
Per_CPU_Control *cpu_self;
ISR_lock_Context giant_lock_context;
+ ISR_Level level;
rival.thread = executing;
rival.resource = mrsp;
@@ -236,13 +232,11 @@ RTEMS_INLINE_ROUTINE MRSP_Status _MRSP_Wait_for_ownership(
_Thread_Raise_priority( executing, ceiling_priority );
if ( timeout > 0 ) {
- _Watchdog_Initialize(
- &executing->Timer,
- _MRSP_Timeout,
- 0,
- &rival
- );
- _Watchdog_Insert_ticks( &executing->Timer, timeout );
+ _Watchdog_Preinitialize( &rival.Watchdog, cpu_self );
+ _Watchdog_Initialize( &rival.Watchdog, _MRSP_Timeout );
+ _ISR_Disable_without_giant( level );
+ _Watchdog_Per_CPU_insert_relative( &rival.Watchdog, cpu_self, timeout );
+ _ISR_Enable_without_giant( level );
}
initial_life_protection = _Thread_Set_life_protection( true );
@@ -258,7 +252,13 @@ RTEMS_INLINE_ROUTINE MRSP_Status _MRSP_Wait_for_ownership(
_Thread_Set_life_protection( initial_life_protection );
if ( timeout > 0 ) {
- _Watchdog_Remove_ticks( &executing->Timer );
+ _ISR_Disable_without_giant( level );
+ _Watchdog_Per_CPU_remove(
+ &rival.Watchdog,
+ cpu_self,
+ &cpu_self->Watchdog.Header[ PER_CPU_WATCHDOG_RELATIVE ]
+ );
+ _ISR_Enable_without_giant( level );
if ( status == MRSP_TIMEOUT ) {
_MRSP_Restore_priority( executing, initial_priority );
diff --git a/cpukit/score/include/rtems/score/percpu.h b/cpukit/score/include/rtems/score/percpu.h
index 39be1e3367..22017889b3 100644
--- a/cpukit/score/include/rtems/score/percpu.h
+++ b/cpukit/score/include/rtems/score/percpu.h
@@ -23,10 +23,11 @@
#include <rtems/asm.h>
#else
#include <rtems/score/assert.h>
- #include <rtems/score/isrlevel.h>
+ #include <rtems/score/isrlock.h>
#include <rtems/score/smp.h>
#include <rtems/score/smplock.h>
#include <rtems/score/timestamp.h>
+ #include <rtems/score/watchdog.h>
#endif
#ifdef __cplusplus
@@ -41,7 +42,7 @@ extern "C" {
* processor.
*/
#if defined( RTEMS_PROFILING )
- #define PER_CPU_CONTROL_SIZE_LOG2 8
+ #define PER_CPU_CONTROL_SIZE_LOG2 9
#else
#define PER_CPU_CONTROL_SIZE_LOG2 7
#endif
@@ -226,6 +227,32 @@ typedef struct {
} Per_CPU_Stats;
/**
+ * @brief Per-CPU watchdog header index.
+ */
+typedef enum {
+ /**
+ * @brief Index for relative per-CPU watchdog header.
+ *
+ * The reference time point for this header is current ticks value
+ * during insert. Time is measured in clock ticks.
+ */
+ PER_CPU_WATCHDOG_RELATIVE,
+
+ /**
+ * @brief Index for absolute per-CPU watchdog header.
+ *
+ * The reference time point for this header is the POSIX Epoch. Time is
+ * measured in nanoseconds since POSIX Epoch.
+ */
+ PER_CPU_WATCHDOG_ABSOLUTE,
+
+ /**
+ * @brief Count of per-CPU watchdog headers.
+ */
+ PER_CPU_WATCHDOG_COUNT
+} Per_CPU_Watchdog_index;
+
+/**
* @brief Per CPU Core Structure
*
* This structure is used to hold per core state information.
@@ -309,6 +336,28 @@ typedef struct Per_CPU_Control {
/** This is the time of the last context switch on this CPU. */
Timestamp_Control time_of_last_context_switch;
+ /**
+ * @brief Watchdog state for this processor.
+ */
+ struct {
+ /**
+ * @brief Protects all watchdog operations on this processor.
+ */
+ ISR_LOCK_MEMBER( Lock )
+
+ /**
+ * @brief Watchdog ticks on this processor used for relative watchdogs.
+ */
+ uint64_t ticks;
+
+ /**
+ * @brief Header for watchdogs.
+ *
+ * @see Per_CPU_Watchdog_index.
+ */
+ Watchdog_Header Header[ PER_CPU_WATCHDOG_COUNT ];
+ } Watchdog;
+
#if defined( RTEMS_SMP )
/**
* @brief This lock protects some parts of the low-level thread dispatching.
diff --git a/cpukit/score/include/rtems/score/schedulerimpl.h b/cpukit/score/include/rtems/score/schedulerimpl.h
index cadebfd02f..d50c36a7b9 100644
--- a/cpukit/score/include/rtems/score/schedulerimpl.h
+++ b/cpukit/score/include/rtems/score/schedulerimpl.h
@@ -452,19 +452,13 @@ RTEMS_INLINE_ROUTINE void _Scheduler_Release_job(
* scheduler which support standard RTEMS features, this includes
* time-slicing management.
*/
-RTEMS_INLINE_ROUTINE void _Scheduler_Tick( void )
+RTEMS_INLINE_ROUTINE void _Scheduler_Tick( const Per_CPU_Control *cpu )
{
- uint32_t cpu_count = _SMP_Get_processor_count();
- uint32_t cpu_index;
+ const Scheduler_Control *scheduler = _Scheduler_Get_by_CPU( cpu );
+ Thread_Control *executing = cpu->executing;
- for ( cpu_index = 0 ; cpu_index < cpu_count ; ++cpu_index ) {
- const Per_CPU_Control *cpu = _Per_CPU_Get_by_index( cpu_index );
- const Scheduler_Control *scheduler = _Scheduler_Get_by_CPU( cpu );
- Thread_Control *executing = cpu->executing;
-
- if ( scheduler != NULL && executing != NULL ) {
- ( *scheduler->Operations.tick )( scheduler, executing );
- }
+ if ( scheduler != NULL && executing != NULL ) {
+ ( *scheduler->Operations.tick )( scheduler, executing );
}
}
diff --git a/cpukit/score/include/rtems/score/thread.h b/cpukit/score/include/rtems/score/thread.h
index 73776b3ec1..44b706d7ff 100644
--- a/cpukit/score/include/rtems/score/thread.h
+++ b/cpukit/score/include/rtems/score/thread.h
@@ -347,6 +347,15 @@ typedef struct {
} Thread_Wait_information;
/**
+ * @brief Information required to manage a thread timer.
+ */
+typedef struct {
+ ISR_LOCK_MEMBER( Lock )
+ Watchdog_Header *header;
+ Watchdog_Control Watchdog;
+} Thread_Timer_information;
+
+/**
* The following defines the control block used to manage
* each thread proxy.
*
@@ -400,7 +409,7 @@ typedef struct {
/** This field is the blocking information for this proxy. */
Thread_Wait_information Wait;
/** This field is the Watchdog used to manage proxy delays and timeouts. */
- Watchdog_Control Timer;
+ Thread_Timer_information Timer;
#if defined(RTEMS_MULTIPROCESSING)
/** This field is the received response packet in an MP system. */
MP_packet_Prefix *receive_packet;
@@ -728,7 +737,7 @@ struct _Thread_Control {
/** This field is the blocking information for this thread. */
Thread_Wait_information Wait;
/** This field is the Watchdog used to manage thread delays and timeouts. */
- Watchdog_Control Timer;
+ Thread_Timer_information Timer;
#if defined(RTEMS_MULTIPROCESSING)
/** This field is the received response packet in an MP system. */
MP_packet_Prefix *receive_packet;
diff --git a/cpukit/score/include/rtems/score/threadimpl.h b/cpukit/score/include/rtems/score/threadimpl.h
index 1377543118..ec9851dba0 100644
--- a/cpukit/score/include/rtems/score/threadimpl.h
+++ b/cpukit/score/include/rtems/score/threadimpl.h
@@ -33,6 +33,7 @@
#include <rtems/score/threadqimpl.h>
#include <rtems/score/todimpl.h>
#include <rtems/score/freechain.h>
+#include <rtems/score/watchdogimpl.h>
#include <rtems/config.h>
#ifdef __cplusplus
@@ -1472,10 +1473,64 @@ RTEMS_INLINE_ROUTINE void _Thread_Wait_set_timeout_code(
/**
* @brief General purpose thread wait timeout.
*
- * @param[in] id Unused.
- * @param[in] arg The thread.
+ * @param[in] watchdog The thread timer watchdog.
*/
-void _Thread_Timeout( Objects_Id id, void *arg );
+void _Thread_Timeout( Watchdog_Control *watchdog );
+
+RTEMS_INLINE_ROUTINE void _Thread_Timer_insert_relative(
+ Thread_Control *the_thread,
+ Per_CPU_Control *cpu,
+ Watchdog_Service_routine_entry routine,
+ Watchdog_Interval ticks
+)
+{
+ ISR_lock_Context lock_context;
+
+ _ISR_lock_ISR_disable_and_acquire( &the_thread->Timer.Lock, &lock_context );
+
+ the_thread->Timer.header = &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_RELATIVE ];
+ the_thread->Timer.Watchdog.routine = routine;
+ _Watchdog_Per_CPU_insert_relative( &the_thread->Timer.Watchdog, cpu, ticks );
+
+ _ISR_lock_Release_and_ISR_enable( &the_thread->Timer.Lock, &lock_context );
+}
+
+RTEMS_INLINE_ROUTINE void _Thread_Timer_insert_absolute(
+ Thread_Control *the_thread,
+ Per_CPU_Control *cpu,
+ Watchdog_Service_routine_entry routine,
+ uint64_t expire
+)
+{
+ ISR_lock_Context lock_context;
+
+ _ISR_lock_ISR_disable_and_acquire( &the_thread->Timer.Lock, &lock_context );
+
+ the_thread->Timer.header = &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_ABSOLUTE ];
+ the_thread->Timer.Watchdog.routine = routine;
+ _Watchdog_Per_CPU_insert_absolute( &the_thread->Timer.Watchdog, cpu, expire );
+
+ _ISR_lock_Release_and_ISR_enable( &the_thread->Timer.Lock, &lock_context );
+}
+
+RTEMS_INLINE_ROUTINE void _Thread_Timer_remove( Thread_Control *the_thread )
+{
+ ISR_lock_Context lock_context;
+
+ _ISR_lock_ISR_disable_and_acquire( &the_thread->Timer.Lock, &lock_context );
+
+ _Watchdog_Per_CPU_remove(
+ &the_thread->Timer.Watchdog,
+#if defined(RTEMS_SMP)
+ the_thread->Timer.Watchdog.cpu,
+#else
+ _Per_CPU_Get(),
+#endif
+ the_thread->Timer.header
+ );
+
+ _ISR_lock_Release_and_ISR_enable( &the_thread->Timer.Lock, &lock_context );
+}
RTEMS_INLINE_ROUTINE void _Thread_Debug_set_real_processor(
Thread_Control *the_thread,
diff --git a/cpukit/score/include/rtems/score/todimpl.h b/cpukit/score/include/rtems/score/todimpl.h
index b61651cdba..b1f8a6d6b6 100644
--- a/cpukit/score/include/rtems/score/todimpl.h
+++ b/cpukit/score/include/rtems/score/todimpl.h
@@ -132,15 +132,6 @@ extern "C" {
*/
typedef struct {
/**
- * @brief Time of day seconds trigger.
- *
- * This value specifies the nanoseconds since the last time of day second.
- * It is updated and evaluated in _TOD_Tickle_ticks(). It is set in
- * _TOD_Set_with_timestamp().
- */
- uint32_t seconds_trigger;
-
- /**
* @brief Indicates if the time of day is set.
*
* This is true if the application has set the current
@@ -273,14 +264,6 @@ static inline uint32_t _TOD_Seconds_since_epoch( void )
}
/**
- * @brief Increments time of day at each clock tick.
- *
- * This routine increments the ticks field of the current time of
- * day at each clock tick.
- */
-void _TOD_Tickle_ticks( void );
-
-/**
* @brief Gets number of ticks in a second.
*
* This method returns the number of ticks in a second.
diff --git a/cpukit/score/include/rtems/score/watchdog.h b/cpukit/score/include/rtems/score/watchdog.h
index bad7269051..c582dbd1ae 100644
--- a/cpukit/score/include/rtems/score/watchdog.h
+++ b/cpukit/score/include/rtems/score/watchdog.h
@@ -20,7 +20,11 @@
#ifndef _RTEMS_SCORE_WATCHDOG_H
#define _RTEMS_SCORE_WATCHDOG_H
-#include <rtems/score/object.h>
+#include <rtems/score/basedefs.h>
+#include <rtems/score/chain.h>
+#include <rtems/score/rbtree.h>
+
+struct Per_CPU_Control;
#ifdef __cplusplus
extern "C" {
@@ -39,6 +43,8 @@ extern "C" {
*/
/**@{*/
+typedef struct Watchdog_Control Watchdog_Control;
+
/**
* @brief Type is used to specify the length of intervals.
*
@@ -58,10 +64,8 @@ typedef void Watchdog_Service_routine;
*
* This type define a pointer to a watchdog service routine.
*/
-typedef Watchdog_Service_routine ( *Watchdog_Service_routine_entry )(
- Objects_Id,
- void *
- );
+typedef Watchdog_Service_routine
+ ( *Watchdog_Service_routine_entry )( Watchdog_Control * );
/**
* @brief The constant for indefinite wait.
@@ -72,22 +76,20 @@ typedef Watchdog_Service_routine ( *Watchdog_Service_routine_entry )(
#define WATCHDOG_NO_TIMEOUT 0
/**
- * @brief Set of the states which a watchdog timer may be at any given time.
- *
- * This enumerated type is the set of the states in which a
- * watchdog timer may be at any given time.
+ * @brief The watchdog header to manage scheduled watchdogs.
*/
+typedef struct {
+ /**
+ * @brief Red-black tree of scheduled watchdogs sorted by expiration time.
+ */
+ RBTree_Control Watchdogs;
-typedef enum {
- /** This is the state when the watchdog is off all chains */
- WATCHDOG_INACTIVE,
- /** This is the state when the watchdog is off all chains, but we are
- * currently searching for the insertion point.
+ /**
+ * @brief The scheduled watchdog with the earliest expiration time or NULL in
+ * case no watchdog is scheduled.
*/
- WATCHDOG_BEING_INSERTED,
- /** This is the state when the watchdog is on a chain, and allowed to fire. */
- WATCHDOG_ACTIVE
-} Watchdog_States;
+ RBTree_Node *first;
+} Watchdog_Header;
/**
* @brief The control block used to manage each watchdog timer.
@@ -95,30 +97,35 @@ typedef enum {
* The following record defines the control block used
* to manage each watchdog timer.
*/
-typedef struct {
- /** This field is a Chain Node structure and allows this to be placed on
- * chains for set management.
- */
- Chain_Node Node;
- /** This field is the state of the watchdog. */
- Watchdog_States state;
- /** This field is the initially requested interval. */
- Watchdog_Interval initial;
- /** This field is the remaining portion of the interval. */
- Watchdog_Interval delta_interval;
- /** This field is the number of system clock ticks when this was scheduled. */
- Watchdog_Interval start_time;
- /** This field is the number of system clock ticks when this was suspended. */
- Watchdog_Interval stop_time;
- /** This field is the function to invoke. */
- Watchdog_Service_routine_entry routine;
- /** This field is the Id to pass as an argument to the routine. */
- Objects_Id id;
- /** This field is an untyped pointer to user data that is passed to the
- * watchdog handler routine.
+struct Watchdog_Control {
+ /**
+ * @brief Nodes for the watchdog.
*/
- void *user_data;
-} Watchdog_Control;
+ union {
+ /**
+ * @brief this field is a red-black tree node structure and allows this to
+ * be placed on a red-black tree used to manage the scheduled watchdogs.
+ */
+ RBTree_Node RBTree;
+
+ /**
+ * @brief this field is a chain node structure and allows this to be placed
+ * on a chain used to manage pending watchdogs by the timer server.
+ */
+ Chain_Node Chain;
+ } Node;
+
+#if defined(RTEMS_SMP)
+ /** @brief This field references the processor of this watchdog control. */
+ struct Per_CPU_Control *cpu;
+#endif
+
+ /** @brief This field is the function to invoke. */
+ Watchdog_Service_routine_entry routine;
+
+ /** @brief This field is the expiration time point. */
+ uint64_t expire;
+};
/**
* @brief The watchdog ticks counter.
diff --git a/cpukit/score/include/rtems/score/watchdogimpl.h b/cpukit/score/include/rtems/score/watchdogimpl.h
index 49ac2a12b1..2b24cc68e5 100644
--- a/cpukit/score/include/rtems/score/watchdogimpl.h
+++ b/cpukit/score/include/rtems/score/watchdogimpl.h
@@ -21,9 +21,11 @@
#include <rtems/score/watchdog.h>
#include <rtems/score/assert.h>
-#include <rtems/score/chainimpl.h>
#include <rtems/score/isrlock.h>
#include <rtems/score/percpu.h>
+#include <rtems/score/rbtreeimpl.h>
+
+#include <sys/timespec.h>
#ifdef __cplusplus
extern "C" {
@@ -35,241 +37,116 @@ extern "C" {
*/
/**
- * @brief Watchdog initializer for static initialization.
- *
- * @see _Watchdog_Initialize().
- */
-#define WATCHDOG_INITIALIZER( routine, id, user_data ) \
- { \
- { NULL, NULL }, \
- WATCHDOG_INACTIVE, \
- 0, 0, 0, 0, \
- ( routine ), ( id ), ( user_data ) \
- }
-
-/**
- * @brief Iterator item to synchronize concurrent insert, remove and tickle
- * operations.
+ * @brief Watchdog states.
*/
-typedef struct {
+typedef enum {
/**
- * @brief A node for a Watchdog_Header::Iterators chain.
+ * @brief The watchdog is scheduled and a black node in the red-black tree.
*/
- Chain_Node Node;
+ WATCHDOG_SCHEDULED_BLACK,
/**
- * @brief The current delta interval of the new watchdog to insert.
+ * @brief The watchdog is scheduled and a red node in the red-black tree.
*/
- Watchdog_Interval delta_interval;
+ WATCHDOG_SCHEDULED_RED,
/**
- * @brief The current watchdog of the chain on the way to insert the new
- * watchdog.
+ * @brief The watchdog is inactive.
*/
- Chain_Node *current;
-} Watchdog_Iterator;
-
-/**
- * @brief Watchdog header.
- */
-typedef struct {
- /**
- * @brief ISR lock to protect this watchdog chain.
- */
- ISR_LOCK_MEMBER( Lock )
+ WATCHDOG_INACTIVE,
/**
- * @brief The chain of active or transient watchdogs.
- */
- Chain_Control Watchdogs;
-
- /**
- * @brief Currently active iterators.
+ * @brief The watchdog is on a chain of pending watchdogs.
*
- * The iterators are registered in _Watchdog_Insert() and updated in case the
- * watchdog chain changes.
+ * This state is used by the timer server for example.
*/
- Chain_Control Iterators;
-} Watchdog_Header;
+ WATCHDOG_PENDING
+} Watchdog_State;
/**
- * @brief Watchdog chain which is managed at ticks.
+ * @brief Watchdog initializer for static initialization.
*
- * This is the watchdog chain which is managed at ticks.
- */
-extern Watchdog_Header _Watchdog_Ticks_header;
-
-/**
- * @brief Watchdog chain which is managed at second boundaries.
+ * The processor of this watchdog is set to processor with index zero.
*
- * This is the watchdog chain which is managed at second boundaries.
+ * @see _Watchdog_Preinitialize().
*/
-extern Watchdog_Header _Watchdog_Seconds_header;
-
-RTEMS_INLINE_ROUTINE void _Watchdog_Acquire(
- Watchdog_Header *header,
- ISR_lock_Context *lock_context
-)
-{
- _ISR_lock_ISR_disable_and_acquire( &header->Lock, lock_context );
-}
+#if defined(RTEMS_SMP)
+ #define WATCHDOG_INITIALIZER( routine ) \
+ { \
+ { { { NULL, NULL, NULL, WATCHDOG_INACTIVE } } }, \
+ &_Per_CPU_Information[ 0 ].per_cpu, \
+ ( routine ), \
+ 0 \
+ }
+#else
+ #define WATCHDOG_INITIALIZER( routine ) \
+ { \
+ { { { NULL, NULL, NULL, WATCHDOG_INACTIVE } } }, \
+ ( routine ), \
+ 0 \
+ }
+#endif
-RTEMS_INLINE_ROUTINE void _Watchdog_Release(
- Watchdog_Header *header,
- ISR_lock_Context *lock_context
+RTEMS_INLINE_ROUTINE void _Watchdog_Header_initialize(
+ Watchdog_Header *header
)
{
- _ISR_lock_Release_and_ISR_enable( &header->Lock, lock_context );
+ _RBTree_Initialize_empty( &header->Watchdogs );
+ header->first = NULL;
}
-RTEMS_INLINE_ROUTINE void _Watchdog_Flash(
- Watchdog_Header *header,
- ISR_lock_Context *lock_context
+RTEMS_INLINE_ROUTINE void _Watchdog_Header_destroy(
+ Watchdog_Header *header
)
{
- _ISR_lock_Flash( &header->Lock, lock_context );
+ /* Do nothing */
+ (void) header;
}
/**
- * @brief Initialize the watchdog handler.
- *
- * This routine initializes the watchdog handler. The watchdog
- * synchronization flag is initialized and the watchdog chains are
- * initialized and emptied.
- */
-void _Watchdog_Handler_initialization( void );
-
-/**
* @brief Performs a watchdog tick.
*
* @param cpu The processor for this watchdog tick.
*/
-void _Watchdog_Tick( Per_CPU_Control *cpu );
-
-/**
- * @brief Removes @a the_watchdog from the watchdog chain.
- *
- * This routine removes @a the_watchdog from the watchdog chain on which
- * it resides and returns the state @a the_watchdog timer was in.
- *
- * @param[in] header The watchdog chain.
- * @param[in] the_watchdog will be removed
- * @retval the state in which @a the_watchdog was in when removed
- */
-Watchdog_States _Watchdog_Remove (
- Watchdog_Header *header,
- Watchdog_Control *the_watchdog
-);
-
-/**
- * @brief Adjusts the header watchdog chain in the backward direction for
- * units ticks.
- *
- * @param[in] header The watchdog chain.
- * @param[in] units The units of ticks to adjust.
- */
-void _Watchdog_Adjust_backward(
- Watchdog_Header *header,
- Watchdog_Interval units
-);
-
-/**
- * @brief Adjusts the watchdogs in backward direction in a locked context.
- *
- * The caller must be the owner of the watchdog lock and will be the owner
- * after the call.
- *
- * @param[in] header The watchdog header.
- * @param[in] units The units of ticks to adjust.
- *
- * @see _Watchdog_Adjust_forward().
- */
-void _Watchdog_Adjust_backward_locked(
- Watchdog_Header *header,
- Watchdog_Interval units
-);
+void _Watchdog_Tick( struct Per_CPU_Control *cpu );
-/**
- * @brief Adjusts the header watchdog chain in the forward direction for units
- * ticks.
- *
- * This may lead to several _Watchdog_Tickle() invocations.
- *
- * @param[in] header The watchdog chain.
- * @param[in] units The units of ticks to adjust.
- */
-void _Watchdog_Adjust_forward(
- Watchdog_Header *header,
- Watchdog_Interval units
-);
+RTEMS_INLINE_ROUTINE Watchdog_State _Watchdog_Get_state(
+ const Watchdog_Control *the_watchdog
+)
+{
+ return RB_COLOR( &the_watchdog->Node.RBTree, Node );
+}
-/**
- * @brief Adjusts the watchdogs in forward direction in a locked context.
- *
- * The caller must be the owner of the watchdog lock and will be the owner
- * after the call. This function may release and acquire the watchdog lock
- * internally.
- *
- * @param[in] header The watchdog header.
- * @param[in] units The units of ticks to adjust.
- * @param[in] lock_context The lock context.
- *
- * @see _Watchdog_Adjust_forward().
- */
-void _Watchdog_Adjust_forward_locked(
- Watchdog_Header *header,
- Watchdog_Interval units,
- ISR_lock_Context *lock_context
-);
+RTEMS_INLINE_ROUTINE void _Watchdog_Set_state(
+ Watchdog_Control *the_watchdog,
+ Watchdog_State state
+)
+{
+ RB_COLOR( &the_watchdog->Node.RBTree, Node ) = state;
+}
-/**
- * @brief Inserts @a the_watchdog into the @a header watchdog chain
- * for a time of @a units.
- *
- * This routine inserts @a the_watchdog into the @a header watchdog chain
- * for a time of @a units.
- * Update the delta interval counters.
- *
- * @param[in] header is @a the_watchdog list to insert @a the_watchdog on
- * @param[in] the_watchdog is the watchdog to insert
- */
-void _Watchdog_Insert (
- Watchdog_Header *header,
- Watchdog_Control *the_watchdog
-);
+RTEMS_INLINE_ROUTINE Per_CPU_Control *_Watchdog_Get_CPU(
+ const Watchdog_Control *the_watchdog
+)
+{
+#if defined(RTEMS_SMP)
+ return the_watchdog->cpu;
+#else
+ return _Per_CPU_Get_by_index( 0 );
+#endif
+}
-/**
- * @brief Inserts the watchdog in a locked context.
- *
- * The caller must be the owner of the watchdog lock and will be the owner
- * after the call. This function may release and acquire the watchdog lock
- * internally.
- *
- * @param[in] header The watchdog header.
- * @param[in] the_watchdog The watchdog.
- * @param[in] lock_context The lock context.
- *
- * @see _Watchdog_Insert().
- */
-void _Watchdog_Insert_locked(
- Watchdog_Header *header,
+RTEMS_INLINE_ROUTINE void _Watchdog_Set_CPU(
Watchdog_Control *the_watchdog,
- ISR_lock_Context *lock_context
-);
-
-/**
- * @brief This routine is invoked at appropriate intervals to update
- * the @a header watchdog chain.
- *
- * This routine is invoked at appropriate intervals to update
- * the @a header watchdog chain.
- * This routine decrements the delta counter in response to a tick.
- *
- * @param[in] header is the watchdog chain to tickle
- */
-void _Watchdog_Tickle (
- Watchdog_Header *header
-);
+ Per_CPU_Control *cpu
+)
+{
+#if defined(RTEMS_SMP)
+ the_watchdog->cpu = cpu;
+#else
+ (void) cpu;
+#endif
+}
/**
* @brief Pre-initializes a watchdog.
@@ -280,228 +157,284 @@ void _Watchdog_Tickle (
* @param[in] the_watchdog The uninitialized watchdog.
*/
RTEMS_INLINE_ROUTINE void _Watchdog_Preinitialize(
- Watchdog_Control *the_watchdog
+ Watchdog_Control *the_watchdog,
+ Per_CPU_Control *cpu
)
{
- the_watchdog->state = WATCHDOG_INACTIVE;
+ _Watchdog_Set_CPU( the_watchdog, cpu );
+ _Watchdog_Set_state( the_watchdog, WATCHDOG_INACTIVE );
+
#if defined(RTEMS_DEBUG)
the_watchdog->routine = NULL;
- the_watchdog->id = 0;
- the_watchdog->user_data = NULL;
+ the_watchdog->expire = 0;
#endif
}
/**
- * This routine initializes the specified watchdog. The watchdog is
- * made inactive, the watchdog id and handler routine are set to the
- * specified values.
+ * @brief Initializes a watchdog with a new service routine.
+ *
+ * The watchdog must be inactive.
*/
-
RTEMS_INLINE_ROUTINE void _Watchdog_Initialize(
Watchdog_Control *the_watchdog,
- Watchdog_Service_routine_entry routine,
- Objects_Id id,
- void *user_data
+ Watchdog_Service_routine_entry routine
)
{
- _Assert( the_watchdog->state == WATCHDOG_INACTIVE );
- the_watchdog->routine = routine;
- the_watchdog->id = id;
- the_watchdog->user_data = user_data;
+ _Assert( _Watchdog_Get_state( the_watchdog ) == WATCHDOG_INACTIVE );
+ the_watchdog->routine = routine;
}
+void _Watchdog_Do_tickle(
+ Watchdog_Header *header,
+ uint64_t now,
+#if defined(RTEMS_SMP)
+ ISR_lock_Control *lock,
+#endif
+ ISR_lock_Context *lock_context
+);
+
+#if defined(RTEMS_SMP)
+ #define _Watchdog_Tickle( header, now, lock, lock_context ) \
+ _Watchdog_Do_tickle( header, now, lock, lock_context )
+#else
+ #define _Watchdog_Tickle( header, now, lock, lock_context ) \
+ _Watchdog_Do_tickle( header, now, lock_context )
+#endif
+
/**
- * This routine returns true if the watchdog timer is in the ACTIVE
- * state, and false otherwise.
+ * @brief Inserts a watchdog into the set of scheduled watchdogs according to
+ * the specified expiration time.
+ *
+ * The watchdog must be inactive.
*/
+void _Watchdog_Insert(
+ Watchdog_Header *header,
+ Watchdog_Control *the_watchdog,
+ uint64_t expire
+);
-RTEMS_INLINE_ROUTINE bool _Watchdog_Is_active(
+/**
+ * @brief In case the watchdog is scheduled, then it is removed from the set of
+ * scheduled watchdogs.
+ *
+ * The watchdog must be initialized before this call.
+ */
+void _Watchdog_Remove(
+ Watchdog_Header *header,
Watchdog_Control *the_watchdog
-)
-{
-
- return ( the_watchdog->state == WATCHDOG_ACTIVE );
-
-}
+);
/**
- * This routine activates THE_WATCHDOG timer which is already
- * on a watchdog chain.
+ * @brief In case the watchdog is scheduled, then it is removed from the set of
+ * scheduled watchdogs.
+ *
+ * The watchdog must be initialized before this call.
+ *
+ * @retval 0 The now time is greater than or equal to the expiration time of
+ * the watchdog.
+ * @retval other The difference of the now and expiration time.
*/
-
-RTEMS_INLINE_ROUTINE void _Watchdog_Activate(
- Watchdog_Control *the_watchdog
+RTEMS_INLINE_ROUTINE uint64_t _Watchdog_Cancel(
+ Watchdog_Header *header,
+ Watchdog_Control *the_watchdog,
+ uint64_t now
)
{
+ uint64_t expire;
+ uint64_t remaining;
- the_watchdog->state = WATCHDOG_ACTIVE;
+ expire = the_watchdog->expire;
-}
-
-/**
- * This routine is invoked at each clock tick to update the ticks
- * watchdog chain.
- */
-
-RTEMS_INLINE_ROUTINE void _Watchdog_Tickle_ticks( void )
-{
+ if ( now < expire ) {
+ remaining = expire - now;
+ } else {
+ remaining = 0;
+ }
- _Watchdog_Tickle( &_Watchdog_Ticks_header );
+ _Watchdog_Remove( header, the_watchdog );
+ return remaining;
}
-/**
- * This routine is invoked at each clock tick to update the seconds
- * watchdog chain.
- */
-
-RTEMS_INLINE_ROUTINE void _Watchdog_Tickle_seconds( void )
+RTEMS_INLINE_ROUTINE bool _Watchdog_Is_scheduled(
+ const Watchdog_Control *the_watchdog
+)
{
-
- _Watchdog_Tickle( &_Watchdog_Seconds_header );
-
+ return _Watchdog_Get_state( the_watchdog ) < WATCHDOG_INACTIVE;
}
-/**
- * This routine inserts THE_WATCHDOG into the ticks watchdog chain
- * for a time of UNITS ticks. The INSERT_MODE indicates whether
- * THE_WATCHDOG is to be activated automatically or later, explicitly
- * by the caller.
- */
-
-RTEMS_INLINE_ROUTINE void _Watchdog_Insert_ticks(
- Watchdog_Control *the_watchdog,
- Watchdog_Interval units
+RTEMS_INLINE_ROUTINE void _Watchdog_Next_first(
+ Watchdog_Header *header,
+ Watchdog_Control *the_watchdog
)
{
+ RBTree_Node *node = _RBTree_Right( &the_watchdog->Node.RBTree );
- the_watchdog->initial = units;
+ if ( node != NULL ) {
+ RBTree_Node *left;
- _Watchdog_Insert( &_Watchdog_Ticks_header, the_watchdog );
+ while ( ( left = _RBTree_Left( node ) ) != NULL ) {
+ node = left;
+ }
+ header->first = node;
+ } else {
+ header->first = _RBTree_Parent( &the_watchdog->Node.RBTree );
+ }
}
/**
- * This routine inserts THE_WATCHDOG into the seconds watchdog chain
- * for a time of UNITS seconds. The INSERT_MODE indicates whether
- * THE_WATCHDOG is to be activated automatically or later, explicitly
- * by the caller.
+ * @brief The bits necessary to store 1000000000 nanoseconds.
+ *
+ * The expiration time is an unsigned 64-bit integer. To store absolute
+ * timeouts we use 30 bits (2**30 == 1073741824) for the nanoseconds and 34
+ * bits for the seconds since UNIX Epoch. This leads to a year 2514 problem.
*/
+#define WATCHDOG_BITS_FOR_1E9_NANOSECONDS 30
-RTEMS_INLINE_ROUTINE void _Watchdog_Insert_seconds(
- Watchdog_Control *the_watchdog,
- Watchdog_Interval units
+RTEMS_INLINE_ROUTINE uint64_t _Watchdog_Ticks_from_seconds(
+ uint32_t seconds
)
{
+ uint64_t ticks = seconds;
- the_watchdog->initial = units;
-
- _Watchdog_Insert( &_Watchdog_Seconds_header, the_watchdog );
+ ticks <<= WATCHDOG_BITS_FOR_1E9_NANOSECONDS;
+ return ticks;
}
-RTEMS_INLINE_ROUTINE Watchdog_States _Watchdog_Remove_ticks(
- Watchdog_Control *the_watchdog
+RTEMS_INLINE_ROUTINE uint64_t _Watchdog_Ticks_from_timespec(
+ const struct timespec *ts
)
{
- return _Watchdog_Remove( &_Watchdog_Ticks_header, the_watchdog );
+ /*
+ * The seconds are in time_t which is a signed integer. Thus this cast is
+ * subject to the year 2038 problem in case time_t is a 32-bit integer.
+ */
+ uint64_t ticks = (uint64_t) ts->tv_sec;
+
+ _Assert( ticks < 0x400000000 );
+ _Assert( ts->tv_nsec >= 0 );
+ _Assert( ts->tv_nsec < 1000000000 );
+
+ ticks <<= WATCHDOG_BITS_FOR_1E9_NANOSECONDS;
+ ticks |= ts->tv_nsec;
+
+ return ticks;
}
-RTEMS_INLINE_ROUTINE Watchdog_States _Watchdog_Remove_seconds(
- Watchdog_Control *the_watchdog
+RTEMS_INLINE_ROUTINE void _Watchdog_Per_CPU_acquire_critical(
+ Per_CPU_Control *cpu,
+ ISR_lock_Context *lock_context
)
{
- return _Watchdog_Remove( &_Watchdog_Seconds_header, the_watchdog );
+ _ISR_lock_Acquire( &cpu->Watchdog.Lock, lock_context );
}
-/**
- * This routine resets THE_WATCHDOG timer to its state at INSERT
- * time. This routine is valid only on interval watchdog timers
- * and is used to make an interval watchdog timer fire "every" so
- * many ticks.
- */
-
-RTEMS_INLINE_ROUTINE void _Watchdog_Reset_ticks(
- Watchdog_Control *the_watchdog
+RTEMS_INLINE_ROUTINE void _Watchdog_Per_CPU_release_critical(
+ Per_CPU_Control *cpu,
+ ISR_lock_Context *lock_context
)
{
-
- _Watchdog_Remove_ticks( the_watchdog );
-
- _Watchdog_Insert( &_Watchdog_Ticks_header, the_watchdog );
-
+ _ISR_lock_Release( &cpu->Watchdog.Lock, lock_context );
}
-/**
- * This routine returns a pointer to the watchdog timer following
- * THE_WATCHDOG on the watchdog chain.
- */
-
-RTEMS_INLINE_ROUTINE Watchdog_Control *_Watchdog_Next(
- Watchdog_Control *the_watchdog
+RTEMS_INLINE_ROUTINE void _Watchdog_Per_CPU_insert_relative(
+ Watchdog_Control *the_watchdog,
+ Per_CPU_Control *cpu,
+ uint32_t ticks
)
{
+ ISR_lock_Context lock_context;
- return ( (Watchdog_Control *) the_watchdog->Node.next );
+ _Watchdog_Set_CPU( the_watchdog, cpu );
+ _Watchdog_Per_CPU_acquire_critical( cpu, &lock_context );
+ _Watchdog_Insert(
+ &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_RELATIVE ],
+ the_watchdog,
+ cpu->Watchdog.ticks + ticks
+ );
+ _Watchdog_Per_CPU_release_critical( cpu, &lock_context );
}
-/**
- * This routine returns a pointer to the watchdog timer preceding
- * THE_WATCHDOG on the watchdog chain.
- */
-
-RTEMS_INLINE_ROUTINE Watchdog_Control *_Watchdog_Previous(
- Watchdog_Control *the_watchdog
+RTEMS_INLINE_ROUTINE void _Watchdog_Per_CPU_insert_absolute(
+ Watchdog_Control *the_watchdog,
+ Per_CPU_Control *cpu,
+ uint64_t expire
)
{
+ ISR_lock_Context lock_context;
- return ( (Watchdog_Control *) the_watchdog->Node.previous );
+ _Watchdog_Set_CPU( the_watchdog, cpu );
+ _Watchdog_Per_CPU_acquire_critical( cpu, &lock_context );
+ _Watchdog_Insert(
+ &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_ABSOLUTE ],
+ the_watchdog,
+ expire
+ );
+ _Watchdog_Per_CPU_release_critical( cpu, &lock_context );
}
-/**
- * This routine returns a pointer to the first watchdog timer
- * on the watchdog chain HEADER.
- */
-
-RTEMS_INLINE_ROUTINE Watchdog_Control *_Watchdog_First(
- Watchdog_Header *header
+RTEMS_INLINE_ROUTINE void _Watchdog_Per_CPU_remove(
+ Watchdog_Control *the_watchdog,
+ Per_CPU_Control *cpu,
+ Watchdog_Header *header
)
{
-
- return ( (Watchdog_Control *) _Chain_First( &header->Watchdogs ) );
-
+ ISR_lock_Context lock_context;
+
+ _Watchdog_Per_CPU_acquire_critical( cpu, &lock_context );
+ _Watchdog_Remove(
+ header,
+ the_watchdog
+ );
+ _Watchdog_Per_CPU_release_critical( cpu, &lock_context );
}
-/**
- * This routine returns a pointer to the last watchdog timer
- * on the watchdog chain HEADER.
- */
-
-RTEMS_INLINE_ROUTINE Watchdog_Control *_Watchdog_Last(
- Watchdog_Header *header
+RTEMS_INLINE_ROUTINE void _Watchdog_Per_CPU_remove_relative(
+ Watchdog_Control *the_watchdog
)
{
-
- return ( (Watchdog_Control *) _Chain_Last( &header->Watchdogs ) );
-
+ Per_CPU_Control *cpu;
+
+ cpu = _Watchdog_Get_CPU( the_watchdog );
+ _Watchdog_Per_CPU_remove(
+ the_watchdog,
+ cpu,
+ &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_RELATIVE ]
+ );
}
-RTEMS_INLINE_ROUTINE bool _Watchdog_Is_empty(
- const Watchdog_Header *header
+RTEMS_INLINE_ROUTINE void _Watchdog_Per_CPU_remove_absolute(
+ Watchdog_Control *the_watchdog
)
{
- return _Chain_Is_empty( &header->Watchdogs );
+ Per_CPU_Control *cpu;
+
+ cpu = _Watchdog_Get_CPU( the_watchdog );
+ _Watchdog_Per_CPU_remove(
+ the_watchdog,
+ cpu,
+ &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_ABSOLUTE ]
+ );
}
-RTEMS_INLINE_ROUTINE void _Watchdog_Header_initialize(
- Watchdog_Header *header
+RTEMS_INLINE_ROUTINE void _Watchdog_Per_CPU_tickle_absolute(
+ Per_CPU_Control *cpu,
+ uint64_t now
)
{
- _ISR_lock_Initialize( &header->Lock, "Watchdog" );
- _Chain_Initialize_empty( &header->Watchdogs );
- _Chain_Initialize_empty( &header->Iterators );
+ ISR_lock_Context lock_context;
+
+ _ISR_lock_ISR_disable_and_acquire( &cpu->Watchdog.Lock, &lock_context );
+ _Watchdog_Tickle(
+ &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_ABSOLUTE ],
+ now,
+ &cpu->Watchdog.Lock,
+ &lock_context
+ );
}
/** @} */
diff --git a/cpukit/score/src/condition.c b/cpukit/score/src/condition.c
index 22c2a9b97c..420681955a 100644
--- a/cpukit/score/src/condition.c
+++ b/cpukit/score/src/condition.c
@@ -282,7 +282,7 @@ static int _Condition_Wake( struct _Condition_Control *_condition, int count )
next = _Chain_Next( node );
thread = THREAD_CHAIN_NODE_TO_THREAD( node );
- _Watchdog_Remove_ticks( &thread->Timer );
+ _Thread_Timer_remove( thread );
_Thread_Unblock( thread );
node = next;
diff --git a/cpukit/score/src/coretodset.c b/cpukit/score/src/coretodset.c
index 3230179414..b2efc07115 100644
--- a/cpukit/score/src/coretodset.c
+++ b/cpukit/score/src/coretodset.c
@@ -26,30 +26,26 @@ void _TOD_Set_with_timestamp(
const Timestamp_Control *tod_as_timestamp
)
{
- struct timespec ts;
- uint32_t nanoseconds;
- Watchdog_Interval seconds_next;
- Watchdog_Interval seconds_now;
- Watchdog_Header *header;
+ struct timespec tod_as_timespec;
+ uint64_t tod_as_ticks;
+ uint32_t cpu_count;
+ uint32_t cpu_index;
- _Timestamp_To_timespec( tod_as_timestamp, &ts );
- nanoseconds = ts.tv_nsec;
- seconds_next = ts.tv_sec;
+ _Timestamp_To_timespec( tod_as_timestamp, &tod_as_timespec );
_Thread_Disable_dispatch();
- seconds_now = _TOD_Seconds_since_epoch();
+ _Timecounter_Set_clock( &tod_as_timespec );
- _Timecounter_Set_clock( &ts );
+ tod_as_ticks = _Watchdog_Ticks_from_timespec( &tod_as_timespec );
+ cpu_count = _SMP_Get_processor_count();
- header = &_Watchdog_Seconds_header;
+ for ( cpu_index = 0 ; cpu_index < cpu_count ; ++cpu_index ) {
+ Per_CPU_Control *cpu = _Per_CPU_Get_by_index( cpu_index );
- if ( seconds_next < seconds_now )
- _Watchdog_Adjust_backward( header, seconds_now - seconds_next );
- else
- _Watchdog_Adjust_forward( header, seconds_next - seconds_now );
+ _Watchdog_Per_CPU_tickle_absolute( cpu, tod_as_ticks );
+ }
- _TOD.seconds_trigger = nanoseconds;
_TOD.is_set = true;
_Thread_Enable_dispatch();
diff --git a/cpukit/score/src/coretodtickle.c b/cpukit/score/src/coretodtickle.c
deleted file mode 100644
index 3d7c71e1c1..0000000000
--- a/cpukit/score/src/coretodtickle.c
+++ /dev/null
@@ -1,36 +0,0 @@
-/**
- * @file
- *
- * @brief Increments time of day at each clock tick
- *
- * @ingroup ScoreTOD
- */
-
-/* COPYRIGHT (c) 1989-2014.
- * On-Line Applications Research Corporation (OAR).
- *
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
- */
-
-#if HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <rtems/score/todimpl.h>
-#include <rtems/score/watchdogimpl.h>
-#include <rtems/config.h>
-
-void _TOD_Tickle_ticks( void )
-{
- /* Update the counter of ticks since boot */
- _Watchdog_Ticks_since_boot += 1;
-
- _TOD.seconds_trigger += rtems_configuration_get_nanoseconds_per_tick();
- if ( _TOD.seconds_trigger >= 1000000000UL ) {
- _TOD.seconds_trigger -= 1000000000UL;
- _Watchdog_Tickle_seconds();
- }
-}
-
diff --git a/cpukit/score/src/kern_tc.c b/cpukit/score/src/kern_tc.c
index e56c292ea3..316a16f05b 100644
--- a/cpukit/score/src/kern_tc.c
+++ b/cpukit/score/src/kern_tc.c
@@ -1971,6 +1971,7 @@ tc_ticktock(int cnt)
return;
count = 0;
#else /* __rtems__ */
+#include <rtems/score/smp.h>
void
_Timecounter_Tick(void)
{
@@ -2021,7 +2022,7 @@ _Timecounter_Tick_simple(uint32_t delta, uint32_t offset,
_Timecounter_Release(lock_context);
- _Watchdog_Tick(_Per_CPU_Get());
+ _Watchdog_Tick(_Per_CPU_Get_snapshot());
}
#endif /* __rtems__ */
diff --git a/cpukit/score/src/smp.c b/cpukit/score/src/smp.c
index 9d9507d1b9..85256b044c 100644
--- a/cpukit/score/src/smp.c
+++ b/cpukit/score/src/smp.c
@@ -87,6 +87,7 @@ void _SMP_Handler_initialize( void )
for ( cpu_index = 0 ; cpu_index < cpu_max; ++cpu_index ) {
Per_CPU_Control *cpu = _Per_CPU_Get_by_index( cpu_index );
+ _ISR_lock_Initialize( &cpu->Watchdog.Lock, "Watchdog" );
_SMP_ticket_lock_Initialize( &cpu->Lock );
_SMP_lock_Stats_initialize( &cpu->Lock_stats, "Per-CPU" );
}
diff --git a/cpukit/score/src/threadinitialize.c b/cpukit/score/src/threadinitialize.c
index a49406f160..0b5fd3a125 100644
--- a/cpukit/score/src/threadinitialize.c
+++ b/cpukit/score/src/threadinitialize.c
@@ -160,6 +160,10 @@ bool _Thread_Initialize(
the_thread->Start.budget_algorithm = budget_algorithm;
the_thread->Start.budget_callout = budget_callout;
+ _ISR_lock_Initialize( &the_thread->Timer.Lock, "Thread Timer" );
+ the_thread->Timer.header = &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_RELATIVE ];
+ _Watchdog_Preinitialize( &the_thread->Timer.Watchdog, cpu );
+
switch ( budget_algorithm ) {
case THREAD_CPU_BUDGET_ALGORITHM_NONE:
case THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE:
diff --git a/cpukit/score/src/threadqenqueue.c b/cpukit/score/src/threadqenqueue.c
index 960783c74c..07618fc800 100644
--- a/cpukit/score/src/threadqenqueue.c
+++ b/cpukit/score/src/threadqenqueue.c
@@ -35,7 +35,7 @@
static void _Thread_queue_Unblock( Thread_Control *the_thread )
{
- _Watchdog_Remove_ticks( &the_thread->Timer );
+ _Thread_Timer_remove( the_thread );
_Thread_Unblock( the_thread );
#if defined(RTEMS_MULTIPROCESSING)
@@ -84,8 +84,12 @@ void _Thread_queue_Enqueue_critical(
*/
if ( timeout != WATCHDOG_NO_TIMEOUT ) {
_Thread_Wait_set_timeout_code( the_thread, timeout_code );
- _Watchdog_Initialize( &the_thread->Timer, _Thread_Timeout, 0, the_thread );
- _Watchdog_Insert_ticks( &the_thread->Timer, timeout );
+ _Thread_Timer_insert_relative(
+ the_thread,
+ cpu_self,
+ _Thread_Timeout,
+ timeout
+ );
}
success = _Thread_Wait_flags_try_change(
diff --git a/cpukit/score/src/threadrestart.c b/cpukit/score/src/threadrestart.c
index 03b1fba8ff..d366f97a0f 100644
--- a/cpukit/score/src/threadrestart.c
+++ b/cpukit/score/src/threadrestart.c
@@ -84,7 +84,7 @@ static void _Thread_Make_zombie( Thread_Control *the_thread )
_Thread_Set_state( the_thread, STATES_ZOMBIE );
_Thread_queue_Extract_with_proxy( the_thread );
- _Watchdog_Remove_ticks( &the_thread->Timer );
+ _Thread_Timer_remove( the_thread );
_ISR_lock_ISR_disable_and_acquire( &zombies->Lock, &lock_context );
_Chain_Append_unprotected( &zombies->Chain, &the_thread->Object.Node );
@@ -191,7 +191,9 @@ static void _Thread_Start_life_change_for_executing(
Thread_Control *executing
)
{
- _Assert( executing->Timer.state == WATCHDOG_INACTIVE );
+ _Assert(
+ _Watchdog_Get_state( &executing->Timer.Watchdog ) == WATCHDOG_INACTIVE
+ );
_Assert(
executing->current_state == STATES_READY
|| executing->current_state == STATES_SUSPENDED
@@ -246,7 +248,9 @@ void _Thread_Life_action_handler(
/* Someone deleted us in the mean-time */
_Thread_Start_life_change_for_executing( executing );
} else {
- _Assert( executing->Timer.state == WATCHDOG_INACTIVE );
+ _Assert(
+ _Watchdog_Get_state( &executing->Timer.Watchdog ) == WATCHDOG_INACTIVE
+ );
_Assert(
executing->current_state == STATES_READY
|| executing->current_state == STATES_SUSPENDED
@@ -274,7 +278,7 @@ static void _Thread_Start_life_change(
_Thread_Set_state( the_thread, STATES_RESTARTING );
_Thread_queue_Extract_with_proxy( the_thread );
- _Watchdog_Remove_ticks( &the_thread->Timer );
+ _Thread_Timer_remove( the_thread );
_Thread_Change_priority(
the_thread,
priority,
diff --git a/cpukit/score/src/threadtimeout.c b/cpukit/score/src/threadtimeout.c
index 8ecaebde06..59f6bd97f0 100644
--- a/cpukit/score/src/threadtimeout.c
+++ b/cpukit/score/src/threadtimeout.c
@@ -33,7 +33,7 @@ static void _Thread_Do_timeout( Thread_Control *the_thread )
_Thread_Lock_restore_default( the_thread );
}
-void _Thread_Timeout( Objects_Id id, void *arg )
+void _Thread_Timeout( Watchdog_Control *watchdog )
{
Thread_Control *the_thread;
void *thread_lock;
@@ -41,7 +41,7 @@ void _Thread_Timeout( Objects_Id id, void *arg )
Thread_Wait_flags wait_flags;
bool unblock;
- the_thread = arg;
+ the_thread = RTEMS_CONTAINER_OF( watchdog, Thread_Control, Timer.Watchdog );
thread_lock = _Thread_Lock_acquire( the_thread, &lock_context );
wait_flags = _Thread_Wait_flags_get( the_thread );
diff --git a/cpukit/score/src/watchdog.c b/cpukit/score/src/watchdog.c
deleted file mode 100644
index 8d172fb8f9..0000000000
--- a/cpukit/score/src/watchdog.c
+++ /dev/null
@@ -1,36 +0,0 @@
-/**
- * @file
- *
- * @brief Watchdog Handler Initialization
- * @ingroup ScoreWatchdog
- */
-
-/*
- * Watchdog Handler
- *
- *
- * COPYRIGHT (c) 1989-1999.
- * On-Line Applications Research Corporation (OAR).
- *
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
- */
-
-#if HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <rtems/score/watchdogimpl.h>
-
-Watchdog_Header _Watchdog_Ticks_header;
-
-Watchdog_Header _Watchdog_Seconds_header;
-
-void _Watchdog_Handler_initialization( void )
-{
- _Watchdog_Ticks_since_boot = 0;
-
- _Watchdog_Header_initialize( &_Watchdog_Ticks_header );
- _Watchdog_Header_initialize( &_Watchdog_Seconds_header );
-}
diff --git a/cpukit/score/src/watchdogadjust.c b/cpukit/score/src/watchdogadjust.c
deleted file mode 100644
index 32b5f7990e..0000000000
--- a/cpukit/score/src/watchdogadjust.c
+++ /dev/null
@@ -1,80 +0,0 @@
-/**
- * @file
- *
- * @brief Watchdog Adjust
- * @ingroup ScoreWatchdog
- */
-
-/*
- * COPYRIGHT (c) 1989-1999.
- * On-Line Applications Research Corporation (OAR).
- *
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
- */
-
-#if HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <rtems/score/watchdogimpl.h>
-
-void _Watchdog_Adjust_backward_locked(
- Watchdog_Header *header,
- Watchdog_Interval units
-)
-{
- if ( !_Watchdog_Is_empty( header ) ) {
- _Watchdog_First( header )->delta_interval += units;
- }
-}
-
-void _Watchdog_Adjust_backward(
- Watchdog_Header *header,
- Watchdog_Interval units
-)
-{
- ISR_lock_Context lock_context;
-
- _Watchdog_Acquire( header, &lock_context );
- _Watchdog_Adjust_backward_locked( header, units );
- _Watchdog_Release( header, &lock_context );
-}
-
-void _Watchdog_Adjust_forward_locked(
- Watchdog_Header *header,
- Watchdog_Interval units,
- ISR_lock_Context *lock_context
-)
-{
- while ( !_Watchdog_Is_empty( header ) && units > 0 ) {
- Watchdog_Control *first = _Watchdog_First( header );
-
- if ( units < first->delta_interval ) {
- first->delta_interval -= units;
- break;
- } else {
- units -= first->delta_interval;
- first->delta_interval = 1;
-
- _Watchdog_Release( header, lock_context );
-
- _Watchdog_Tickle( header );
-
- _Watchdog_Acquire( header, lock_context );
- }
- }
-}
-
-void _Watchdog_Adjust_forward(
- Watchdog_Header *header,
- Watchdog_Interval units
-)
-{
- ISR_lock_Context lock_context;
-
- _Watchdog_Acquire( header, &lock_context );
- _Watchdog_Adjust_forward_locked( header, units, &lock_context );
- _Watchdog_Release( header, &lock_context );
-}
diff --git a/cpukit/score/src/watchdoginsert.c b/cpukit/score/src/watchdoginsert.c
index db15f55b0d..22fc7a5f76 100644
--- a/cpukit/score/src/watchdoginsert.c
+++ b/cpukit/score/src/watchdoginsert.c
@@ -1,17 +1,22 @@
/**
- * @file
+ * @file
*
* @brief Watchdog Insert
* @ingroup ScoreWatchdog
*/
-
+
/*
- * COPYRIGHT (c) 1989-1999.
- * On-Line Applications Research Corporation (OAR).
+ * Copyright (c) 2016 embedded brains GmbH. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Dornierstr. 4
+ * 82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
*
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
*/
#if HAVE_CONFIG_H
@@ -20,106 +25,41 @@
#include <rtems/score/watchdogimpl.h>
-static void _Watchdog_Insert_fixup(
- Watchdog_Header *header,
- Watchdog_Control *the_watchdog,
- Watchdog_Interval delta,
- Watchdog_Control *next_watchdog,
- Watchdog_Interval delta_next
-)
-{
- const Chain_Node *iterator_tail;
- Chain_Node *iterator_node;
-
- next_watchdog->delta_interval = delta_next - delta;
-
- iterator_node = _Chain_First( &header->Iterators );
- iterator_tail = _Chain_Immutable_tail( &header->Iterators );
-
- while ( iterator_node != iterator_tail ) {
- Watchdog_Iterator *iterator;
-
- iterator = (Watchdog_Iterator *) iterator_node;
-
- if ( iterator->current == &next_watchdog->Node ) {
- iterator->current = &the_watchdog->Node;
- }
-
- iterator_node = _Chain_Next( iterator_node );
- }
-}
-
-void _Watchdog_Insert_locked(
+void _Watchdog_Insert(
Watchdog_Header *header,
Watchdog_Control *the_watchdog,
- ISR_lock_Context *lock_context
+ uint64_t expire
)
{
- if ( the_watchdog->state == WATCHDOG_INACTIVE ) {
- Watchdog_Iterator iterator;
- Chain_Node *current;
- Chain_Node *next;
- Watchdog_Interval delta;
-
- the_watchdog->state = WATCHDOG_BEING_INSERTED;
-
- _Chain_Append_unprotected( &header->Iterators, &iterator.Node );
-
- delta = the_watchdog->initial;
- current = _Chain_Head( &header->Watchdogs );
+ RBTree_Node **link;
+ RBTree_Node *parent;
+ RBTree_Node *old_first;
+ RBTree_Node *new_first;
- while (
- ( next = _Chain_Next( current ) ) != _Chain_Tail( &header->Watchdogs )
- ) {
- Watchdog_Control *next_watchdog;
- Watchdog_Interval delta_next;
+ _Assert( _Watchdog_Get_state( the_watchdog ) == WATCHDOG_INACTIVE );
- next_watchdog = (Watchdog_Control *) next;
- delta_next = next_watchdog->delta_interval;
+ link = _RBTree_Root_reference( &header->Watchdogs );
+ parent = NULL;
+ old_first = header->first;
+ new_first = &the_watchdog->Node.RBTree;
- if ( delta < delta_next ) {
- _Watchdog_Insert_fixup(
- header,
- the_watchdog,
- delta,
- next_watchdog,
- delta_next
- );
- break;
- }
+ the_watchdog->expire = expire;
- iterator.delta_interval = delta - delta_next;
- iterator.current = next;
+ while ( *link != NULL ) {
+ Watchdog_Control *parent_watchdog;
- _Watchdog_Flash( header, lock_context );
+ parent = *link;
+ parent_watchdog = (Watchdog_Control *) parent;
- if ( the_watchdog->state != WATCHDOG_BEING_INSERTED ) {
- goto abort_insert;
- }
-
- delta = iterator.delta_interval;
- current = iterator.current;
+ if ( expire < parent_watchdog->expire ) {
+ link = _RBTree_Left_reference( parent );
+ } else {
+ link = _RBTree_Right_reference( parent );
+ new_first = old_first;
}
-
- the_watchdog->delta_interval = delta;
- the_watchdog->start_time = _Watchdog_Ticks_since_boot;
- _Watchdog_Activate( the_watchdog );
- _Chain_Insert_unprotected( current, &the_watchdog->Node );
-
-abort_insert:
-
- _Chain_Extract_unprotected( &iterator.Node );
}
-}
-
-void _Watchdog_Insert(
- Watchdog_Header *header,
- Watchdog_Control *the_watchdog
-)
-{
- ISR_lock_Context lock_context;
- _Watchdog_Acquire( header, &lock_context );
- _Watchdog_Insert_locked( header, the_watchdog, &lock_context );
- _Watchdog_Release( header, &lock_context );
+ header->first = new_first;
+ _RBTree_Add_child( &the_watchdog->Node.RBTree, parent, link );
+ _RBTree_Insert_color( &header->Watchdogs, &the_watchdog->Node.RBTree );
}
diff --git a/cpukit/score/src/watchdogremove.c b/cpukit/score/src/watchdogremove.c
index 2aa72a4e75..2605a67fa4 100644
--- a/cpukit/score/src/watchdogremove.c
+++ b/cpukit/score/src/watchdogremove.c
@@ -1,17 +1,22 @@
/**
* @file
*
- * @brief Remove Watchdog from List
+ * @brief Remove Watchdog
* @ingroup ScoreWatchdog
*/
/*
- * COPYRIGHT (c) 1989-1999.
- * On-Line Applications Research Corporation (OAR).
+ * Copyright (c) 2016 embedded brains GmbH. All rights reserved.
*
- * 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.
+ * embedded brains GmbH
+ * Dornierstr. 4
+ * 82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
*/
#if HAVE_CONFIG_H
@@ -19,161 +24,18 @@
#endif
#include <rtems/score/watchdogimpl.h>
-#include <rtems/score/assert.h>
-
-static void _Watchdog_Remove_it(
- Watchdog_Header *header,
- Watchdog_Control *the_watchdog
-)
-{
- Chain_Node *next;
- Watchdog_Interval delta;
- const Chain_Node *iterator_tail;
- Chain_Node *iterator_node;
-
- _Assert( the_watchdog->state == WATCHDOG_ACTIVE );
-
- the_watchdog->state = WATCHDOG_INACTIVE;
- the_watchdog->stop_time = _Watchdog_Ticks_since_boot;
-
- next = _Chain_Next( &the_watchdog->Node );
- delta = the_watchdog->delta_interval;
-
- if ( next != _Chain_Tail( &header->Watchdogs ) ) {
- Watchdog_Control *next_watchdog;
-
- next_watchdog = (Watchdog_Control *) next;
- next_watchdog->delta_interval += delta;
- }
-
- _Chain_Extract_unprotected( &the_watchdog->Node );
-
- iterator_node = _Chain_First( &header->Iterators );
- iterator_tail = _Chain_Immutable_tail( &header->Iterators );
-
- while ( iterator_node != iterator_tail ) {
- Watchdog_Iterator *iterator;
-
- iterator = (Watchdog_Iterator *) iterator_node;
-
- if ( iterator->current == next ) {
- iterator->delta_interval += delta;
- }
-
- if ( iterator->current == &the_watchdog->Node ) {
- Chain_Node *previous = _Chain_Previous( &the_watchdog->Node );
-
- iterator->current = previous;
-
- if ( previous != _Chain_Head( &header->Watchdogs ) ) {
- Watchdog_Control *previous_watchdog;
-
- previous_watchdog = (Watchdog_Control *) previous;
- iterator->delta_interval += previous_watchdog->delta_interval;
- }
- }
-
- iterator_node = _Chain_Next( iterator_node );
- }
-}
-Watchdog_States _Watchdog_Remove(
+void _Watchdog_Remove(
Watchdog_Header *header,
Watchdog_Control *the_watchdog
)
{
- ISR_lock_Context lock_context;
- Watchdog_States previous_state;
- Watchdog_Interval now;
-
- _Watchdog_Acquire( header, &lock_context );
- previous_state = the_watchdog->state;
- switch ( previous_state ) {
- case WATCHDOG_INACTIVE:
- break;
-
- case WATCHDOG_BEING_INSERTED:
-
- /*
- * It is not actually on the chain so just change the state and
- * the Insert operation we interrupted will be aborted.
- */
- the_watchdog->state = WATCHDOG_INACTIVE;
- now = _Watchdog_Ticks_since_boot;
- the_watchdog->start_time = now;
- the_watchdog->stop_time = now;
- break;
-
- case WATCHDOG_ACTIVE:
- _Watchdog_Remove_it( header, the_watchdog );
- break;
- }
-
- _Watchdog_Release( header, &lock_context );
- return( previous_state );
-}
-
-void _Watchdog_Tickle(
- Watchdog_Header *header
-)
-{
- ISR_lock_Context lock_context;
-
- _Watchdog_Acquire( header, &lock_context );
-
- if ( !_Watchdog_Is_empty( header ) ) {
- Watchdog_Control *first;
- Watchdog_Interval delta;
-
- first = _Watchdog_First( header );
- delta = first->delta_interval;
-
- /*
- * Although it is forbidden to insert watchdogs with a delta interval of
- * zero it is possible to observe watchdogs with a delta interval of zero
- * at this point. For example lets have a watchdog chain of one watchdog
- * with a delta interval of one and insert a new one with an initial value
- * of one. At the start of the insert procedure it will advance one step
- * and reduce its delta interval by one yielding zero. Now a tick happens.
- * This will remove the watchdog on the chain and update the insert
- * iterator. Now the insert operation continues and will insert the new
- * watchdog with a delta interval of zero.
- */
- if ( delta > 0 ) {
- --delta;
- first->delta_interval = delta;
+ if ( _Watchdog_Is_scheduled( the_watchdog ) ) {
+ if ( header->first == &the_watchdog->Node.RBTree ) {
+ _Watchdog_Next_first( header, the_watchdog );
}
- while ( delta == 0 ) {
- bool run;
- Watchdog_Service_routine_entry routine;
- Objects_Id id;
- void *user_data;
-
- run = ( first->state == WATCHDOG_ACTIVE );
-
- _Watchdog_Remove_it( header, first );
-
- routine = first->routine;
- id = first->id;
- user_data = first->user_data;
-
- _Watchdog_Release( header, &lock_context );
-
- if ( run ) {
- (*routine)( id, user_data );
- }
-
- _Watchdog_Acquire( header, &lock_context );
-
- if ( _Watchdog_Is_empty( header ) ) {
- break;
- }
-
- first = _Watchdog_First( header );
- delta = first->delta_interval;
- }
+ _RBTree_Extract( &header->Watchdogs, &the_watchdog->Node.RBTree );
+ _Watchdog_Set_state( the_watchdog, WATCHDOG_INACTIVE );
}
-
- _Watchdog_Release( header, &lock_context );
}
diff --git a/cpukit/score/src/watchdogtick.c b/cpukit/score/src/watchdogtick.c
index e89c088350..ab7eadcf1d 100644
--- a/cpukit/score/src/watchdogtick.c
+++ b/cpukit/score/src/watchdogtick.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015 embedded brains GmbH. All rights reserved.
+ * Copyright (c) 2015, 2016 embedded brains GmbH. All rights reserved.
*
* embedded brains GmbH
* Dornierstr. 4
@@ -12,25 +12,81 @@
* http://www.rtems.org/license/LICENSE.
*/
-#include <rtems/score/assert.h>
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems/score/watchdogimpl.h>
#include <rtems/score/schedulerimpl.h>
#include <rtems/score/threaddispatch.h>
-#include <rtems/score/todimpl.h>
-#include <rtems/score/watchdogimpl.h>
+#include <rtems/score/timecounter.h>
-#if HAVE_CONFIG_H
-#include "config.h"
+void _Watchdog_Do_tickle(
+ Watchdog_Header *header,
+ uint64_t now,
+#ifdef RTEMS_SMP
+ ISR_lock_Control *lock,
#endif
+ ISR_lock_Context *lock_context
+)
+{
+ while ( true ) {
+ Watchdog_Control *the_watchdog;
+
+ the_watchdog = (Watchdog_Control *) header->first;
+
+ if ( the_watchdog == NULL ) {
+ break;
+ }
+
+ if ( the_watchdog->expire <= now ) {
+ Watchdog_Service_routine_entry routine;
+
+ _Watchdog_Next_first( header, the_watchdog );
+ _RBTree_Extract( &header->Watchdogs, &the_watchdog->Node.RBTree );
+ _Watchdog_Set_state( the_watchdog, WATCHDOG_INACTIVE );
+ routine = the_watchdog->routine;
+
+ _ISR_lock_Release_and_ISR_enable( lock, lock_context );
+ ( *routine )( the_watchdog );
+ _ISR_lock_ISR_disable_and_acquire( lock, lock_context );
+ } else {
+ break;
+ }
+ }
+
+ _ISR_lock_Release_and_ISR_enable( lock, lock_context );
+}
void _Watchdog_Tick( Per_CPU_Control *cpu )
{
- _Assert( !_Thread_Dispatch_is_enabled() );
+ ISR_lock_Context lock_context;
+ uint64_t ticks;
+ struct timespec now;
if ( _Per_CPU_Is_boot_processor( cpu ) ) {
- _TOD_Tickle_ticks();
+ ++_Watchdog_Ticks_since_boot;
+ }
- _Watchdog_Tickle_ticks();
+ _ISR_lock_ISR_disable_and_acquire( &cpu->Watchdog.Lock, &lock_context );
- _Scheduler_Tick();
- }
+ ticks = cpu->Watchdog.ticks;
+ _Assert( ticks < UINT64_MAX );
+ ++ticks;
+ cpu->Watchdog.ticks = ticks;
+
+ _Watchdog_Tickle(
+ &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_RELATIVE ],
+ ticks,
+ &cpu->Watchdog.Lock,
+ &lock_context
+ );
+
+ _Timecounter_Getnanotime( &now );
+ _Watchdog_Per_CPU_tickle_absolute(
+ cpu,
+ _Watchdog_Ticks_from_timespec( &now )
+ );
+
+ _Scheduler_Tick( cpu );
}
diff --git a/testsuites/psxtests/psx04/init.c b/testsuites/psxtests/psx04/init.c
index ff3bb96e13..945da76a17 100644
--- a/testsuites/psxtests/psx04/init.c
+++ b/testsuites/psxtests/psx04/init.c
@@ -281,7 +281,12 @@ void *POSIX_Init(
puts( "Init: Wait 4 seconds for alarm" );
remaining = sleep( 4 );
printf( "Init: %d seconds left in sleep\n", remaining );
- rtems_test_assert( remaining == 2 );
+
+ /*
+ * sleep() uses nanosleep() internally which discards the nanoseconds part,
+ * e.g. 1.99s -> 1s
+ */
+ rtems_test_assert( remaining == 1 || remaining == 2 );
/* test SIG_SETMASK case and returning oset of pthread_sigmask */
diff --git a/testsuites/smptests/Makefile.am b/testsuites/smptests/Makefile.am
index 92f45286e5..610f3137c4 100644
--- a/testsuites/smptests/Makefile.am
+++ b/testsuites/smptests/Makefile.am
@@ -14,6 +14,7 @@ SUBDIRS += smpatomic01
SUBDIRS += smpcache01
SUBDIRS += smpcapture01
SUBDIRS += smpcapture02
+SUBDIRS += smpclock01
SUBDIRS += smpfatal01
SUBDIRS += smpfatal02
SUBDIRS += smpfatal03
diff --git a/testsuites/smptests/configure.ac b/testsuites/smptests/configure.ac
index 27e8f9c95a..a89b796afe 100644
--- a/testsuites/smptests/configure.ac
+++ b/testsuites/smptests/configure.ac
@@ -69,6 +69,7 @@ smpatomic01/Makefile
smpcache01/Makefile
smpcapture01/Makefile
smpcapture02/Makefile
+smpclock01/Makefile
smpfatal01/Makefile
smpfatal02/Makefile
smpfatal03/Makefile
diff --git a/testsuites/smptests/smpclock01/Makefile.am b/testsuites/smptests/smpclock01/Makefile.am
new file mode 100644
index 0000000000..49e274b833
--- /dev/null
+++ b/testsuites/smptests/smpclock01/Makefile.am
@@ -0,0 +1,20 @@
+rtems_tests_PROGRAMS = smpclock01
+smpclock01_SOURCES = init.c
+smpclock01_SOURCES += ../../support/src/spin.c
+
+dist_rtems_tests_DATA = smpclock01.scn smpclock01.doc
+
+include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg
+include $(top_srcdir)/../automake/compile.am
+include $(top_srcdir)/../automake/leaf.am
+
+AM_CPPFLAGS += -I$(top_srcdir)/../support/include
+
+LINK_OBJS = $(smpclock01_OBJECTS)
+LINK_LIBS = $(smpclock01_LDLIBS)
+
+smpclock01$(EXEEXT): $(smpclock01_OBJECTS) $(smpclock01_DEPENDENCIES)
+ @rm -f smpclock01$(EXEEXT)
+ $(make-exe)
+
+include $(top_srcdir)/../automake/local.am
diff --git a/testsuites/smptests/smpclock01/init.c b/testsuites/smptests/smpclock01/init.c
new file mode 100644
index 0000000000..36016ef680
--- /dev/null
+++ b/testsuites/smptests/smpclock01/init.c
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2016 embedded brains GmbH. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Dornierstr. 4
+ * 82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#ifdef HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#include "tmacros.h"
+
+#include <rtems.h>
+#include <rtems/libcsupport.h>
+#include <rtems/score/percpu.h>
+#include <rtems/score/smpbarrier.h>
+
+#include <test_support.h>
+
+#define CPU_COUNT 2
+
+#define SCHEDULER_A rtems_build_name(' ', ' ', ' ', 'A')
+
+#define SCHEDULER_B rtems_build_name(' ', ' ', ' ', 'B')
+
+const char rtems_test_name[] = "SMPCLOCK 1";
+
+typedef struct {
+ SMP_barrier_Control barrier;
+ SMP_barrier_State delay_barrier_state;
+ SMP_barrier_State timer_barrier_state;
+} test_context;
+
+static test_context test_instance = {
+ .barrier = SMP_BARRIER_CONTROL_INITIALIZER,
+ .delay_barrier_state = SMP_BARRIER_STATE_INITIALIZER,
+ .timer_barrier_state = SMP_BARRIER_STATE_INITIALIZER
+};
+
+static void wait(test_context *ctx, SMP_barrier_State *bs)
+{
+ _SMP_barrier_Wait(&ctx->barrier, bs, CPU_COUNT);
+}
+
+static void timer_isr(rtems_id id, void *arg)
+{
+ test_context *ctx = arg;
+
+ /* (B) */
+ wait(ctx, &ctx->timer_barrier_state);
+}
+
+static void timer_task(rtems_task_argument arg)
+{
+ test_context *ctx = (test_context *) arg;
+ rtems_status_code sc;
+ rtems_id timer_id;
+
+ rtems_test_assert(rtems_get_current_processor() == 1);
+
+ sc = rtems_timer_create(SCHEDULER_B, &timer_id);
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+ /* (A) */
+ wait(ctx, &ctx->timer_barrier_state);
+
+ sc = rtems_timer_fire_after(timer_id, 1, timer_isr, ctx);
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+ sc = rtems_task_wake_after(1);
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+ sc = rtems_timer_delete(timer_id);
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+ /* (C) */
+ wait(ctx, &ctx->timer_barrier_state);
+
+ while (true) {
+ /* Wait for deletion */
+ }
+}
+
+static void delay_clock_tick(test_context *ctx)
+{
+ rtems_interrupt_level level;
+ const Per_CPU_Control *cpu_self = _Per_CPU_Get_by_index(0);
+ const Per_CPU_Control *cpu_other = _Per_CPU_Get_by_index(1);
+ uint64_t ticks;
+
+ rtems_test_assert(rtems_get_current_processor() == 0);
+
+ rtems_test_spin_until_next_tick();
+ ticks = cpu_self->Watchdog.ticks;
+
+ rtems_interrupt_local_disable(level);
+
+ /* (A) */
+ wait(ctx, &ctx->delay_barrier_state);
+
+ /* (B) */
+ wait(ctx, &ctx->delay_barrier_state);
+
+ rtems_test_assert(cpu_self->Watchdog.ticks == ticks);
+ rtems_test_assert(cpu_other->Watchdog.ticks == ticks + 1);
+
+ rtems_interrupt_local_enable(level);
+
+ rtems_test_assert(cpu_self->Watchdog.ticks == ticks + 1);
+ rtems_test_assert(cpu_other->Watchdog.ticks == ticks + 1);
+
+ /* (C) */
+ wait(ctx, &ctx->delay_barrier_state);
+}
+
+static void test(void)
+{
+ test_context *ctx = &test_instance;
+ rtems_status_code sc;
+ rtems_id scheduler_b_id;
+ rtems_id task_id;
+
+ sc = rtems_scheduler_ident(SCHEDULER_B, &scheduler_b_id);
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+ sc = rtems_task_create(
+ SCHEDULER_B,
+ 1,
+ RTEMS_MINIMUM_STACK_SIZE,
+ RTEMS_DEFAULT_MODES,
+ RTEMS_DEFAULT_ATTRIBUTES,
+ &task_id
+ );
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+ sc = rtems_task_set_scheduler(task_id, scheduler_b_id);
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+ sc = rtems_task_start(task_id, timer_task, (rtems_task_argument) ctx);
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+ delay_clock_tick(ctx);
+
+ sc = rtems_task_delete(task_id);
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+}
+
+static void Init(rtems_task_argument arg)
+{
+ rtems_resource_snapshot snapshot;
+
+ TEST_BEGIN();
+
+ rtems_resource_snapshot_take(&snapshot);
+
+ if (rtems_get_processor_count() == CPU_COUNT) {
+ test();
+ }
+
+ rtems_test_assert(rtems_resource_snapshot_check(&snapshot));
+
+ TEST_END();
+ rtems_test_exit(0);
+}
+
+#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
+#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
+
+#define CONFIGURE_SMP_APPLICATION
+
+#define CONFIGURE_SMP_MAXIMUM_PROCESSORS CPU_COUNT
+
+#define CONFIGURE_SCHEDULER_SIMPLE_SMP
+
+#include <rtems/scheduler.h>
+
+RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(a);
+RTEMS_SCHEDULER_CONTEXT_SIMPLE_SMP(b);
+
+#define CONFIGURE_SCHEDULER_CONTROLS \
+ RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(a, SCHEDULER_A), \
+ RTEMS_SCHEDULER_CONTROL_SIMPLE_SMP(b, SCHEDULER_B)
+
+#define CONFIGURE_SMP_SCHEDULER_ASSIGNMENTS \
+ RTEMS_SCHEDULER_ASSIGN(0, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_MANDATORY), \
+ RTEMS_SCHEDULER_ASSIGN(1, RTEMS_SCHEDULER_ASSIGN_PROCESSOR_OPTIONAL)
+
+#define CONFIGURE_MAXIMUM_TASKS CPU_COUNT
+
+#define CONFIGURE_MAXIMUM_TIMERS 1
+
+#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
+
+#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
+
+#define CONFIGURE_INIT
+
+#include <rtems/confdefs.h>
diff --git a/testsuites/smptests/smpclock01/smpclock01.doc b/testsuites/smptests/smpclock01/smpclock01.doc
new file mode 100644
index 0000000000..130644a60d
--- /dev/null
+++ b/testsuites/smptests/smpclock01/smpclock01.doc
@@ -0,0 +1,11 @@
+This file describes the directives and concepts tested by this test set.
+
+test set name: smpclock01
+
+directives:
+
+ - Clock driver interrupt
+
+concepts:
+
+ - Ensures that the clock interrupt is distributed to all online processors.
diff --git a/testsuites/smptests/smpclock01/smpclock01.scn b/testsuites/smptests/smpclock01/smpclock01.scn
new file mode 100644
index 0000000000..192ed83471
--- /dev/null
+++ b/testsuites/smptests/smpclock01/smpclock01.scn
@@ -0,0 +1,2 @@
+*** BEGIN OF TEST SMPCLOCK 1 ***
+*** END OF TEST SMPCLOCK 1 ***
diff --git a/testsuites/smptests/smpwakeafter01/smpwakeafter01.scn b/testsuites/smptests/smpwakeafter01/smpwakeafter01.scn
index 9bbb558421..7fa203d813 100644
--- a/testsuites/smptests/smpwakeafter01/smpwakeafter01.scn
+++ b/testsuites/smptests/smpwakeafter01/smpwakeafter01.scn
@@ -9,36 +9,196 @@
3 seconds remaining
2 seconds remaining
1 seconds remaining
-counts[0][0] = 15479
-counts[0][1] = 17039
-counts[0][2] = 12389
-counts[0][3] = 8077
-counts[0][4] = 3
-counts[0][5] = 2431
-counts[0][6] = 2630
-counts[0][7] = 2128
-counts[1][0] = 15461
-counts[1][1] = 16813
-counts[1][2] = 12248
-counts[1][3] = 7483
-counts[1][4] = 5499
-counts[1][5] = 3170
-counts[1][6] = 2549
-counts[1][7] = 1748
-counts[2][0] = 71
-counts[2][1] = 17068
-counts[2][2] = 7661
-counts[2][3] = 8190
-counts[2][4] = 5513
-counts[2][5] = 3864
-counts[2][6] = 1454
-counts[2][7] = 1993
-counts[3][0] = 14511
-counts[3][1] = 16115
-counts[3][2] = 12561
-counts[3][3] = 7281
-counts[3][4] = 5507
-counts[3][5] = 3828
-counts[3][6] = 2687
-counts[3][7] = 1278
+counts[0][0] = 10013
+counts[0][1] = 5007
+counts[0][2] = 3339
+counts[0][3] = 2004
+counts[0][4] = 1432
+counts[0][5] = 912
+counts[0][6] = 771
+counts[0][7] = 590
+counts[1][0] = 10027
+counts[1][1] = 5015
+counts[1][2] = 3344
+counts[1][3] = 2007
+counts[1][4] = 1434
+counts[1][5] = 913
+counts[1][6] = 773
+counts[1][7] = 591
+counts[2][0] = 10041
+counts[2][1] = 5022
+counts[2][2] = 3349
+counts[2][3] = 2010
+counts[2][4] = 1436
+counts[2][5] = 914
+counts[2][6] = 774
+counts[2][7] = 592
+counts[3][0] = 10055
+counts[3][1] = 5029
+counts[3][2] = 3353
+counts[3][3] = 2013
+counts[3][4] = 1438
+counts[3][5] = 915
+counts[3][6] = 775
+counts[3][7] = 593
+counts[4][0] = 10070
+counts[4][1] = 5036
+counts[4][2] = 3358
+counts[4][3] = 2015
+counts[4][4] = 1440
+counts[4][5] = 917
+counts[4][6] = 776
+counts[4][7] = 594
+counts[5][0] = 10084
+counts[5][1] = 5043
+counts[5][2] = 3363
+counts[5][3] = 2018
+counts[5][4] = 1442
+counts[5][5] = 918
+counts[5][6] = 777
+counts[5][7] = 594
+counts[6][0] = 10098
+counts[6][1] = 5050
+counts[6][2] = 3368
+counts[6][3] = 2021
+counts[6][4] = 1444
+counts[6][5] = 919
+counts[6][6] = 778
+counts[6][7] = 595
+counts[7][0] = 10113
+counts[7][1] = 5058
+counts[7][2] = 3373
+counts[7][3] = 2024
+counts[7][4] = 1446
+counts[7][5] = 921
+counts[7][6] = 779
+counts[7][7] = 596
+counts[8][0] = 10127
+counts[8][1] = 5065
+counts[8][2] = 3377
+counts[8][3] = 2027
+counts[8][4] = 1448
+counts[8][5] = 922
+counts[8][6] = 780
+counts[8][7] = 597
+counts[9][0] = 10142
+counts[9][1] = 5072
+counts[9][2] = 3382
+counts[9][3] = 2030
+counts[9][4] = 1450
+counts[9][5] = 923
+counts[9][6] = 781
+counts[9][7] = 598
+counts[10][0] = 10156
+counts[10][1] = 5079
+counts[10][2] = 3387
+counts[10][3] = 2033
+counts[10][4] = 1452
+counts[10][5] = 925
+counts[10][6] = 783
+counts[10][7] = 599
+counts[11][0] = 10170
+counts[11][1] = 5086
+counts[11][2] = 3392
+counts[11][3] = 2036
+counts[11][4] = 1454
+counts[11][5] = 926
+counts[11][6] = 784
+counts[11][7] = 599
+counts[12][0] = 10185
+counts[12][1] = 5094
+counts[12][2] = 3397
+counts[12][3] = 2039
+counts[12][4] = 1457
+counts[12][5] = 927
+counts[12][6] = 785
+counts[12][7] = 600
+counts[13][0] = 10200
+counts[13][1] = 5101
+counts[13][2] = 3402
+counts[13][3] = 2042
+counts[13][4] = 1459
+counts[13][5] = 929
+counts[13][6] = 786
+counts[13][7] = 601
+counts[14][0] = 10215
+counts[14][1] = 5109
+counts[14][2] = 3407
+counts[14][3] = 2045
+counts[14][4] = 1461
+counts[14][5] = 930
+counts[14][6] = 787
+counts[14][7] = 602
+counts[15][0] = 10230
+counts[15][1] = 5116
+counts[15][2] = 3412
+counts[15][3] = 2048
+counts[15][4] = 1463
+counts[15][5] = 931
+counts[15][6] = 788
+counts[15][7] = 603
+counts[16][0] = 10245
+counts[16][1] = 5124
+counts[16][2] = 3417
+counts[16][3] = 2051
+counts[16][4] = 1465
+counts[16][5] = 933
+counts[16][6] = 789
+counts[16][7] = 604
+counts[17][0] = 10260
+counts[17][1] = 5131
+counts[17][2] = 3422
+counts[17][3] = 2054
+counts[17][4] = 1467
+counts[17][5] = 934
+counts[17][6] = 791
+counts[17][7] = 605
+counts[18][0] = 10275
+counts[18][1] = 5139
+counts[18][2] = 3427
+counts[18][3] = 2057
+counts[18][4] = 1469
+counts[18][5] = 935
+counts[18][6] = 792
+counts[18][7] = 606
+counts[19][0] = 10290
+counts[19][1] = 5146
+counts[19][2] = 3432
+counts[19][3] = 2060
+counts[19][4] = 1472
+counts[19][5] = 937
+counts[19][6] = 793
+counts[19][7] = 607
+counts[20][0] = 10305
+counts[20][1] = 5154
+counts[20][2] = 3437
+counts[20][3] = 2063
+counts[20][4] = 1474
+counts[20][5] = 938
+counts[20][6] = 794
+counts[20][7] = 607
+counts[21][0] = 10320
+counts[21][1] = 5161
+counts[21][2] = 3442
+counts[21][3] = 2066
+counts[21][4] = 1476
+counts[21][5] = 940
+counts[21][6] = 795
+counts[21][7] = 608
+counts[22][0] = 10335
+counts[22][1] = 5169
+counts[22][2] = 3447
+counts[22][3] = 2069
+counts[22][4] = 1478
+counts[22][5] = 941
+counts[22][6] = 796
+counts[22][7] = 609
+counts[23][0] = 10350
+counts[23][1] = 5176
+counts[23][2] = 3452
+counts[23][3] = 2072
+counts[23][4] = 1480
+counts[23][5] = 942
+counts[23][6] = 798
+counts[23][7] = 610
*** END OF TEST SMPWAKEAFTER 1 ***
diff --git a/testsuites/sptests/Makefile.am b/testsuites/sptests/Makefile.am
index c5210a5ab9..43f3d82794 100644
--- a/testsuites/sptests/Makefile.am
+++ b/testsuites/sptests/Makefile.am
@@ -25,7 +25,7 @@ _SUBDIRS = \
spintrcritical05 spintrcritical06 spintrcritical07 spintrcritical08 \
spintrcritical09 spintrcritical10 spintrcritical11 spintrcritical12 \
spintrcritical13 spintrcritical14 spintrcritical15 spintrcritical16 \
- spintrcritical17 spintrcritical18 spmkdir spmountmgr01 spheapprot \
+ spintrcritical18 spmkdir spmountmgr01 spheapprot \
sppagesize spsem01 spsem02 spsimplesched01 spsimplesched02 \
spsimplesched03 spnsext01 spedfsched01 spedfsched02 spedfsched03 \
spcbssched01 spcbssched02 spcbssched03 spqreslib sptimespec01 \
@@ -77,6 +77,7 @@ _SUBDIRS += speventsystem01
_SUBDIRS += spinternalerror01
_SUBDIRS += spinternalerror02
_SUBDIRS += sptimer_err01 sptimer_err02
+_SUBDIRS += sptimerserver01
_SUBDIRS += spclock_err02
if HAS_CPUSET
diff --git a/testsuites/sptests/configure.ac b/testsuites/sptests/configure.ac
index e46f6fa5a5..eeebc91171 100644
--- a/testsuites/sptests/configure.ac
+++ b/testsuites/sptests/configure.ac
@@ -46,6 +46,7 @@ AM_CONDITIONAL(HAS_SMP,test "$rtems_cv_RTEMS_SMP" = "yes")
# Explicitly list all Makefiles here
AC_CONFIG_FILES([Makefile
+sptimerserver01/Makefile
spsysinit01/Makefile
splinkersets01/Makefile
spstdthreads01/Makefile
@@ -216,7 +217,6 @@ spintrcritical13/Makefile
spintrcritical14/Makefile
spintrcritical15/Makefile
spintrcritical16/Makefile
-spintrcritical17/Makefile
spheapprot/Makefile
spmkdir/Makefile
spmountmgr01/Makefile
diff --git a/testsuites/sptests/sp31/task1.c b/testsuites/sptests/sp31/task1.c
index f4e526a027..c3f0ae13fc 100644
--- a/testsuites/sptests/sp31/task1.c
+++ b/testsuites/sptests/sp31/task1.c
@@ -40,14 +40,6 @@ static rtems_timer_service_routine Do_nothing(
/* Do nothing */
}
-static Watchdog_Interval schedule_time( void )
-{
- const Watchdog_Control *watchdog =
- &_Timer_server->Interval_watchdogs.System_watchdog;
-
- return watchdog->initial + watchdog->start_time;
-}
-
rtems_task Task_1(
rtems_task_argument argument
)
@@ -119,10 +111,6 @@ rtems_task Task_1(
"Timer 1 scheduled for %" PRIdWatchdog_Interval " ticks since boot\n",
info.start_time + info.initial
);
- printf(
- "Timer Server scheduled for %" PRIdWatchdog_Interval " ticks since boot\n",
- schedule_time()
- );
puts( "TA1 - rtems_task_wake_after - 1 second" );
status = rtems_task_wake_after( 1 * rtems_clock_get_ticks_per_second() );
@@ -139,11 +127,6 @@ rtems_task Task_1(
"Timer 1 scheduled for %" PRIdWatchdog_Interval " ticks since boot\n",
info.start_time + info.initial
);
- printf(
- "Timer Server scheduled for %" PRIdWatchdog_Interval " ticks since boot\n",
- schedule_time()
- );
- rtems_test_assert( (info.start_time + info.initial) == schedule_time() );
puts( "TA1 - rtems_task_wake_after - 1 second" );
status = rtems_task_wake_after( 1 * rtems_clock_get_ticks_per_second() );
@@ -160,11 +143,6 @@ rtems_task Task_1(
"Timer 1 scheduled for %" PRIdWatchdog_Interval " ticks since boot\n",
info.start_time + info.initial
);
- printf(
- "Timer Server scheduled for %" PRIdWatchdog_Interval " ticks since boot\n",
- schedule_time()
- );
- rtems_test_assert( (info.start_time + info.initial) == schedule_time() );
puts( "TA1 - rtems_timer_cancel - timer 1" );
status = rtems_timer_cancel( tmid );
diff --git a/testsuites/sptests/spintrcritical08/init.c b/testsuites/sptests/spintrcritical08/init.c
index f375cd49f3..3610e65b96 100644
--- a/testsuites/sptests/spintrcritical08/init.c
+++ b/testsuites/sptests/spintrcritical08/init.c
@@ -46,23 +46,21 @@ static rtems_timer_service_routine test_release_from_isr(
void *arg
)
{
- Watchdog_Header *header = &_Watchdog_Ticks_header;
+ Per_CPU_Control *cpu = _Per_CPU_Get();
+ Watchdog_Header *header = &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_RELATIVE ];
+ Watchdog_Control *watchdog = (Watchdog_Control *) header->first;
- if ( !_Watchdog_Is_empty( header ) ) {
- Watchdog_Control *watchdog = _Watchdog_First( header );
+ if (
+ watchdog != NULL
+ && watchdog->expire == cpu->Watchdog.ticks
+ && watchdog->routine == _Rate_monotonic_Timeout
+ ) {
+ _Watchdog_Per_CPU_remove_relative( watchdog );
- if (
- watchdog->delta_interval == 0
- && watchdog->routine == _Rate_monotonic_Timeout
- ) {
- Watchdog_States state = _Watchdog_Remove_ticks( watchdog );
+ (*watchdog->routine)( watchdog );
- rtems_test_assert( state == WATCHDOG_ACTIVE );
- (*watchdog->routine)( watchdog->id, watchdog->user_data );
-
- if ( getState() == RATE_MONOTONIC_EXPIRED_WHILE_BLOCKING ) {
- case_hit = true;
- }
+ if ( getState() == RATE_MONOTONIC_EXPIRED_WHILE_BLOCKING ) {
+ case_hit = true;
}
}
}
diff --git a/testsuites/sptests/spintrcritical09/init.c b/testsuites/sptests/spintrcritical09/init.c
index cc119e88c1..44eccc7821 100644
--- a/testsuites/sptests/spintrcritical09/init.c
+++ b/testsuites/sptests/spintrcritical09/init.c
@@ -15,6 +15,7 @@
#include <intrcritical.h>
#include <rtems/score/threadimpl.h>
+#include <rtems/score/threadimpl.h>
#include <rtems/score/watchdogimpl.h>
const char rtems_test_name[] = "SPINTRCRITICAL 9";
@@ -37,23 +38,21 @@ static rtems_timer_service_routine test_release_from_isr(
void *arg
)
{
- Watchdog_Header *header = &_Watchdog_Ticks_header;
-
- if ( !_Watchdog_Is_empty( header ) ) {
- Watchdog_Control *watchdog = _Watchdog_First( header );
+ Per_CPU_Control *cpu_self = _Per_CPU_Get();
+ Watchdog_Header *header = &cpu_self->Watchdog.Header[ PER_CPU_WATCHDOG_RELATIVE ];
+ Watchdog_Control *watchdog = (Watchdog_Control *) header->first;
- if (
- watchdog->delta_interval == 0
- && watchdog->routine == _Thread_Timeout
- ) {
- Watchdog_States state = _Watchdog_Remove_ticks( watchdog );
+ if (
+ watchdog != NULL
+ && watchdog->expire == cpu_self->Watchdog.ticks
+ && watchdog->routine == _Thread_Timeout
+ ) {
+ _Watchdog_Per_CPU_remove( watchdog, cpu_self, header );
- rtems_test_assert( state == WATCHDOG_ACTIVE );
- (*watchdog->routine)( watchdog->id, watchdog->user_data );
+ (*watchdog->routine)( watchdog );
- if ( is_interrupt_timeout() ) {
- case_hit = true;
- }
+ if ( is_interrupt_timeout() ) {
+ case_hit = true;
}
}
}
diff --git a/testsuites/sptests/spintrcritical10/init.c b/testsuites/sptests/spintrcritical10/init.c
index e4a2a940a6..25be23a852 100644
--- a/testsuites/sptests/spintrcritical10/init.c
+++ b/testsuites/sptests/spintrcritical10/init.c
@@ -78,7 +78,7 @@ static void any_satisfy_before_timeout(rtems_id timer, void *arg)
);
rtems_test_assert(thread->Wait.return_code == RTEMS_SUCCESSFUL);
- _Thread_Timeout(0, thread);
+ _Thread_Timeout(&thread->Timer.Watchdog);
rtems_test_assert(
*(rtems_event_set *) thread->Wait.return_argument == GREEN
@@ -175,7 +175,7 @@ static void all_satisfy_before_timeout(rtems_id timer, void *arg)
);
rtems_test_assert(thread->Wait.return_code == RTEMS_SUCCESSFUL);
- _Thread_Timeout(0, thread);
+ _Thread_Timeout(&thread->Timer.Watchdog);
rtems_test_assert(
*(rtems_event_set *) thread->Wait.return_argument == EVENTS
@@ -251,7 +251,7 @@ static void timeout_before_satisfied(rtems_id timer, void *arg)
);
rtems_test_assert(thread->Wait.return_code == RTEMS_SUCCESSFUL);
- _Thread_Timeout(0, thread);
+ _Thread_Timeout(&thread->Timer.Watchdog);
rtems_test_assert(
*(rtems_event_set *) thread->Wait.return_argument == DEADBEEF
diff --git a/testsuites/sptests/spintrcritical16/init.c b/testsuites/sptests/spintrcritical16/init.c
index a094b419b3..3657c0607f 100644
--- a/testsuites/sptests/spintrcritical16/init.c
+++ b/testsuites/sptests/spintrcritical16/init.c
@@ -43,7 +43,7 @@ static rtems_timer_service_routine test_release_from_isr(
}
if ( Main_TCB->Wait.queue != NULL ) {
- _Thread_Timeout( 0, Main_TCB );
+ _Thread_Timeout( &Main_TCB->Timer.Watchdog );
}
}
diff --git a/testsuites/sptests/spintrcritical17/Makefile.am b/testsuites/sptests/spintrcritical17/Makefile.am
deleted file mode 100644
index 20b372cf48..0000000000
--- a/testsuites/sptests/spintrcritical17/Makefile.am
+++ /dev/null
@@ -1,25 +0,0 @@
-
-rtems_tests_PROGRAMS = spintrcritical17
-spintrcritical17_SOURCES = init.c \
- ../spintrcritical_support/intrcritical.c
-spintrcritical17_SOURCES += ../spintrcritical_support/intrcritical.h
-
-dist_rtems_tests_DATA = spintrcritical17.scn
-dist_rtems_tests_DATA += spintrcritical17.doc
-
-include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg
-include $(top_srcdir)/../automake/compile.am
-include $(top_srcdir)/../automake/leaf.am
-
-
-AM_CPPFLAGS += -I$(top_srcdir)/../support/include
-AM_CPPFLAGS += -I$(top_srcdir)/spintrcritical_support
-
-LINK_OBJS = $(spintrcritical17_OBJECTS)
-LINK_LIBS = $(spintrcritical17_LDLIBS)
-
-spintrcritical17$(EXEEXT): $(spintrcritical17_OBJECTS) $(spintrcritical17_DEPENDENCIES)
- @rm -f spintrcritical17$(EXEEXT)
- $(make-exe)
-
-include $(top_srcdir)/../automake/local.am
diff --git a/testsuites/sptests/spintrcritical17/init.c b/testsuites/sptests/spintrcritical17/init.c
deleted file mode 100644
index 238493e71a..0000000000
--- a/testsuites/sptests/spintrcritical17/init.c
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (c) 2009-2014 embedded brains GmbH.
- *
- * embedded brains GmbH
- * Dornierstr. 4
- * 82178 Puchheim
- * Germany
- * <rtems@embedded-brains.de>
- *
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <tmacros.h>
-#include <intrcritical.h>
-
-#include <rtems/rtems/timerimpl.h>
-
-const char rtems_test_name[] = "SPINTRCRITICAL 17";
-
-typedef struct {
- rtems_id timer1;
- rtems_id timer2;
- bool done;
-} test_context;
-
-static test_context ctx_instance;
-
-static void never(rtems_id timer_id, void *arg)
-{
- rtems_test_assert(0);
-}
-
-static void fire(rtems_id timer_id, void *arg)
-{
- /* The arg is NULL */
- test_context *ctx = &ctx_instance;
- rtems_status_code sc;
-
- if (!ctx->done) {
- ctx->done =
- _Timer_server->Interval_watchdogs.system_watchdog_helper != NULL;
-
- if (ctx->done) {
- sc = rtems_timer_server_fire_after(ctx->timer2, 100, never, NULL);
- rtems_test_assert(sc == RTEMS_SUCCESSFUL);
- }
- }
-}
-
-static bool test_body(void *arg)
-{
- test_context *ctx = arg;
- rtems_status_code sc;
-
- sc = rtems_timer_reset(ctx->timer1);
- rtems_test_assert(sc == RTEMS_SUCCESSFUL);
-
- return ctx->done;
-}
-
-static void Init(rtems_task_argument ignored)
-{
- test_context *ctx = &ctx_instance;
- rtems_status_code sc;
-
- TEST_BEGIN();
-
- sc = rtems_timer_create(
- rtems_build_name('T', 'I', 'M', '1'),
- &ctx->timer1
- );
- rtems_test_assert(sc == RTEMS_SUCCESSFUL);
-
- sc = rtems_timer_create(
- rtems_build_name('T', 'I', 'M', '2'),
- &ctx->timer2
- );
- rtems_test_assert(sc == RTEMS_SUCCESSFUL);
-
- sc = rtems_timer_initiate_server(
- RTEMS_MINIMUM_PRIORITY,
- RTEMS_MINIMUM_STACK_SIZE,
- RTEMS_DEFAULT_ATTRIBUTES
- );
- rtems_test_assert(sc == RTEMS_SUCCESSFUL);
-
- sc = rtems_timer_server_fire_after(ctx->timer1, 1000, never, NULL);
- rtems_test_assert(sc == RTEMS_SUCCESSFUL);
-
- interrupt_critical_section_test(test_body, ctx, fire);
- rtems_test_assert(ctx->done);
-
- TEST_END();
- rtems_test_exit(0);
-}
-
-#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
-#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
-
-#define CONFIGURE_MICROSECONDS_PER_TICK 1000
-
-#define CONFIGURE_MAXIMUM_TASKS 2
-#define CONFIGURE_MAXIMUM_TIMERS 3
-#define CONFIGURE_MAXIMUM_USER_EXTENSIONS 1
-
-#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
-
-#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
-
-#define CONFIGURE_INIT
-
-#include <rtems/confdefs.h>
diff --git a/testsuites/sptests/spintrcritical17/spintrcritical17.doc b/testsuites/sptests/spintrcritical17/spintrcritical17.doc
deleted file mode 100644
index 809a9669d6..0000000000
--- a/testsuites/sptests/spintrcritical17/spintrcritical17.doc
+++ /dev/null
@@ -1,18 +0,0 @@
-# Copyright (c) 2009-2015 embedded brains GmbH.
-#
-# The license and distribution terms for this file may be
-# found in the file LICENSE in this distribution or at
-# http://www.rtems.org/license/LICENSE.
-#
-
-This file describes the directives and concepts tested by this test set.
-
-test set name: spintrcritical17
-
-directives:
-
- _Timer_server_Update_system_watchdog
-
-concepts:
-
-+ Test critical sections which are only accessible through an interrupt.
diff --git a/testsuites/sptests/spintrcritical17/spintrcritical17.scn b/testsuites/sptests/spintrcritical17/spintrcritical17.scn
deleted file mode 100644
index 14566dfb3d..0000000000
--- a/testsuites/sptests/spintrcritical17/spintrcritical17.scn
+++ /dev/null
@@ -1,2 +0,0 @@
-*** TEST INTERRUPT CRITICAL SECTION 17 ***
-*** END OF INTERRUPT CRITICAL SECTION 17 ***
diff --git a/testsuites/sptests/spintrcritical20/init.c b/testsuites/sptests/spintrcritical20/init.c
index 7e52211742..85c1645b5c 100644
--- a/testsuites/sptests/spintrcritical20/init.c
+++ b/testsuites/sptests/spintrcritical20/init.c
@@ -91,7 +91,7 @@ static bool test_body(void *arg)
ctx->thread_queue_was_null = true;
}
- _Thread_Timeout(0, ctx->semaphore_task_tcb);
+ _Thread_Timeout(&ctx->semaphore_task_tcb->Timer.Watchdog);
switch (ctx->semaphore_task_tcb->Wait.return_code) {
case CORE_SEMAPHORE_STATUS_SUCCESSFUL:
diff --git a/testsuites/sptests/spsize/size.c b/testsuites/sptests/spsize/size.c
index e9470e384d..e19ca99606 100644
--- a/testsuites/sptests/spsize/size.c
+++ b/testsuites/sptests/spsize/size.c
@@ -391,8 +391,6 @@ uninitialized =
/*userext.h*/ (sizeof _User_extensions_List) +
/*watchdog.h*/ (sizeof _Watchdog_Ticks_since_boot) +
- (sizeof _Watchdog_Ticks_header) +
- (sizeof _Watchdog_Seconds_header) +
/*wkspace.h*/ (sizeof _Workspace_Area);
diff --git a/testsuites/sptests/sptimecounter01/init.c b/testsuites/sptests/sptimecounter01/init.c
index 7b31064f54..d87ffec460 100644
--- a/testsuites/sptests/sptimecounter01/init.c
+++ b/testsuites/sptests/sptimecounter01/init.c
@@ -24,7 +24,6 @@
#include <rtems/score/timecounterimpl.h>
#include <rtems/score/todimpl.h>
-#include <rtems/score/watchdogimpl.h>
#include <rtems/timecounter.h>
#include <rtems/bsd.h>
@@ -57,8 +56,6 @@ void boot_card(const char *cmdline)
rtems_test_begink();
- _Watchdog_Handler_initialization();
-
assert(time(NULL) == TOD_SECONDS_1970_THROUGH_1988);
rtems_bsd_bintime(&bt);
diff --git a/testsuites/sptests/sptimerserver01/Makefile.am b/testsuites/sptests/sptimerserver01/Makefile.am
new file mode 100644
index 0000000000..2e5048d4e3
--- /dev/null
+++ b/testsuites/sptests/sptimerserver01/Makefile.am
@@ -0,0 +1,19 @@
+rtems_tests_PROGRAMS = sptimerserver01
+sptimerserver01_SOURCES = init.c
+
+dist_rtems_tests_DATA = sptimerserver01.scn sptimerserver01.doc
+
+include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg
+include $(top_srcdir)/../automake/compile.am
+include $(top_srcdir)/../automake/leaf.am
+
+AM_CPPFLAGS += -I$(top_srcdir)/../support/include
+
+LINK_OBJS = $(sptimerserver01_OBJECTS)
+LINK_LIBS = $(sptimerserver01_LDLIBS)
+
+sptimerserver01$(EXEEXT): $(sptimerserver01_OBJECTS) $(sptimerserver01_DEPENDENCIES)
+ @rm -f sptimerserver01$(EXEEXT)
+ $(make-exe)
+
+include $(top_srcdir)/../automake/local.am
diff --git a/testsuites/sptests/sptimerserver01/init.c b/testsuites/sptests/sptimerserver01/init.c
new file mode 100644
index 0000000000..88f1fb3cf3
--- /dev/null
+++ b/testsuites/sptests/sptimerserver01/init.c
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2016 embedded brains GmbH. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Dornierstr. 4
+ * 82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#ifdef HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#include "tmacros.h"
+
+const char rtems_test_name[] = "SPTIMERSERVER 1";
+
+#define TIMER_COUNT 2
+
+typedef struct {
+ rtems_id timer[TIMER_COUNT];
+ rtems_id master;
+} test_context;
+
+static test_context ctx_instance;
+
+static const rtems_time_of_day start = {
+ .year = 2016,
+ .month = 3,
+ .day = 1,
+ .hour = 12,
+ .minute = 5,
+ .second = 17
+};
+
+static void cancel(rtems_id id, void *arg)
+{
+ test_context *ctx = arg;
+ rtems_status_code sc;
+
+ sc = rtems_timer_cancel(ctx->timer[1]);
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+ sc = rtems_event_transient_send(ctx->master);
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+}
+
+static void never(rtems_id id, void *arg)
+{
+ rtems_test_assert(0);
+}
+
+static void test(void)
+{
+ test_context *ctx = &ctx_instance;
+ rtems_status_code sc;
+ size_t i;
+ rtems_time_of_day later;
+
+ ctx->master = rtems_task_self();
+
+ sc = rtems_timer_initiate_server(
+ RTEMS_MINIMUM_PRIORITY,
+ RTEMS_MINIMUM_STACK_SIZE,
+ RTEMS_DEFAULT_ATTRIBUTES
+ );
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+ for (i = 0; i < TIMER_COUNT; ++i) {
+ sc = rtems_timer_create(
+ rtems_build_name('T', 'M', 'R', '0' + i),
+ &ctx->timer[i]
+ );
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+ }
+
+ sc = rtems_timer_server_fire_after(ctx->timer[0], 10, cancel, ctx);
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+ sc = rtems_timer_server_fire_after(ctx->timer[1], 10, never, NULL);
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+ sc = rtems_event_transient_receive(RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+ sc = rtems_clock_set(&start);
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+ later = start;
+ ++later.second;
+
+ sc = rtems_timer_server_fire_when(ctx->timer[0], &later, cancel, ctx);
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+ sc = rtems_timer_server_fire_when(ctx->timer[1], &later, never, NULL);
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+
+ sc = rtems_event_transient_receive(RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+}
+
+static void Init(rtems_task_argument arg)
+{
+ TEST_BEGIN();
+
+ test();
+
+ TEST_END();
+ rtems_test_exit(0);
+}
+
+#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
+#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
+
+#define CONFIGURE_MAXIMUM_TASKS 2
+#define CONFIGURE_MAXIMUM_TIMERS TIMER_COUNT
+
+#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
+
+#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
+
+#define CONFIGURE_INIT
+
+#include <rtems/confdefs.h>
diff --git a/testsuites/sptests/sptimerserver01/sptimerserver01.doc b/testsuites/sptests/sptimerserver01/sptimerserver01.doc
new file mode 100644
index 0000000000..c0dc4ef578
--- /dev/null
+++ b/testsuites/sptests/sptimerserver01/sptimerserver01.doc
@@ -0,0 +1,12 @@
+This file describes the directives and concepts tested by this test set.
+
+test set name: sptimerserver01
+
+directives:
+
+ - rtems_timer_cancel()
+
+concepts:
+
+ - Ensure that pending timer server timers are cancelled via
+ rtems_timer_cancel().
diff --git a/testsuites/sptests/sptimerserver01/sptimerserver01.scn b/testsuites/sptests/sptimerserver01/sptimerserver01.scn
new file mode 100644
index 0000000000..315f030c94
--- /dev/null
+++ b/testsuites/sptests/sptimerserver01/sptimerserver01.scn
@@ -0,0 +1,2 @@
+*** BEGIN OF TEST SPTIMERSERVER 1 ***
+*** END OF TEST SPTIMERSERVER 1 ***
diff --git a/testsuites/sptests/spwatchdog/init.c b/testsuites/sptests/spwatchdog/init.c
index 025295b45b..3b08fb57e5 100644
--- a/testsuites/sptests/spwatchdog/init.c
+++ b/testsuites/sptests/spwatchdog/init.c
@@ -26,241 +26,192 @@
const char rtems_test_name[] = "SPWATCHDOG";
-static void test_watchdog_routine( Objects_Id id, void *arg )
-{
- (void) id;
- (void) arg;
-
- rtems_test_assert( 0 );
-}
+typedef struct {
+ Watchdog_Control Base;
+ int counter;
+} test_watchdog;
-static void init_watchdogs(
- Watchdog_Header *header,
- Watchdog_Control watchdogs[4]
-)
+static void test_watchdog_routine( Watchdog_Control *base )
{
- Watchdog_Control *a = &watchdogs[0];
- Watchdog_Control *b = &watchdogs[1];
- Watchdog_Control *c = &watchdogs[2];
- Watchdog_Control *d = &watchdogs[3];
-
- _Watchdog_Header_initialize( header );
- rtems_test_assert( _Watchdog_Is_empty( header ) );
- rtems_test_assert( _Chain_Is_empty( &header->Iterators ) );
-
- _Watchdog_Preinitialize( c );
- c->initial = 6;
- _Watchdog_Insert( header, c );
- rtems_test_assert( c->delta_interval == 6 );
-
- rtems_test_assert( !_Watchdog_Is_empty( header ) );
- rtems_test_assert( _Chain_Is_empty( &header->Iterators ) );
-
- _Watchdog_Preinitialize( a );
- a->initial = 2;
- _Watchdog_Insert( header, a );
- rtems_test_assert( a->delta_interval == 2 );
- rtems_test_assert( c->delta_interval == 4 );
-
- _Watchdog_Preinitialize( b );
- b->initial = 4;
- _Watchdog_Insert( header, b );
- rtems_test_assert( a->delta_interval == 2 );
- rtems_test_assert( b->delta_interval == 2 );
- rtems_test_assert( c->delta_interval == 2 );
-
- _Watchdog_Preinitialize( d );
-}
+ test_watchdog *watchdog = (test_watchdog *) base;
-static void destroy_watchdogs(
- Watchdog_Header *header
-)
-{
- _ISR_lock_Destroy( &header->Lock );
+ ++watchdog->counter;
}
-static void add_iterator(
- Watchdog_Header *header,
- Watchdog_Iterator *i,
- Watchdog_Control *w
-)
+static void test_watchdog_static_init( void )
{
- _Chain_Append_unprotected( &header->Iterators, &i->Node );
- i->delta_interval = 2;
- i->current = &w->Node;
-}
+ static Watchdog_Control a = WATCHDOG_INITIALIZER(
+ test_watchdog_routine
+ );
+ Watchdog_Control b;
-static void test_watchdog_insert_and_remove( void )
-{
- Watchdog_Header header;
- Watchdog_Control watchdogs[4];
- Watchdog_Control *a = &watchdogs[0];
- Watchdog_Control *b = &watchdogs[1];
- Watchdog_Control *c = &watchdogs[2];
- Watchdog_Control *d = &watchdogs[3];
- Watchdog_Iterator i;
-
- init_watchdogs( &header, watchdogs );
- add_iterator( &header, &i, c );
-
- /* Remove next watchdog of iterator */
- _Watchdog_Remove( &header, c );
- rtems_test_assert( i.delta_interval == 4 );
- rtems_test_assert( i.current == &b->Node );
-
- /* Remove watchdog before the current watchdog of iterator */
- _Watchdog_Remove( &header, a );
- rtems_test_assert( i.delta_interval == 6 );
- rtems_test_assert( i.current == &b->Node );
-
- /* Remove current (= last) watchdog of iterator */
- _Watchdog_Remove( &header, b );
- rtems_test_assert( i.delta_interval == 6 );
- rtems_test_assert( i.current == _Chain_Head( &header.Watchdogs ) );
-
- /* Insert first watchdog */
- a->initial = 1;
- _Watchdog_Insert( &header, a );
- rtems_test_assert( i.delta_interval == 6 );
- rtems_test_assert( i.current == _Chain_Head( &header.Watchdogs ) );
-
- destroy_watchdogs( &header );
- init_watchdogs( &header, watchdogs );
- add_iterator( &header, &i, b );
-
- /* Insert right before current watchdog of iterator */
- d->initial = 3;
- _Watchdog_Insert( &header, d );
- rtems_test_assert( i.delta_interval == 2 );
- rtems_test_assert( i.current == &d->Node );
-
- destroy_watchdogs( &header );
- init_watchdogs( &header, watchdogs );
- add_iterator( &header, &i, b );
-
- /* Insert right after current watchdog of iterator */
- d->initial = 5;
- _Watchdog_Insert( &header, d );
- rtems_test_assert( i.delta_interval == 2 );
- rtems_test_assert( i.current == &b->Node );
-
- destroy_watchdogs( &header );
+ memset( &b, 0, sizeof( b ) );
+ _Watchdog_Preinitialize( &b, _Per_CPU_Get_by_index( 0 ) );
+ _Watchdog_Initialize(
+ &b,
+ test_watchdog_routine
+ );
+
+ rtems_test_assert( memcmp( &a, &b, sizeof( a ) ) == 0 );
}
-static void init_watchdogs_remove_second_and_insert_first(
- Watchdog_Header *header,
- Watchdog_Control watchdogs[3]
-)
+static bool test_watchdog_is_inactive( test_watchdog *watchdog )
{
- Watchdog_Control *a = &watchdogs[0];
- Watchdog_Control *b = &watchdogs[1];
- Watchdog_Control *c = &watchdogs[2];
-
- _Watchdog_Preinitialize( a );
- _Watchdog_Preinitialize( b );
- _Watchdog_Preinitialize( c );
-
- _Watchdog_Header_initialize( header );
-
- a->initial = 6;
- _Watchdog_Insert( header, a );
- rtems_test_assert( a->delta_interval == 6 );
-
- b->initial = 8;
- _Watchdog_Insert( header, b );
- rtems_test_assert( a->delta_interval == 6 );
- rtems_test_assert( b->delta_interval == 2 );
+ return _Watchdog_Get_state( &watchdog->Base ) == WATCHDOG_INACTIVE;
}
-static void test_watchdog_remove_second_and_insert_first( void )
+static void test_watchdog_init( test_watchdog *watchdog, int counter )
{
- Watchdog_Header header;
- Watchdog_Control watchdogs[3];
- Watchdog_Control *a = &watchdogs[0];
- Watchdog_Control *b = &watchdogs[1];
- Watchdog_Control *c = &watchdogs[2];
- Watchdog_Iterator i;
-
- init_watchdogs_remove_second_and_insert_first( &header, watchdogs );
- add_iterator( &header, &i, b );
-
- _Watchdog_Remove( &header, b );
- rtems_test_assert( i.delta_interval == 8 );
- rtems_test_assert( i.current == &a->Node );
-
- c->initial = 4;
- _Watchdog_Insert( &header, c );
- rtems_test_assert( a->delta_interval == 2 );
- rtems_test_assert( c->delta_interval == 4 );
- rtems_test_assert( i.delta_interval == 8 );
- rtems_test_assert( i.current == &c->Node );
-
- destroy_watchdogs( &header );
+ _Watchdog_Preinitialize( &watchdog->Base, _Per_CPU_Get_snapshot() );
+ _Watchdog_Initialize( &watchdog->Base, test_watchdog_routine );
+ rtems_test_assert( test_watchdog_is_inactive( watchdog ) ) ;
+ watchdog->counter = counter;
}
-static void init_watchdogs_insert_with_iterator(
- Watchdog_Header *header,
- Watchdog_Control watchdogs[2]
-)
+static uint64_t test_watchdog_tick( Watchdog_Header *header, uint64_t now )
{
- Watchdog_Control *a = &watchdogs[0];
- Watchdog_Control *b = &watchdogs[1];
+ ISR_LOCK_DEFINE( , lock, "Test" )
+ ISR_lock_Context lock_context;
- _Watchdog_Preinitialize( a );
- _Watchdog_Preinitialize( b );
+ _ISR_lock_ISR_disable_and_acquire( &lock, &lock_context );
+ ++now;
+ _Watchdog_Tickle( header, now, &lock, &lock_context );
+ _ISR_lock_Destroy( &lock );
- _Watchdog_Header_initialize( header );
-
- a->initial = 6;
- _Watchdog_Insert( header, a );
- rtems_test_assert( a->delta_interval == 6 );
+ return now;
}
-static void test_watchdog_insert_with_iterator( void )
+static void test_watchdog_operations( void )
{
Watchdog_Header header;
- Watchdog_Control watchdogs[2];
- Watchdog_Control *a = &watchdogs[0];
- Watchdog_Control *b = &watchdogs[1];
- Watchdog_Iterator i;
-
- init_watchdogs_insert_with_iterator( &header, watchdogs );
- add_iterator( &header, &i, a );
-
- b->initial = 4;
- _Watchdog_Insert( &header, b );
- rtems_test_assert( a->delta_interval == 2 );
- rtems_test_assert( b->delta_interval == 4 );
- rtems_test_assert( i.delta_interval == 2 );
- rtems_test_assert( i.current == &b->Node );
-
- destroy_watchdogs( &header );
-}
-
-static void test_watchdog_static_init( void )
-{
- #if defined(RTEMS_USE_16_BIT_OBJECT)
- #define JUNK_ID 0x1234
- #else
- #define JUNK_ID 0x12345678
- #endif
-
- static Watchdog_Control a = WATCHDOG_INITIALIZER(
- test_watchdog_routine,
- JUNK_ID,
- (void *) 0xdeadbeef
- );
- Watchdog_Control b;
-
- memset( &b, 0, sizeof( b ) );
- _Watchdog_Initialize(
- &b,
- test_watchdog_routine,
- JUNK_ID,
- (void *) 0xdeadbeef
- );
-
- rtems_test_assert( memcmp( &a, &b, sizeof( a ) ) == 0 );
+ uint64_t now;
+ test_watchdog a;
+ test_watchdog b;
+ test_watchdog c;
+
+ _Watchdog_Header_initialize( &header );
+ rtems_test_assert( _RBTree_Is_empty( &header.Watchdogs ) );
+ rtems_test_assert( header.first == NULL );
+
+ test_watchdog_init( &a, 10 );
+ test_watchdog_init( &b, 20 );
+ test_watchdog_init( &c, 30 );
+
+ now = 0;
+ now = test_watchdog_tick( &header, now );
+
+ _Watchdog_Insert( &header, &a.Base, now + 1 );
+ rtems_test_assert( header.first == &a.Base.Node.RBTree );
+ rtems_test_assert( !test_watchdog_is_inactive( &a ) ) ;
+ rtems_test_assert( a.Base.expire == 2 );
+ rtems_test_assert( a.counter == 10 );
+
+ _Watchdog_Remove( &header, &a.Base );
+ rtems_test_assert( header.first == NULL );
+ rtems_test_assert( test_watchdog_is_inactive( &a ) ) ;
+ rtems_test_assert( a.Base.expire == 2 );
+ rtems_test_assert( a.counter == 10 );
+
+ _Watchdog_Remove( &header, &a.Base );
+ rtems_test_assert( header.first == NULL );
+ rtems_test_assert( test_watchdog_is_inactive( &a ) ) ;
+ rtems_test_assert( a.Base.expire == 2 );
+ rtems_test_assert( a.counter == 10 );
+
+ _Watchdog_Insert( &header, &a.Base, now + 1 );
+ rtems_test_assert( header.first == &a.Base.Node.RBTree );
+ rtems_test_assert( !test_watchdog_is_inactive( &a ) ) ;
+ rtems_test_assert( a.Base.expire == 2 );
+ rtems_test_assert( a.counter == 10 );
+
+ _Watchdog_Insert( &header, &b.Base, now + 1 );
+ rtems_test_assert( header.first == &a.Base.Node.RBTree );
+ rtems_test_assert( !test_watchdog_is_inactive( &b ) ) ;
+ rtems_test_assert( b.Base.expire == 2 );
+ rtems_test_assert( b.counter == 20 );
+
+ _Watchdog_Insert( &header, &c.Base, now + 2 );
+ rtems_test_assert( header.first == &a.Base.Node.RBTree );
+ rtems_test_assert( !test_watchdog_is_inactive( &c ) ) ;
+ rtems_test_assert( c.Base.expire == 3 );
+ rtems_test_assert( c.counter == 30 );
+
+ _Watchdog_Remove( &header, &a.Base );
+ rtems_test_assert( header.first == &b.Base.Node.RBTree );
+ rtems_test_assert( test_watchdog_is_inactive( &a ) ) ;
+ rtems_test_assert( a.Base.expire == 2 );
+ rtems_test_assert( a.counter == 10 );
+
+ _Watchdog_Remove( &header, &b.Base );
+ rtems_test_assert( header.first == &c.Base.Node.RBTree );
+ rtems_test_assert( test_watchdog_is_inactive( &b ) ) ;
+ rtems_test_assert( b.Base.expire == 2 );
+ rtems_test_assert( b.counter == 20 );
+
+ _Watchdog_Remove( &header, &c.Base );
+ rtems_test_assert( header.first == NULL );
+ rtems_test_assert( test_watchdog_is_inactive( &c ) ) ;
+ rtems_test_assert( c.Base.expire == 3 );
+ rtems_test_assert( c.counter == 30 );
+
+ _Watchdog_Insert( &header, &a.Base, now + 2 );
+ rtems_test_assert( header.first == &a.Base.Node.RBTree );
+ rtems_test_assert( !test_watchdog_is_inactive( &a ) ) ;
+ rtems_test_assert( a.Base.expire == 3 );
+ rtems_test_assert( a.counter == 10 );
+
+ _Watchdog_Insert( &header, &b.Base, now + 2 );
+ rtems_test_assert( header.first == &a.Base.Node.RBTree );
+ rtems_test_assert( !test_watchdog_is_inactive( &b ) ) ;
+ rtems_test_assert( b.Base.expire == 3 );
+ rtems_test_assert( b.counter == 20 );
+
+ _Watchdog_Insert( &header, &c.Base, now + 3 );
+ rtems_test_assert( header.first == &a.Base.Node.RBTree );
+ rtems_test_assert( !test_watchdog_is_inactive( &c ) ) ;
+ rtems_test_assert( c.Base.expire == 4 );
+ rtems_test_assert( c.counter == 30 );
+
+ now = test_watchdog_tick( &header, now );
+ rtems_test_assert( !_RBTree_Is_empty( &header.Watchdogs ) );
+ rtems_test_assert( header.first == &a.Base.Node.RBTree );
+ rtems_test_assert( !test_watchdog_is_inactive( &a ) ) ;
+ rtems_test_assert( a.Base.expire == 3 );
+ rtems_test_assert( a.counter == 10 );
+ rtems_test_assert( !test_watchdog_is_inactive( &b ) ) ;
+ rtems_test_assert( b.Base.expire == 3 );
+ rtems_test_assert( b.counter == 20 );
+ rtems_test_assert( !test_watchdog_is_inactive( &c ) ) ;
+ rtems_test_assert( c.Base.expire == 4 );
+ rtems_test_assert( c.counter == 30 );
+
+ now = test_watchdog_tick( &header, now );
+ rtems_test_assert( !_RBTree_Is_empty( &header.Watchdogs ) );
+ rtems_test_assert( header.first == &c.Base.Node.RBTree );
+ rtems_test_assert( test_watchdog_is_inactive( &a ) ) ;
+ rtems_test_assert( a.Base.expire == 3 );
+ rtems_test_assert( a.counter == 11 );
+ rtems_test_assert( test_watchdog_is_inactive( &b ) ) ;
+ rtems_test_assert( b.Base.expire == 3 );
+ rtems_test_assert( b.counter == 21 );
+ rtems_test_assert( !test_watchdog_is_inactive( &c ) ) ;
+ rtems_test_assert( c.Base.expire == 4 );
+ rtems_test_assert( c.counter == 30 );
+
+ now = test_watchdog_tick( &header, now );
+ rtems_test_assert( _RBTree_Is_empty( &header.Watchdogs ) );
+ rtems_test_assert( header.first == NULL );
+ rtems_test_assert( test_watchdog_is_inactive( &a ) ) ;
+ rtems_test_assert( a.Base.expire == 3 );
+ rtems_test_assert( a.counter == 11 );
+ rtems_test_assert( test_watchdog_is_inactive( &b ) ) ;
+ rtems_test_assert( b.Base.expire == 3 );
+ rtems_test_assert( b.counter == 21 );
+ rtems_test_assert( test_watchdog_is_inactive( &c ) ) ;
+ rtems_test_assert( c.Base.expire == 4 );
+ rtems_test_assert( c.counter == 31 );
+
+ _Watchdog_Header_destroy( &header );
}
rtems_task Init(
@@ -272,10 +223,8 @@ rtems_task Init(
TEST_BEGIN();
+ test_watchdog_operations();
test_watchdog_static_init();
- test_watchdog_insert_and_remove();
- test_watchdog_remove_second_and_insert_first();
- test_watchdog_insert_with_iterator();
build_time( &time, 12, 31, 1988, 9, 0, 0, 0 );
diff --git a/testsuites/tmtests/tmtimer01/tmtimer01.scn b/testsuites/tmtests/tmtimer01/tmtimer01.scn
index ea882d415f..db3ca01d27 100644
--- a/testsuites/tmtests/tmtimer01/tmtimer01.scn
+++ b/testsuites/tmtests/tmtimer01/tmtimer01.scn
@@ -1,137 +1,137 @@
<TMTimer01 timerCount="65504">
<Sample>
- <ActiveTimers>0</ActiveTimers><First unit="ns">6397</First><Middle unit="ns">3290</Middle><Last unit="ns">1527</Last>
+ <ActiveTimers>0</ActiveTimers><First unit="ns">8812</First><Middle unit="ns">1412</Middle><Last unit="ns">917</Last>
</Sample>
<Sample>
- <ActiveTimers>2</ActiveTimers><First unit="ns">1986</First><Middle unit="ns">1550</Middle><Last unit="ns">1314</Last>
+ <ActiveTimers>2</ActiveTimers><First unit="ns">1602</First><Middle unit="ns">1010</Middle><Last unit="ns">1367</Last>
</Sample>
<Sample>
- <ActiveTimers>4</ActiveTimers><First unit="ns">1551</First><Middle unit="ns">2134</Middle><Last unit="ns">3072</Last>
+ <ActiveTimers>4</ActiveTimers><First unit="ns">1524</First><Middle unit="ns">1089</Middle><Last unit="ns">1086</Last>
</Sample>
<Sample>
- <ActiveTimers>7</ActiveTimers><First unit="ns">2545</First><Middle unit="ns">3511</Middle><Last unit="ns">3404</Last>
+ <ActiveTimers>7</ActiveTimers><First unit="ns">1791</First><Middle unit="ns">1121</Middle><Last unit="ns">1838</Last>
</Sample>
<Sample>
- <ActiveTimers>10</ActiveTimers><First unit="ns">1595</First><Middle unit="ns">2363</Middle><Last unit="ns">4287</Last>
+ <ActiveTimers>10</ActiveTimers><First unit="ns">1488</First><Middle unit="ns">1016</Middle><Last unit="ns">2134</Last>
</Sample>
<Sample>
- <ActiveTimers>14</ActiveTimers><First unit="ns">1473</First><Middle unit="ns">2740</Middle><Last unit="ns">6069</Last>
+ <ActiveTimers>14</ActiveTimers><First unit="ns">1527</First><Middle unit="ns">1698</Middle><Last unit="ns">3186</Last>
</Sample>
<Sample>
- <ActiveTimers>19</ActiveTimers><First unit="ns">1566</First><Middle unit="ns">3195</Middle><Last unit="ns">5993</Last>
+ <ActiveTimers>19</ActiveTimers><First unit="ns">2078</First><Middle unit="ns">1665</Middle><Last unit="ns">3397</Last>
</Sample>
<Sample>
- <ActiveTimers>25</ActiveTimers><First unit="ns">1251</First><Middle unit="ns">2718</Middle><Last unit="ns">7307</Last>
+ <ActiveTimers>25</ActiveTimers><First unit="ns">1519</First><Middle unit="ns">2368</Middle><Last unit="ns">4464</Last>
</Sample>
<Sample>
- <ActiveTimers>32</ActiveTimers><First unit="ns">2302</First><Middle unit="ns">5690</Middle><Last unit="ns">10269</Last>
+ <ActiveTimers>32</ActiveTimers><First unit="ns">1243</First><Middle unit="ns">2623</Middle><Last unit="ns">3549</Last>
</Sample>
<Sample>
- <ActiveTimers>41</ActiveTimers><First unit="ns">1522</First><Middle unit="ns">8221</Middle><Last unit="ns">13424</Last>
+ <ActiveTimers>41</ActiveTimers><First unit="ns">2368</First><Middle unit="ns">2578</Middle><Last unit="ns">4105</Last>
</Sample>
<Sample>
- <ActiveTimers>52</ActiveTimers><First unit="ns">1799</First><Middle unit="ns">8455</Middle><Last unit="ns">14820</Last>
+ <ActiveTimers>52</ActiveTimers><First unit="ns">2322</First><Middle unit="ns">2563</Middle><Last unit="ns">4126</Last>
</Sample>
<Sample>
- <ActiveTimers>66</ActiveTimers><First unit="ns">1062</First><Middle unit="ns">12480</Middle><Last unit="ns">16590</Last>
+ <ActiveTimers>66</ActiveTimers><First unit="ns">2499</First><Middle unit="ns">1855</Middle><Last unit="ns">4919</Last>
</Sample>
<Sample>
- <ActiveTimers>83</ActiveTimers><First unit="ns">1384</First><Middle unit="ns">11710</Middle><Last unit="ns">21854</Last>
+ <ActiveTimers>83</ActiveTimers><First unit="ns">1689</First><Middle unit="ns">3128</Middle><Last unit="ns">5894</Last>
</Sample>
<Sample>
- <ActiveTimers>104</ActiveTimers><First unit="ns">1666</First><Middle unit="ns">15200</Middle><Last unit="ns">30951</Last>
+ <ActiveTimers>104</ActiveTimers><First unit="ns">2301</First><Middle unit="ns">2647</Middle><Last unit="ns">4595</Last>
</Sample>
<Sample>
- <ActiveTimers>130</ActiveTimers><First unit="ns">1345</First><Middle unit="ns">17154</Middle><Last unit="ns">37942</Last>
+ <ActiveTimers>130</ActiveTimers><First unit="ns">2880</First><Middle unit="ns">3183</Middle><Last unit="ns">6222</Last>
</Sample>
<Sample>
- <ActiveTimers>162</ActiveTimers><First unit="ns">1369</First><Middle unit="ns">22381</Middle><Last unit="ns">46929</Last>
+ <ActiveTimers>162</ActiveTimers><First unit="ns">2597</First><Middle unit="ns">2376</Middle><Last unit="ns">7118</Last>
</Sample>
<Sample>
- <ActiveTimers>201</ActiveTimers><First unit="ns">2271</First><Middle unit="ns">35625</Middle><Last unit="ns">59972</Last>
+ <ActiveTimers>201</ActiveTimers><First unit="ns">3519</First><Middle unit="ns">3466</Middle><Last unit="ns">6673</Last>
</Sample>
<Sample>
- <ActiveTimers>249</ActiveTimers><First unit="ns">1279</First><Middle unit="ns">37271</Middle><Last unit="ns">69662</Last>
+ <ActiveTimers>249</ActiveTimers><First unit="ns">2829</First><Middle unit="ns">3177</Middle><Last unit="ns">7784</Last>
</Sample>
<Sample>
- <ActiveTimers>308</ActiveTimers><First unit="ns">864</First><Middle unit="ns">44580</Middle><Last unit="ns">87633</Last>
+ <ActiveTimers>308</ActiveTimers><First unit="ns">2614</First><Middle unit="ns">3396</Middle><Last unit="ns">7338</Last>
</Sample>
<Sample>
- <ActiveTimers>381</ActiveTimers><First unit="ns">1078</First><Middle unit="ns">53821</Middle><Last unit="ns">106376</Last>
+ <ActiveTimers>381</ActiveTimers><First unit="ns">3454</First><Middle unit="ns">4888</Middle><Last unit="ns">9114</Last>
</Sample>
<Sample>
- <ActiveTimers>470</ActiveTimers><First unit="ns">913</First><Middle unit="ns">67021</Middle><Last unit="ns">133201</Last>
+ <ActiveTimers>470</ActiveTimers><First unit="ns">3397</First><Middle unit="ns">2443</Middle><Last unit="ns">7689</Last>
</Sample>
<Sample>
- <ActiveTimers>580</ActiveTimers><First unit="ns">1870</First><Middle unit="ns">79863</Middle><Last unit="ns">169394</Last>
+ <ActiveTimers>580</ActiveTimers><First unit="ns">2233</First><Middle unit="ns">4410</Middle><Last unit="ns">9355</Last>
</Sample>
<Sample>
- <ActiveTimers>715</ActiveTimers><First unit="ns">1732</First><Middle unit="ns">99965</Middle><Last unit="ns">208901</Last>
+ <ActiveTimers>715</ActiveTimers><First unit="ns">3787</First><Middle unit="ns">5891</Middle><Last unit="ns">6833</Last>
</Sample>
<Sample>
- <ActiveTimers>881</ActiveTimers><First unit="ns">1503</First><Middle unit="ns">138820</Middle><Last unit="ns">259314</Last>
+ <ActiveTimers>881</ActiveTimers><First unit="ns">3839</First><Middle unit="ns">5089</Middle><Last unit="ns">9232</Last>
</Sample>
<Sample>
- <ActiveTimers>1085</ActiveTimers><First unit="ns">1096</First><Middle unit="ns">166404</Middle><Last unit="ns">337461</Last>
+ <ActiveTimers>1085</ActiveTimers><First unit="ns">2838</First><Middle unit="ns">2739</Middle><Last unit="ns">11575</Last>
</Sample>
<Sample>
- <ActiveTimers>1336</ActiveTimers><First unit="ns">1383</First><Middle unit="ns">209434</Middle><Last unit="ns">445806</Last>
+ <ActiveTimers>1336</ActiveTimers><First unit="ns">3256</First><Middle unit="ns">5011</Middle><Last unit="ns">9684</Last>
</Sample>
<Sample>
- <ActiveTimers>1645</ActiveTimers><First unit="ns">1787</First><Middle unit="ns">253904</Middle><Last unit="ns">533644</Last>
+ <ActiveTimers>1645</ActiveTimers><First unit="ns">2293</First><Middle unit="ns">5262</Middle><Last unit="ns">10183</Last>
</Sample>
<Sample>
- <ActiveTimers>2025</ActiveTimers><First unit="ns">2082</First><Middle unit="ns">327384</Middle><Last unit="ns">657141</Last>
+ <ActiveTimers>2025</ActiveTimers><First unit="ns">4436</First><Middle unit="ns">5934</Middle><Last unit="ns">8804</Last>
</Sample>
<Sample>
- <ActiveTimers>2492</ActiveTimers><First unit="ns">1843</First><Middle unit="ns">417457</Middle><Last unit="ns">814380</Last>
+ <ActiveTimers>2492</ActiveTimers><First unit="ns">4506</First><Middle unit="ns">7284</Middle><Last unit="ns">10389</Last>
</Sample>
<Sample>
- <ActiveTimers>3067</ActiveTimers><First unit="ns">1980</First><Middle unit="ns">493511</Middle><Last unit="ns">977427</Last>
+ <ActiveTimers>3067</ActiveTimers><First unit="ns">3832</First><Middle unit="ns">4990</Middle><Last unit="ns">9536</Last>
</Sample>
<Sample>
- <ActiveTimers>3774</ActiveTimers><First unit="ns">2695</First><Middle unit="ns">622065</Middle><Last unit="ns">1237577</Last>
+ <ActiveTimers>3774</ActiveTimers><First unit="ns">5088</First><Middle unit="ns">4888</Middle><Last unit="ns">9633</Last>
</Sample>
<Sample>
- <ActiveTimers>4644</ActiveTimers><First unit="ns">1463</First><Middle unit="ns">827565</Middle><Last unit="ns">1565553</Last>
+ <ActiveTimers>4644</ActiveTimers><First unit="ns">5590</First><Middle unit="ns">5749</Middle><Last unit="ns">8975</Last>
</Sample>
<Sample>
- <ActiveTimers>5714</ActiveTimers><First unit="ns">1866</First><Middle unit="ns">1053458</Middle><Last unit="ns">1914932</Last>
+ <ActiveTimers>5714</ActiveTimers><First unit="ns">4854</First><Middle unit="ns">6813</Middle><Last unit="ns">11603</Last>
</Sample>
<Sample>
- <ActiveTimers>7030</ActiveTimers><First unit="ns">3481</First><Middle unit="ns">1266198</Middle><Last unit="ns">2450199</Last>
+ <ActiveTimers>7030</ActiveTimers><First unit="ns">6139</First><Middle unit="ns">6132</Middle><Last unit="ns">12630</Last>
</Sample>
<Sample>
- <ActiveTimers>8649</ActiveTimers><First unit="ns">2773</First><Middle unit="ns">1558351</Middle><Last unit="ns">2967472</Last>
+ <ActiveTimers>8649</ActiveTimers><First unit="ns">6877</First><Middle unit="ns">3852</Middle><Last unit="ns">10973</Last>
</Sample>
<Sample>
- <ActiveTimers>10640</ActiveTimers><First unit="ns">2086</First><Middle unit="ns">2003884</Middle><Last unit="ns">3766161</Last>
+ <ActiveTimers>10640</ActiveTimers><First unit="ns">6532</First><Middle unit="ns">6097</Middle><Last unit="ns">11725</Last>
</Sample>
<Sample>
- <ActiveTimers>13089</ActiveTimers><First unit="ns">3911</First><Middle unit="ns">2501427</Middle><Last unit="ns">4619553</Last>
+ <ActiveTimers>13089</ActiveTimers><First unit="ns">5284</First><Middle unit="ns">5392</Middle><Last unit="ns">13246</Last>
</Sample>
<Sample>
- <ActiveTimers>16101</ActiveTimers><First unit="ns">3276</First><Middle unit="ns">3189159</Middle><Last unit="ns">5886373</Last>
+ <ActiveTimers>16101</ActiveTimers><First unit="ns">7077</First><Middle unit="ns">7572</Middle><Last unit="ns">14820</Last>
</Sample>
<Sample>
- <ActiveTimers>19806</ActiveTimers><First unit="ns">3801</First><Middle unit="ns">4005049</Middle><Last unit="ns">7394938</Last>
+ <ActiveTimers>19806</ActiveTimers><First unit="ns">7132</First><Middle unit="ns">8335</Middle><Last unit="ns">11668</Last>
</Sample>
<Sample>
- <ActiveTimers>24363</ActiveTimers><First unit="ns">3088</First><Middle unit="ns">4977788</Middle><Last unit="ns">9138839</Last>
+ <ActiveTimers>24363</ActiveTimers><First unit="ns">8676</First><Middle unit="ns">7919</Middle><Last unit="ns">13937</Last>
</Sample>
<Sample>
- <ActiveTimers>29968</ActiveTimers><First unit="ns">4089</First><Middle unit="ns">6133462</Middle><Last unit="ns">11361012</Last>
+ <ActiveTimers>29968</ActiveTimers><First unit="ns">5970</First><Middle unit="ns">10978</Middle><Last unit="ns">16035</Last>
</Sample>
<Sample>
- <ActiveTimers>36862</ActiveTimers><First unit="ns">2059</First><Middle unit="ns">7870138</Middle><Last unit="ns">14319206</Last>
+ <ActiveTimers>36862</ActiveTimers><First unit="ns">8804</First><Middle unit="ns">8767</Middle><Last unit="ns">13089</Last>
</Sample>
<Sample>
- <ActiveTimers>45342</ActiveTimers><First unit="ns">2224</First><Middle unit="ns">9917100</Middle><Last unit="ns">17754441</Last>
+ <ActiveTimers>45342</ActiveTimers><First unit="ns">8608</First><Middle unit="ns">10305</Middle><Last unit="ns">15709</Last>
</Sample>
<Sample>
- <ActiveTimers>55772</ActiveTimers><First unit="ns">1979</First><Middle unit="ns">11815557</Middle><Last unit="ns">21907509</Last>
+ <ActiveTimers>55772</ActiveTimers><First unit="ns">8949</First><Middle unit="ns">10031</Middle><Last unit="ns">16262</Last>
</Sample>
<Sample>
- <ActiveTimers>65503</ActiveTimers><First unit="ns">2404</First><Middle unit="ns">13694591</Middle><Last unit="ns">26215885</Last>
+ <ActiveTimers>65503</ActiveTimers><First unit="ns">9199</First><Middle unit="ns">10309</Middle><Last unit="ns">19090</Last>
</Sample>
</TMTimer01>