[PATCH 8/8] score: Replace watchdog handler implementation
Gedare Bloom
gedare at rtems.org
Thu Mar 3 17:36:23 UTC 2016
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?
"be placed on Red-Black Trees for set management." copy-pasted comment
should be Chains?
"watchdog is scheduled and a black node". ditto, black should be red
for the second one.
_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.
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
More information about the devel
mailing list