score: Replace watchdog handler implementation

Use a red-black tree instead of delta chains.

Close #2344.
Update #2554.
Update #2555.
Close #2606.
This commit is contained in:
Sebastian Huber
2016-03-04 13:36:10 +01:00
parent 90d8567d34
commit 03b900d3ed
92 changed files with 2445 additions and 2670 deletions
+1 -2
View File
@@ -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
@@ -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.
@@ -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. */
+33 -21
View File
@@ -21,6 +21,7 @@
#include <rtems/posix/timer.h>
#include <rtems/score/objectimpl.h>
#include <rtems/score/watchdogimpl.h>
#ifdef __cplusplus
extern "C" {
@@ -50,24 +51,6 @@ extern "C" {
#error "POSIX_TIMER_RELATIVE == TIMER_ABSTIME"
#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( &_POSIX_Timer_Information, (Objects_Id) id, location );
return (POSIX_Timer_Control *) _Objects_Get_isr_disable(
&_POSIX_Timer_Information,
(Objects_Id) id,
location,
lock_context
);
}
RTEMS_INLINE_ROUTINE Per_CPU_Control *_POSIX_Timer_Acquire_critical(
POSIX_Timer_Control *ptimer,
ISR_lock_Context *lock_context
)
{
Per_CPU_Control *cpu;
cpu = _Watchdog_Get_CPU( &ptimer->Timer );
_Watchdog_Per_CPU_acquire_critical( cpu, lock_context );
return cpu;
}
RTEMS_INLINE_ROUTINE void _POSIX_Timer_Release(
Per_CPU_Control *cpu,
ISR_lock_Context *lock_context
)
{
_Watchdog_Per_CPU_release_critical( cpu, lock_context );
_ISR_lock_ISR_enable( lock_context );
}
#ifdef __cplusplus
+49 -41
View File
@@ -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
)
{
#if defined(RTEMS_DEBUG)
int status;
#define KILL_STATUS status =
#else
#define KILL_STATUS (void)
#endif
ISR_LOCK_DEFINE( static, _POSIX_signals_Alarm_lock, "POSIX Alarm" )
KILL_STATUS kill( getpid(), SIGALRM );
static void _POSIX_signals_Alarm_TSR( Watchdog_Control *the_watchdog )
{
int status;
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;
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_timer = &_POSIX_signals_Alarm_timer;
the_watchdog = &_POSIX_signals_Alarm_watchdog;
ticks_per_second = TOD_TICKS_PER_SECOND;
ticks = seconds * ticks_per_second;
_Thread_Disable_dispatch();
_ISR_lock_ISR_disable_and_acquire(
&_POSIX_signals_Alarm_lock,
&lock_context
);
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.
*/
cpu = _Watchdog_Get_CPU( the_watchdog );
_Watchdog_Per_CPU_acquire_critical( cpu, &lock_context2 );
now = cpu->Watchdog.ticks;
remaining = the_timer->initial -
((the_timer->stop_time - the_timer->start_time) / TOD_TICKS_PER_SECOND);
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 );
_Watchdog_Per_CPU_release_critical( cpu, &lock_context2 );
_ISR_lock_Release_and_ISR_enable(
&_POSIX_signals_Alarm_lock,
&lock_context
);
_Thread_Enable_dispatch();
return remaining;
return ( remaining + ticks_per_second - 1 ) / ticks_per_second;
}
+4 -1
View File
@@ -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
+18 -13
View File
@@ -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 );
+5 -1
View File
@@ -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();
+10 -4
View File
@@ -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;
}
+2 -1
View File
@@ -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;
+9 -3
View File
@@ -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();
+5 -2
View File
@@ -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)
+15 -14
View File
@@ -42,31 +42,32 @@ int timer_gettime(
{
POSIX_Timer_Control *ptimer;
Objects_Locations location;
struct timespec current_time;
Watchdog_Interval left;
ISR_lock_Context lock_context;
Per_CPU_Control *cpu;
uint64_t now;
uint32_t remaining;
if ( !value )
rtems_set_errno_and_return_minus_one( EINVAL );
/* Reads the current time */
_TOD_Get_as_timespec( &current_time );
ptimer = _POSIX_Timer_Get( timerid, &location );
ptimer = _POSIX_Timer_Get( timerid, &location, &lock_context );
switch ( location ) {
case OBJECTS_LOCAL:
/* Calculates the time left before the timer finishes */
cpu = _POSIX_Timer_Acquire_critical( ptimer, &lock_context );
now = cpu->Watchdog.ticks;
left =
(ptimer->Timer.start_time + ptimer->Timer.initial) - /* expire */
_Watchdog_Ticks_since_boot; /* now */
if ( now < ptimer->Timer.expire ) {
remaining = (uint32_t) ( ptimer->Timer.expire - now );
} else {
remaining = 0;
}
_Timespec_From_ticks( left, &value->it_value );
_Timespec_From_ticks( remaining, &value->it_value );
value->it_interval = ptimer->timer_data.it_interval;
value->it_interval = ptimer->timer_data.it_interval;
_Objects_Put( &ptimer->Object );
_POSIX_Timer_Release( cpu, &lock_context );
return 0;
#if defined(RTEMS_MULTIPROCESSING)
-66
View File
@@ -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;
}
+104 -42
View File
@@ -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 );
/* 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 );
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;
/*
* 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:
-89
View File
@@ -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;
}
+85 -60
View File
@@ -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
);
static uint32_t _POSIX_signals_Ualarm_interval;
/*
* _POSIX_signals_Ualarm_TSR
*/
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;
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_timer = &_POSIX_signals_Ualarm_timer;
the_watchdog = &_POSIX_signals_Ualarm_watchdog;
ticks_initial = _POSIX_signals_Ualarm_us_to_ticks( useconds );
ticks_interval = _POSIX_signals_Ualarm_us_to_ticks( interval );
_Thread_Disable_dispatch();
_ISR_lock_ISR_disable_and_acquire(
&_POSIX_signals_Ualarm_lock,
&lock_context
);
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.
*/
cpu = _Watchdog_Get_CPU( the_watchdog );
_Watchdog_Per_CPU_acquire_critical( cpu, &lock_context2 );
now = cpu->Watchdog.ticks;
ticks = the_timer->initial;
ticks -= (the_timer->stop_time - the_timer->start_time);
/* remaining is now in ticks */
remaining = (useconds_t) _Watchdog_Cancel(
&cpu->Watchdog.Header[ PER_CPU_WATCHDOG_RELATIVE ],
the_watchdog,
now
);
_Timespec_From_ticks( ticks, &tp );
remaining = tp.tv_sec * TOD_MICROSECONDS_PER_SECOND;
remaining += tp.tv_nsec / 1000;
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;
_Watchdog_Per_CPU_release_critical( cpu, &lock_context2 );
_ISR_lock_Release_and_ISR_enable(
&_POSIX_signals_Ualarm_lock,
&lock_context
);
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 ) );
}
_Thread_Enable_dispatch();
remaining *= rtems_configuration_get_microseconds_per_tick();
return remaining;
}
+8 -14
View File
@@ -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
* 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(
rtems_id id,
void *ignored
);
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
);
+59 -32
View File
@@ -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 in use as an interval
* timer which will fire in the clock tick ISR.
*/
TIMER_INTERVAL,
/**
* 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,
/**
* 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,
/**
* 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_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_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_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_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 =
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
);
/**
+105 -111
View File
@@ -10,6 +10,8 @@
* COPYRIGHT (c) 1989-2011.
* On-Line Applications Research Corporation (OAR).
*
* Copyright (c) 2016 embedded brains GmbH.
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
@@ -35,81 +37,13 @@ extern "C" {
* @{
*/
typedef struct Timer_server_Control Timer_server_Control;
typedef struct Timer_server_Control {
ISR_LOCK_MEMBER( Lock )
/**
* @brief Method used for task based timers.
*/
typedef void (*Timer_server_Method)(
Timer_server_Control *timer_server,
Timer_Control *timer
);
Chain_Control Pending;
typedef struct {
/**
* @brief This watchdog that will be registered in the system tick mechanic
* for timer server wake-up.
*/
Watchdog_Control System_watchdog;
/**
* @brief Remaining delta of the system watchdog.
*/
Watchdog_Interval system_watchdog_delta;
/**
* @brief Unique identifier of the context which deals currently with the
* system watchdog.
*/
Thread_Control *system_watchdog_helper;
/**
* @brief Each insert and tickle operation increases the generation count so
* that the system watchdog dealer notices updates of the watchdog chain.
*/
uint32_t generation;
/**
* @brief Watchdog header managed by the timer server.
*/
Watchdog_Header Header;
/**
* @brief Last time snapshot of the timer server.
*
* The units may be ticks or seconds.
*/
Watchdog_Interval last_snapshot;
/**
* @brief Current time snapshot of the timer server.
*
* The units may be ticks or seconds.
*/
Watchdog_Interval current_snapshot;
} Timer_server_Watchdogs;
struct Timer_server_Control {
/**
* @brief The cancel method of the timer server.
*/
Timer_server_Method cancel;
/**
* @brief The schedule operation method of the timer server.
*/
Timer_server_Method schedule_operation;
/**
* @brief Interval watchdogs triggered by the timer server.
*/
Timer_server_Watchdogs Interval_watchdogs;
/**
* @brief TOD watchdogs triggered by the timer server.
*/
Timer_server_Watchdogs TOD_watchdogs;
};
Objects_Id server_id;
} Timer_server_Control;
/**
* @brief Pointer to default timer server control block.
@@ -148,64 +82,124 @@ RTEMS_INLINE_ROUTINE void _Timer_Free (
_Objects_Free( &_Timer_Information, &the_timer->Object );
}
/**
* @brief Timer_Get
*
* This function maps timer IDs to timer control blocks.
* If ID corresponds to a local timer, then it returns
* the timer control pointer which maps to ID and location
* is set to OBJECTS_LOCAL. Otherwise, location is set
* to OBJECTS_ERROR and the returned value is undefined.
*/
RTEMS_INLINE_ROUTINE Timer_Control *_Timer_Get (
RTEMS_INLINE_ROUTINE Timer_Control *_Timer_Get(
Objects_Id id,
Objects_Locations *location
Objects_Locations *location,
ISR_lock_Context *lock_context
)
{
return (Timer_Control *)
_Objects_Get( &_Timer_Information, id, location );
return (Timer_Control *) _Objects_Get_isr_disable(
&_Timer_Information,
id,
location,
lock_context
);
}
/**
* @brief Timer_Is_interval_class
*
* This function returns TRUE if the class is that of an INTERVAL
* timer, and FALSE otherwise.
*/
RTEMS_INLINE_ROUTINE bool _Timer_Is_interval_class (
RTEMS_INLINE_ROUTINE Per_CPU_Control *_Timer_Acquire_critical(
Timer_Control *the_timer,
ISR_lock_Context *lock_context
)
{
Per_CPU_Control *cpu;
cpu = _Watchdog_Get_CPU( &the_timer->Ticker );
_Watchdog_Per_CPU_acquire_critical( cpu, lock_context );
return cpu;
}
RTEMS_INLINE_ROUTINE void _Timer_Release(
Per_CPU_Control *cpu,
ISR_lock_Context *lock_context
)
{
_Watchdog_Per_CPU_release_critical( cpu, lock_context );
_ISR_lock_ISR_enable( lock_context );
}
RTEMS_INLINE_ROUTINE bool _Timer_Is_interval_class(
Timer_Classes the_class
)
{
return (the_class == TIMER_INTERVAL) || (the_class == TIMER_INTERVAL_ON_TASK);
Timer_Classes mask =
TIMER_CLASS_BIT_NOT_DORMANT | TIMER_CLASS_BIT_TIME_OF_DAY;
return ( the_class & mask ) == TIMER_CLASS_BIT_NOT_DORMANT;
}
/**
* @brief Timer_Is_time_of_day_class
*
* This function returns TRUE if the class is that of an INTERVAL
* timer, and FALSE otherwise.
*/
RTEMS_INLINE_ROUTINE bool _Timer_Is_timer_of_day_class (
RTEMS_INLINE_ROUTINE bool _Timer_Is_on_task_class(
Timer_Classes the_class
)
{
return ( the_class == TIMER_TIME_OF_DAY );
Timer_Classes mask =
TIMER_CLASS_BIT_NOT_DORMANT | TIMER_CLASS_BIT_ON_TASK;
return ( the_class & mask ) == mask;
}
/**
* @brief Timer_Is_dormant_class
*
* This function returns TRUE if the class is that of a DORMANT
* timer, and FALSE otherwise.
*/
RTEMS_INLINE_ROUTINE bool _Timer_Is_dormant_class (
RTEMS_INLINE_ROUTINE Per_CPU_Watchdog_index _Timer_Watchdog_header_index(
Timer_Classes the_class
)
{
return ( the_class == TIMER_DORMANT );
return ( the_class & TIMER_CLASS_BIT_TIME_OF_DAY );
}
void _Timer_Cancel( Timer_Control *the_timer );
RTEMS_INLINE_ROUTINE Watchdog_Interval _Timer_Get_CPU_ticks(
const Per_CPU_Control *cpu
)
{
return (Watchdog_Interval) cpu->Watchdog.ticks;
}
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 );
}
/**@}*/
+5 -6
View File
@@ -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 );
}
+1 -1
View File
@@ -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 );
+4 -1
View File
@@ -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 );
+2 -1
View File
@@ -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 );
+4 -1
View File
@@ -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 );
+18 -20
View File
@@ -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;
+15 -31
View File
@@ -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 ) {
the_period = RTEMS_CONTAINER_OF( watchdog, Rate_monotonic_Control, Timer );
the_thread = the_period->owner;
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 );
_Thread_Disable_dispatch();
_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;
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();
}
+4 -5
View File
@@ -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;
+7 -11
View File
@@ -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;
+8 -23
View File
@@ -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)
+156 -23
View File
@@ -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,
+6 -8
View File
@@ -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;
+8 -56
View File
@@ -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
);
}
+8 -42
View File
@@ -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
);
}
+8 -5
View File
@@ -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)
+15 -26
View File
@@ -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)
+95 -301
View File
@@ -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 );
}
_ISR_lock_ISR_disable_and_acquire( &ts->Lock, lock_context );
}
static Watchdog_Interval _Timer_server_Get_ticks( void )
{
return _Watchdog_Ticks_since_boot;
}
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,98 +136,34 @@ static rtems_task _Timer_server_Body(
}
}
static void _Timer_server_Wakeup(
Objects_Id id,
void *arg
static rtems_status_code _Timer_server_Initiate(
rtems_task_priority priority,
size_t stack_size,
rtems_attribute attribute_set
)
{
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
)
{
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
@@ -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
);
#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
_Assert( status == RTEMS_SUCCESSFUL );
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;
}
+11 -57
View File
@@ -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
);
}
+11 -59
View File
@@ -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
);
}
-3
View File
@@ -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();
+2 -3
View File
@@ -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
+6 -1
View File
@@ -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;
/**
+16 -16
View File
@@ -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 );
+51 -2
View File
@@ -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
@@ -225,6 +226,32 @@ typedef struct {
#endif /* defined( RTEMS_PROFILING ) */
} 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
*
@@ -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.
@@ -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 );
}
}
+11 -2
View File
@@ -346,6 +346,15 @@ typedef struct {
Thread_queue_Heads *spare_heads;
} 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;
+58 -3
View File
@@ -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,
@@ -131,15 +131,6 @@ extern "C" {
* @brief TOD control.
*/
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.
*
@@ -272,14 +263,6 @@ static inline uint32_t _TOD_Seconds_since_epoch( void )
return (uint32_t) _Timecounter_Time_second;
}
/**
* @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.
*
+49 -42
View File
@@ -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 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.
typedef struct {
/**
* @brief Red-black tree of scheduled watchdogs sorted by expiration time.
*/
WATCHDOG_BEING_INSERTED,
/** This is the state when the watchdog is on a chain, and allowed to fire. */
WATCHDOG_ACTIVE
} Watchdog_States;
RBTree_Control Watchdogs;
/**
* @brief The scheduled watchdog with the earliest expiration time or NULL in
* case no watchdog is scheduled.
*/
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.
struct Watchdog_Control {
/**
* @brief Nodes for the watchdog.
*/
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.
*/
void *user_data;
} Watchdog_Control;
union {
/**
* @brief this field is a red-black tree node structure and allows this to
* be placed on a red-black tree used to manage the scheduled watchdogs.
*/
RBTree_Node RBTree;
/**
* @brief this field is a chain node structure and allows this to be placed
* on a chain used to manage pending watchdogs by the timer server.
*/
Chain_Node Chain;
} Node;
#if defined(RTEMS_SMP)
/** @brief This field references the processor of this watchdog control. */
struct Per_CPU_Control *cpu;
#endif
/** @brief This field is the function to invoke. */
Watchdog_Service_routine_entry routine;
/** @brief This field is the expiration time point. */
uint64_t expire;
};
/**
* @brief The watchdog ticks counter.
File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More