[PATCH 8/8] score: Replace watchdog handler implementation
Joel Sherrill
joel at rtems.org
Thu Mar 3 22:44:02 UTC 2016
On Thu, Mar 3, 2016 at 12:41 PM, Sebastian Huber <
sebastian.huber at embedded-brains.de> wrote:
> Thanks a lot for your review.
>
> ----- Gedare Bloom <gedare at rtems.org> schrieb:
> > I scanned through most of it. I just have a few minor issues/questions:
> >
> > There is an _Assert(0) followed by a TODO. This _Assert() is likely
> > dead/untested code block. It may be worth fabricating a fatal test for
> > it, if possible?
>
> This one:
>
> > + 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.
> > + */
>
> Its a code move from one file to another, so nothing new.
>
>
I recall convincing myself years ago when implementing this that if an
error is generated, there was nothing we could do. It was a long time ago
and I think the only thing that can happen is that the thread no longer
exists when the timer fires.
I recall that the signo has already been error checked when the timer is
created so that error can't be generated unless there is data corruption.
Also I am not sure pthread_kill() returns distinct errors for those
conditions.
If it does, then maybe one is an explicit nop via comment or we add
debug asserts. Debug asserts didn't exist when this code was written.
> >
> > "be placed on Red-Black Trees for set management." copy-pasted comment
> > should be Chains?
>
> Thanks, for spotting this.
>
> >
> > "watchdog is scheduled and a black node". ditto, black should be red
> > for the second one.
>
> Oh, yes.
>
> >
> > _Watchdog_Ticks_from_seconds(): why is ticks = seconds<<30 the right
> > thing to do? Same for _Watchdog_Ticks_from_timespec(). I am missing
> > some assumption here, I guess. It might improve readability to provide
> > a helper function for this.
>
> Ok, sorry for the magic numbers. 2**30 == 1073741824 enough to cope with
> 1e9 nanoseconds. So, we have 2**34 seconds available, leading to a year
> 2514 problem.
>
>
That's pretty close to the 2^64 nanosecond limit as I recall. So reasonable
but
I suppose that should be very explicit somewhere in a comment.
Funny, before there was a wiki, we had a FAQ document which had a section on
date/time overflow issues. We probably need a section in the users manual
with
the current truth on this:
https://docs.rtems.org/releases/rtemsdocs-4.6.4/share/rtems/html/FAQ/FAQ00100.html
We have multiple date/time and interval representations in the score,
classic and
POSIX APIs. It would be good to capture them again.
--joel
> >
> >
> > On Thu, Mar 3, 2016 at 10:23 AM, Joel Sherrill <joel at rtems.org> wrote:
> > > This looks OK but is such a large patch, it needs more eyes.
> > >
> > > Gedare and Chris... please.
> > >
> > > On Thu, Mar 3, 2016 at 8:47 AM, Sebastian Huber
> > > <sebastian.huber at embedded-brains.de> wrote:
> > >>
> > >> Use a red-black tree instead of delta chains.
> > >>
> > >> Close #2344.
> > >> Update #2554.
> > >> Update #2555.
> > >> Close #2606.
> > >> ---
> > >> cpukit/posix/Makefile.am | 3 +-
> > >> cpukit/posix/include/rtems/posix/pthreadimpl.h | 5 +-
> > >> cpukit/posix/include/rtems/posix/threadsup.h | 2 +
> > >> cpukit/posix/include/rtems/posix/timerimpl.h | 54 +-
> > >> cpukit/posix/src/alarm.c | 96 ++--
> > >> cpukit/posix/src/nanosleep.c | 5 +-
> > >> cpukit/posix/src/pthread.c | 31 +-
> > >> cpukit/posix/src/pthreadcreate.c | 6 +-
> > >> cpukit/posix/src/pthreadsetschedparam.c | 14 +-
> > >> cpukit/posix/src/timercreate.c | 3 +-
> > >> cpukit/posix/src/timerdelete.c | 12 +-
> > >> cpukit/posix/src/timergetoverrun.c | 7 +-
> > >> cpukit/posix/src/timergettime.c | 29 +-
> > >> cpukit/posix/src/timerinserthelper.c | 66 ---
> > >> cpukit/posix/src/timersettime.c | 152 ++++--
> > >> cpukit/posix/src/timertsr.c | 89 ----
> > >> cpukit/posix/src/ualarm.c | 155 +++---
> > >> cpukit/rtems/include/rtems/rtems/ratemonimpl.h | 24 +-
> > >> cpukit/rtems/include/rtems/rtems/timer.h | 59 ++-
> > >> cpukit/rtems/include/rtems/rtems/timerimpl.h | 216 ++++----
> > >> cpukit/rtems/src/eventseize.c | 11 +-
> > >> cpukit/rtems/src/eventsurrender.c | 2 +-
> > >> cpukit/rtems/src/ratemoncancel.c | 5 +-
> > >> cpukit/rtems/src/ratemoncreate.c | 3 +-
> > >> cpukit/rtems/src/ratemondelete.c | 5 +-
> > >> cpukit/rtems/src/ratemonperiod.c | 38 +-
> > >> cpukit/rtems/src/ratemontimeout.c | 50 +-
> > >> cpukit/rtems/src/taskwakeafter.c | 9 +-
> > >> cpukit/rtems/src/taskwakewhen.c | 18 +-
> > >> cpukit/rtems/src/timercancel.c | 31 +-
> > >> cpukit/rtems/src/timercreate.c | 179 ++++++-
> > >> cpukit/rtems/src/timerdelete.c | 14 +-
> > >> cpukit/rtems/src/timerfireafter.c | 64 +--
> > >> cpukit/rtems/src/timerfirewhen.c | 50 +-
> > >> cpukit/rtems/src/timergetinfo.c | 13 +-
> > >> cpukit/rtems/src/timerreset.c | 41 +-
> > >> cpukit/rtems/src/timerserver.c | 394
> ++++----------
> > >> cpukit/rtems/src/timerserverfireafter.c | 68 +--
> > >> cpukit/rtems/src/timerserverfirewhen.c | 70 +--
> > >> cpukit/sapi/src/exinit.c | 3 -
> > >> cpukit/score/Makefile.am | 5 +-
> > >> cpukit/score/include/rtems/score/mrsp.h | 7 +-
> > >> cpukit/score/include/rtems/score/mrspimpl.h | 32 +-
> > >> cpukit/score/include/rtems/score/percpu.h | 53 +-
> > >> cpukit/score/include/rtems/score/schedulerimpl.h | 16 +-
> > >> cpukit/score/include/rtems/score/thread.h | 13 +-
> > >> cpukit/score/include/rtems/score/threadimpl.h | 61 ++-
> > >> cpukit/score/include/rtems/score/todimpl.h | 17 -
> > >> cpukit/score/include/rtems/score/watchdog.h | 89 ++--
> > >> cpukit/score/include/rtems/score/watchdogimpl.h | 590
> > >> +++++++++------------
> > >> cpukit/score/src/condition.c | 2 +-
> > >> cpukit/score/src/coretodset.c | 28 +-
> > >> cpukit/score/src/coretodtickle.c | 36 --
> > >> cpukit/score/src/kern_tc.c | 3 +-
> > >> cpukit/score/src/smp.c | 1 +
> > >> cpukit/score/src/threadinitialize.c | 4 +
> > >> cpukit/score/src/threadqenqueue.c | 10 +-
> > >> cpukit/score/src/threadrestart.c | 12 +-
> > >> cpukit/score/src/threadtimeout.c | 4 +-
> > >> cpukit/score/src/watchdog.c | 36 --
> > >> cpukit/score/src/watchdogadjust.c | 80 ---
> > >> cpukit/score/src/watchdoginsert.c | 132 ++---
> > >> cpukit/score/src/watchdogremove.c | 172 +-----
> > >> cpukit/score/src/watchdogtick.c | 78 ++-
> > >> testsuites/smptests/Makefile.am | 1 +
> > >> testsuites/smptests/configure.ac | 1 +
> > >> testsuites/smptests/smpclock01/Makefile.am | 20 +
> > >> testsuites/smptests/smpclock01/init.c | 206 +++++++
> > >> testsuites/smptests/smpclock01/smpclock01.doc | 11 +
> > >> testsuites/smptests/smpclock01/smpclock01.scn | 2 +
> > >> .../smptests/smpwakeafter01/smpwakeafter01.scn | 224 ++++++--
> > >> testsuites/sptests/Makefile.am | 3 +-
> > >> testsuites/sptests/configure.ac | 2 +-
> > >> testsuites/sptests/sp31/task1.c | 22 -
> > >> testsuites/sptests/spintrcritical08/init.c | 26 +-
> > >> testsuites/sptests/spintrcritical09/init.c | 27 +-
> > >> testsuites/sptests/spintrcritical10/init.c | 6 +-
> > >> testsuites/sptests/spintrcritical16/init.c | 2 +-
> > >> testsuites/sptests/spintrcritical17/Makefile.am | 25 -
> > >> testsuites/sptests/spintrcritical17/init.c | 118 -----
> > >> .../sptests/spintrcritical17/spintrcritical17.doc | 18 -
> > >> .../sptests/spintrcritical17/spintrcritical17.scn | 2 -
> > >> testsuites/sptests/spintrcritical20/init.c | 2 +-
> > >> testsuites/sptests/spsize/size.c | 2 -
> > >> testsuites/sptests/sptimecounter01/init.c | 3 -
> > >> testsuites/sptests/sptimerserver01/Makefile.am | 19 +
> > >> testsuites/sptests/sptimerserver01/init.c | 129 +++++
> > >> .../sptests/sptimerserver01/sptimerserver01.doc | 12 +
> > >> .../sptests/sptimerserver01/sptimerserver01.scn | 2 +
> > >> testsuites/sptests/spwatchdog/init.c | 381
> ++++++-------
> > >> testsuites/tmtests/tmtimer01/tmtimer01.scn | 90 ++--
> > >> 91 files changed, 2340 insertions(+), 2593 deletions(-)
> > >> delete mode 100644 cpukit/posix/src/timerinserthelper.c
> > >> delete mode 100644 cpukit/posix/src/timertsr.c
> > >> delete mode 100644 cpukit/score/src/coretodtickle.c
> > >> delete mode 100644 cpukit/score/src/watchdog.c
> > >> delete mode 100644 cpukit/score/src/watchdogadjust.c
> > >> create mode 100644 testsuites/smptests/smpclock01/Makefile.am
> > >> create mode 100644 testsuites/smptests/smpclock01/init.c
> > >> create mode 100644 testsuites/smptests/smpclock01/smpclock01.doc
> > >> create mode 100644 testsuites/smptests/smpclock01/smpclock01.scn
> > >> delete mode 100644 testsuites/sptests/spintrcritical17/Makefile.am
> > >> delete mode 100644 testsuites/sptests/spintrcritical17/init.c
> > >> delete mode 100644
> > >> testsuites/sptests/spintrcritical17/spintrcritical17.doc
> > >> delete mode 100644
> > >> testsuites/sptests/spintrcritical17/spintrcritical17.scn
> > >> create mode 100644 testsuites/sptests/sptimerserver01/Makefile.am
> > >> create mode 100644 testsuites/sptests/sptimerserver01/init.c
> > >> create mode 100644
> testsuites/sptests/sptimerserver01/sptimerserver01.doc
> > >> create mode 100644
> testsuites/sptests/sptimerserver01/sptimerserver01.scn
> > >>
> > >> diff --git a/cpukit/posix/Makefile.am b/cpukit/posix/Makefile.am
> > >> index 40bc153..62a2a5a 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 870b5f9..16b0163 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 55db35d..7cd2354 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 8b5b42e..8c151c1 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( 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( 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 e85622f..196bc16 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( 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( 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 46697ae..21bdb98 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 ac5fbe4..001ae79 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 3185ab6..fc07b1f 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 c3be366..c9560f5 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 697f1ce..5123071 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 8438b0d..c39de8e 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 dd7669e..0a28fa7 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 f065cc9..7f0015b 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( ¤t_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 b1f3373..0000000
> > >> --- 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 fe54ff9..ac5c258 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 092bf16..0000000
> > >> --- 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 9607d3f..27cd2eb 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( 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( 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 490912e..f184c44 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 7cc9051..032c495 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 55be634..59ba09b 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( cpu, lock_context );
> > >> +
> > >> + return cpu;
> > >> +}
> > >> +
> > >> +RTEMS_INLINE_ROUTINE void _Timer_Release(
> > >> + Per_CPU_Control *cpu,
> > >> + ISR_lock_Context *lock_context
> > >> +)
> > >> +{
> > >> + _Watchdog_Per_CPU_release( 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 3dc554f..0be6bd6 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 5726cc8..7c4fe2e 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 67b230f..2e4d532 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 1ac4a36..1a5c9b2 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 77cf3fe..09b9ab6 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 6afe101..58be148 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 08f9bd1..7c25595 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 b7f328f..fa5f6f4 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 cf0b303..5d6d45a 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 1e737a2..5d4343e 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 5c718b9..80c1356 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 0849ec5..9c41397 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 84cf46b..82bd878 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 1acbaf9..eddeb16 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 17c32e6..a11861c 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 7ab172e..72c912b 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 7d75780..cf06319 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 0636782..ce1fd05 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 0069af1..f96a470 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 7df2316..350c774 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 3d3f1c1..ea440b3 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 08f96ac..cb3de67 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 bc9ed4b..7638fb5 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 39be1e3..2201788 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 cadebfd..d50c36a 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 73776b3..44b706d 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 1377543..ec9851d 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 b61651c..b1f8a6d 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 bad7269..b371f94 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 Red-Black Trees for set management.
> > >> + */
> > >> + RBTree_Node RBTree;
> > >> +
> > >> + /**
> > >> + * @brief This field is a Chain Node structure and allows this to
> > >> + * be placed on Red-Black Trees for set management.
> > >> + */
> > >> + 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 49ac2a1..0f6947f 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 black 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,261 @@ 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;
> > >> }
> > >>
> > >> -/**
> > >> - * This routine returns true if the watchdog timer is in the ACTIVE
> > >> - * state, and false otherwise.
> > >> - */
> > >> -
> > >> -RTEMS_INLINE_ROUTINE bool _Watchdog_Is_active(
> > >> - Watchdog_Control *the_watchdog
> > >> -)
> > >> -{
> > >> -
> > >> - return ( the_watchdog->state == WATCHDOG_ACTIVE );
> > >> +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 activates THE_WATCHDOG timer which is already
> > >> - * on a watchdog chain.
> > >> + * @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 void _Watchdog_Activate(
> > >> +/**
> > >> + * @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
> > >> -)
> > >> -{
> > >> -
> > >> - the_watchdog->state = WATCHDOG_ACTIVE;
> > >> -
> > >> -}
> > >> +);
> > >>
> > >> /**
> > >> - * This routine is invoked at each clock tick to update the ticks
> > >> - * 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_Tickle_ticks( void )
> > >> +RTEMS_INLINE_ROUTINE uint64_t _Watchdog_Cancel(
> > >> + Watchdog_Header *header,
> > >> + Watchdog_Control *the_watchdog,
> > >> + uint64_t now
> > >> +)
> > >> {
> > >> + uint64_t expire;
> > >> + uint64_t remaining;
> > >>
> > >> - _Watchdog_Tickle( &_Watchdog_Ticks_header );
> > >> -
> > >> -}
> > >> -
> > >> -/**
> > >> - * This routine is invoked at each clock tick to update the seconds
> > >> - * watchdog chain.
> > >> - */
> > >> + expire = the_watchdog->expire;
> > >>
> > >> -RTEMS_INLINE_ROUTINE void _Watchdog_Tickle_seconds( void )
> > >> -{
> > >> + if ( now < expire ) {
> > >> + remaining = expire - now;
> > >> + } else {
> > >> + remaining = 0;
> > >> + }
> > >>
> > >> - _Watchdog_Tickle( &_Watchdog_Seconds_header );
> > >> + _Watchdog_Remove( header, the_watchdog );
> > >>
> > >> + return remaining;
> > >> }
> > >>
> > >> -/**
> > >> - * 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 bool _Watchdog_Is_scheduled(
> > >> + const Watchdog_Control *the_watchdog
> > >> )
> > >> {
> > >> -
> > >> - the_watchdog->initial = units;
> > >> -
> > >> - _Watchdog_Insert( &_Watchdog_Ticks_header, the_watchdog );
> > >> -
> > >> + return _Watchdog_Get_state( the_watchdog ) < WATCHDOG_INACTIVE;
> > >> }
> > >>
> > >> -/**
> > >> - * 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.
> > >> - */
> > >> -
> > >> -RTEMS_INLINE_ROUTINE void _Watchdog_Insert_seconds(
> > >> - 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_Seconds_header, the_watchdog );
> > >> + while ( ( left = _RBTree_Left( node ) ) != NULL ) {
> > >> + node = left;
> > >> + }
> > >>
> > >> + header->first = node;
> > >> + } else {
> > >> + header->first = _RBTree_Parent( &the_watchdog->Node.RBTree );
> > >> + }
> > >> }
> > >>
> > >> -RTEMS_INLINE_ROUTINE Watchdog_States _Watchdog_Remove_ticks(
> > >> - Watchdog_Control *the_watchdog
> > >> +RTEMS_INLINE_ROUTINE uint64_t _Watchdog_Ticks_from_seconds(
> > >> + uint32_t seconds
> > >> )
> > >> {
> > >> - return _Watchdog_Remove( &_Watchdog_Ticks_header, the_watchdog );
> > >> -}
> > >> + uint64_t ticks = seconds;
> > >>
> > >> -RTEMS_INLINE_ROUTINE Watchdog_States _Watchdog_Remove_seconds(
> > >> - Watchdog_Control *the_watchdog
> > >> -)
> > >> -{
> > >> - return _Watchdog_Remove( &_Watchdog_Seconds_header, the_watchdog );
> > >> -}
> > >> + ticks <<= 30;
> > >>
> > >> -/**
> > >> - * 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.
> > >> - */
> > >> + return ticks;
> > >> +}
> > >>
> > >> -RTEMS_INLINE_ROUTINE void _Watchdog_Reset_ticks(
> > >> - Watchdog_Control *the_watchdog
> > >> +RTEMS_INLINE_ROUTINE uint64_t _Watchdog_Ticks_from_timespec(
> > >> + const struct timespec *ts
> > >> )
> > >> {
> > >> + uint64_t ticks = (uint64_t) ts->tv_sec;
> > >>
> > >> - _Watchdog_Remove_ticks( the_watchdog );
> > >> + _Assert( ticks < 0x400000000 );
> > >> + _Assert( ts->tv_nsec >= 0 );
> > >> + _Assert( ts->tv_nsec < 1000000000 );
> > >>
> > >> - _Watchdog_Insert( &_Watchdog_Ticks_header, the_watchdog );
> > >> + ticks <<= 30;
> > >> + ticks |= ts->tv_nsec;
> > >>
> > >> + return ticks;
> > >> }
> > >>
> > >> -/**
> > >> - * This routine returns a pointer to the watchdog timer following
> > >> - * THE_WATCHDOG on the watchdog chain.
> > >> - */
> > >> +#define _Watchdog_Per_CPU_acquire( cpu, lock_context ) \
> > >> + _ISR_lock_Acquire( &( cpu )->Watchdog.Lock, lock_context )
> > >>
> > >> -RTEMS_INLINE_ROUTINE Watchdog_Control *_Watchdog_Next(
> > >> - Watchdog_Control *the_watchdog
> > >> +#define _Watchdog_Per_CPU_release( cpu, lock_context ) \
> > >> + _ISR_lock_Release( &( cpu )->Watchdog.Lock, lock_context )
> > >> +
> > >> +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( cpu, &lock_context );
> > >> + _Watchdog_Insert(
> > >> + &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_RELATIVE ],
> > >> + the_watchdog,
> > >> + cpu->Watchdog.ticks + ticks
> > >> + );
> > >> + _Watchdog_Per_CPU_release( 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( cpu, &lock_context );
> > >> + _Watchdog_Insert(
> > >> + &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_ABSOLUTE ],
> > >> + the_watchdog,
> > >> + expire
> > >> + );
> > >> + _Watchdog_Per_CPU_release( 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( cpu, &lock_context );
> > >> + _Watchdog_Remove(
> > >> + header,
> > >> + the_watchdog
> > >> + );
> > >> + _Watchdog_Per_CPU_release( 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 22c2a9b..4206819 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 3230179..b2efc07 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 3d7c71e..0000000
> > >> --- 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 e56c292..316a16f 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 9d9507d..85256b0 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 a49406f..0b5fd3a 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 960783c..07618fc 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 03b1fba..d366f97 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 8ecaebd..59f6bd9 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 8d172fb..0000000
> > >> --- 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 32b5f79..0000000
> > >> --- 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 db15f55..22fc7a5 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 at 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 2aa72a4..2605a67 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 at 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 e89c088..ab7eadc 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/smptests/Makefile.am
> > >> b/testsuites/smptests/Makefile.am
> > >> index 92f4528..610f313 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 27e8f9c..a89b796 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 0000000..49e274b
> > >> --- /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 at .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 0000000..36016ef
> > >> --- /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 at 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 0000000..130644a
> > >> --- /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 0000000..192ed83
> > >> --- /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 9bbb558..7fa203d 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 c5210a5..43f3d82 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 e46f6fa..eeebc91 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 f4e526a..c3f0ae1 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 f375cd4..3610e65 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 cc119e8..44eccc7 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 e4a2a94..25be23a 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 a094b41..3657c06 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 20b372c..0000000
> > >> --- 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 at .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 238493e..0000000
> > >> --- 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 at 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 809a966..0000000
> > >> --- 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 14566df..0000000
> > >> --- 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 7e52211..85c1645 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 e9470e3..e19ca99 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 7b31064..d87ffec 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 0000000..2e5048d
> > >> --- /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 at .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 0000000..88f1fb3
> > >> --- /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 at 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 0000000..c0dc4ef
> > >> --- /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 0000000..315f030
> > >> --- /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 025295b..3b08fb5 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 ea882d4..db3ca01 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>
> > >> --
> > >> 1.8.4.5
> > >>
> > >> _______________________________________________
> > >> devel mailing list
> > >> devel at rtems.org
> > >> http://lists.rtems.org/mailman/listinfo/devel
> > >
> > >
> > >
> > > _______________________________________________
> > > devel mailing list
> > > devel at rtems.org
> > > http://lists.rtems.org/mailman/listinfo/devel
> >
> >
>
> --
> Sebastian Huber, embedded brains GmbH
>
> Address : Dornierstr. 4, D-82178 Puchheim, Germany
> Phone : +49 89 189 47 41-16
> Fax : +49 89 189 47 41-09
> E-Mail : sebastian.huber at embedded-brains.de
> PGP : Public key available on request.
>
> Diese Nachricht ist keine geschäftliche Mitteilung im Sinne des EHUG.
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.rtems.org/pipermail/devel/attachments/20160303/8056b3e8/attachment-0002.html>
More information about the devel
mailing list