mirror of
https://gitlab.rtems.org/rtems/rtos/rtems.git
synced 2026-09-28 00:49:13 +08:00
score: Optimize watchdog tickle
Avoid unnecessary lock acquire/release operations. Get realtime via timecounter only if necessary. Update #3264.
This commit is contained in:
@@ -96,6 +96,13 @@ RTEMS_INLINE_ROUTINE void _Watchdog_Header_initialize(
|
|||||||
header->first = NULL;
|
header->first = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RTEMS_INLINE_ROUTINE Watchdog_Control *_Watchdog_Header_first(
|
||||||
|
const Watchdog_Header *header
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return (Watchdog_Control *) header->first;
|
||||||
|
}
|
||||||
|
|
||||||
RTEMS_INLINE_ROUTINE void _Watchdog_Header_destroy(
|
RTEMS_INLINE_ROUTINE void _Watchdog_Header_destroy(
|
||||||
Watchdog_Header *header
|
Watchdog_Header *header
|
||||||
)
|
)
|
||||||
@@ -187,6 +194,7 @@ RTEMS_INLINE_ROUTINE void _Watchdog_Initialize(
|
|||||||
|
|
||||||
void _Watchdog_Do_tickle(
|
void _Watchdog_Do_tickle(
|
||||||
Watchdog_Header *header,
|
Watchdog_Header *header,
|
||||||
|
Watchdog_Control *first,
|
||||||
uint64_t now,
|
uint64_t now,
|
||||||
#if defined(RTEMS_SMP)
|
#if defined(RTEMS_SMP)
|
||||||
ISR_lock_Control *lock,
|
ISR_lock_Control *lock,
|
||||||
@@ -195,11 +203,11 @@ void _Watchdog_Do_tickle(
|
|||||||
);
|
);
|
||||||
|
|
||||||
#if defined(RTEMS_SMP)
|
#if defined(RTEMS_SMP)
|
||||||
#define _Watchdog_Tickle( header, now, lock, lock_context ) \
|
#define _Watchdog_Tickle( header, first, now, lock, lock_context ) \
|
||||||
_Watchdog_Do_tickle( header, now, lock, lock_context )
|
_Watchdog_Do_tickle( header, first, now, lock, lock_context )
|
||||||
#else
|
#else
|
||||||
#define _Watchdog_Tickle( header, now, lock, lock_context ) \
|
#define _Watchdog_Tickle( header, first, now, lock, lock_context ) \
|
||||||
_Watchdog_Do_tickle( header, now, lock_context )
|
_Watchdog_Do_tickle( header, first, now, lock_context )
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -548,22 +556,6 @@ RTEMS_INLINE_ROUTINE void _Watchdog_Per_CPU_remove_realtime(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
RTEMS_INLINE_ROUTINE void _Watchdog_Per_CPU_tickle_realtime(
|
|
||||||
Per_CPU_Control *cpu,
|
|
||||||
uint64_t now
|
|
||||||
)
|
|
||||||
{
|
|
||||||
ISR_lock_Context lock_context;
|
|
||||||
|
|
||||||
_ISR_lock_ISR_disable_and_acquire( &cpu->Watchdog.Lock, &lock_context );
|
|
||||||
_Watchdog_Tickle(
|
|
||||||
&cpu->Watchdog.Header[ PER_CPU_WATCHDOG_REALTIME ],
|
|
||||||
now,
|
|
||||||
&cpu->Watchdog.Lock,
|
|
||||||
&lock_context
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
@@ -41,9 +41,29 @@ void _TOD_Set(
|
|||||||
cpu_count = _SMP_Get_processor_count();
|
cpu_count = _SMP_Get_processor_count();
|
||||||
|
|
||||||
for ( cpu_index = 0 ; cpu_index < cpu_count ; ++cpu_index ) {
|
for ( cpu_index = 0 ; cpu_index < cpu_count ; ++cpu_index ) {
|
||||||
Per_CPU_Control *cpu = _Per_CPU_Get_by_index( cpu_index );
|
Per_CPU_Control *cpu;
|
||||||
|
Watchdog_Header *header;
|
||||||
|
ISR_lock_Context lock_context;
|
||||||
|
Watchdog_Control *first;
|
||||||
|
|
||||||
_Watchdog_Per_CPU_tickle_realtime( cpu, tod_as_ticks );
|
cpu = _Per_CPU_Get_by_index( cpu_index );
|
||||||
|
header = &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_REALTIME ];
|
||||||
|
|
||||||
|
_ISR_lock_ISR_disable_and_acquire( &cpu->Watchdog.Lock, &lock_context );
|
||||||
|
|
||||||
|
first = _Watchdog_Header_first( header );
|
||||||
|
|
||||||
|
if ( first != NULL ) {
|
||||||
|
_Watchdog_Tickle(
|
||||||
|
header,
|
||||||
|
first,
|
||||||
|
tod_as_ticks,
|
||||||
|
&cpu->Watchdog.Lock,
|
||||||
|
&lock_context
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
_ISR_lock_Release_and_ISR_enable( &cpu->Watchdog.Lock, &lock_context );
|
||||||
}
|
}
|
||||||
|
|
||||||
_TOD.is_set = true;
|
_TOD.is_set = true;
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
|
|
||||||
void _Watchdog_Do_tickle(
|
void _Watchdog_Do_tickle(
|
||||||
Watchdog_Header *header,
|
Watchdog_Header *header,
|
||||||
|
Watchdog_Control *first,
|
||||||
uint64_t now,
|
uint64_t now,
|
||||||
#ifdef RTEMS_SMP
|
#ifdef RTEMS_SMP
|
||||||
ISR_lock_Control *lock,
|
ISR_lock_Control *lock,
|
||||||
@@ -30,39 +31,33 @@ void _Watchdog_Do_tickle(
|
|||||||
ISR_lock_Context *lock_context
|
ISR_lock_Context *lock_context
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
while ( true ) {
|
do {
|
||||||
Watchdog_Control *the_watchdog;
|
if ( first->expire <= now ) {
|
||||||
|
|
||||||
the_watchdog = (Watchdog_Control *) header->first;
|
|
||||||
|
|
||||||
if ( the_watchdog == NULL ) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( the_watchdog->expire <= now ) {
|
|
||||||
Watchdog_Service_routine_entry routine;
|
Watchdog_Service_routine_entry routine;
|
||||||
|
|
||||||
_Watchdog_Next_first( header, the_watchdog );
|
_Watchdog_Next_first( header, first );
|
||||||
_RBTree_Extract( &header->Watchdogs, &the_watchdog->Node.RBTree );
|
_RBTree_Extract( &header->Watchdogs, &first->Node.RBTree );
|
||||||
_Watchdog_Set_state( the_watchdog, WATCHDOG_INACTIVE );
|
_Watchdog_Set_state( first, WATCHDOG_INACTIVE );
|
||||||
routine = the_watchdog->routine;
|
routine = first->routine;
|
||||||
|
|
||||||
_ISR_lock_Release_and_ISR_enable( lock, lock_context );
|
_ISR_lock_Release_and_ISR_enable( lock, lock_context );
|
||||||
( *routine )( the_watchdog );
|
( *routine )( first );
|
||||||
_ISR_lock_ISR_disable_and_acquire( lock, lock_context );
|
_ISR_lock_ISR_disable_and_acquire( lock, lock_context );
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
_ISR_lock_Release_and_ISR_enable( lock, lock_context );
|
first = _Watchdog_Header_first( header );
|
||||||
|
} while ( first != NULL );
|
||||||
}
|
}
|
||||||
|
|
||||||
void _Watchdog_Tick( Per_CPU_Control *cpu )
|
void _Watchdog_Tick( Per_CPU_Control *cpu )
|
||||||
{
|
{
|
||||||
ISR_lock_Context lock_context;
|
ISR_lock_Context lock_context;
|
||||||
uint64_t ticks;
|
Watchdog_Header *header;
|
||||||
struct timespec now;
|
Watchdog_Control *first;
|
||||||
|
uint64_t ticks;
|
||||||
|
struct timespec now;
|
||||||
|
|
||||||
if ( _Per_CPU_Is_boot_processor( cpu ) ) {
|
if ( _Per_CPU_Is_boot_processor( cpu ) ) {
|
||||||
++_Watchdog_Ticks_since_boot;
|
++_Watchdog_Ticks_since_boot;
|
||||||
@@ -75,18 +70,34 @@ void _Watchdog_Tick( Per_CPU_Control *cpu )
|
|||||||
++ticks;
|
++ticks;
|
||||||
cpu->Watchdog.ticks = ticks;
|
cpu->Watchdog.ticks = ticks;
|
||||||
|
|
||||||
_Watchdog_Tickle(
|
header = &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_MONOTONIC ];
|
||||||
&cpu->Watchdog.Header[ PER_CPU_WATCHDOG_MONOTONIC ],
|
first = _Watchdog_Header_first( header );
|
||||||
ticks,
|
|
||||||
&cpu->Watchdog.Lock,
|
|
||||||
&lock_context
|
|
||||||
);
|
|
||||||
|
|
||||||
_Timecounter_Getnanotime( &now );
|
if ( first != NULL ) {
|
||||||
_Watchdog_Per_CPU_tickle_realtime(
|
_Watchdog_Tickle(
|
||||||
cpu,
|
header,
|
||||||
_Watchdog_Realtime_from_timespec( &now )
|
first,
|
||||||
);
|
ticks,
|
||||||
|
&cpu->Watchdog.Lock,
|
||||||
|
&lock_context
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
header = &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_REALTIME ];
|
||||||
|
first = _Watchdog_Header_first( header );
|
||||||
|
|
||||||
|
if ( first != NULL ) {
|
||||||
|
_Timecounter_Getnanotime( &now );
|
||||||
|
_Watchdog_Tickle(
|
||||||
|
header,
|
||||||
|
first,
|
||||||
|
_Watchdog_Realtime_from_timespec( &now ),
|
||||||
|
&cpu->Watchdog.Lock,
|
||||||
|
&lock_context
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
_ISR_lock_Release_and_ISR_enable( &cpu->Watchdog.Lock, &lock_context );
|
||||||
|
|
||||||
_Scheduler_Tick( cpu );
|
_Scheduler_Tick( cpu );
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,10 +82,18 @@ static uint64_t test_watchdog_tick( Watchdog_Header *header, uint64_t now )
|
|||||||
{
|
{
|
||||||
ISR_LOCK_DEFINE( , lock, "Test" )
|
ISR_LOCK_DEFINE( , lock, "Test" )
|
||||||
ISR_lock_Context lock_context;
|
ISR_lock_Context lock_context;
|
||||||
|
Watchdog_Control *first;
|
||||||
|
|
||||||
_ISR_lock_ISR_disable_and_acquire( &lock, &lock_context );
|
_ISR_lock_ISR_disable_and_acquire( &lock, &lock_context );
|
||||||
|
|
||||||
++now;
|
++now;
|
||||||
_Watchdog_Tickle( header, now, &lock, &lock_context );
|
first = _Watchdog_Header_first( header );
|
||||||
|
|
||||||
|
if ( first != NULL ) {
|
||||||
|
_Watchdog_Tickle( header, first, now, &lock, &lock_context );
|
||||||
|
}
|
||||||
|
|
||||||
|
_ISR_lock_Release_and_ISR_enable( &lock, &lock_context );
|
||||||
_ISR_lock_Destroy( &lock );
|
_ISR_lock_Destroy( &lock );
|
||||||
|
|
||||||
return now;
|
return now;
|
||||||
|
|||||||
Reference in New Issue
Block a user