bsps/clock: Fix fast idle clock tick support

If we interrupt a thread dispatch critical section (thread dispatch
disable level != ISR nest level), then we should not do the fast idle
mode since this may delay an ongoing system call forever.
This commit is contained in:
Sebastian Huber
2020-07-23 08:42:59 +02:00
parent 1fab9726c9
commit 33314eb60a
2 changed files with 22 additions and 9 deletions

View File

@@ -98,15 +98,21 @@ void clockOn(void* unused)
static void clockHandler(void) static void clockHandler(void)
{ {
#if (CLOCK_DRIVER_USE_FAST_IDLE == 1) #if (CLOCK_DRIVER_USE_FAST_IDLE == 1)
rtems_interrupt_level level; rtems_interrupt_level level;
uint32_t tb; uint32_t tb;
Per_CPU_Control *cpu_self;
rtems_interrupt_disable(level); rtems_interrupt_disable(level);
tb = ppc_time_base(); tb = ppc_time_base();
rtems_timecounter_tick(); rtems_timecounter_tick();
cpu_self = _Per_CPU_Get();
while ( _Thread_Heir == _Thread_Executing && _Thread_Executing->is_idle ) { while (
cpu_self->thread_dispatch_disable_level == cpu_self->isr_nest_level
&& cpu_self->heir == cpu_self->executing
&& cpu_self->executing->is_idle
) {
tb += Clock_Decrementer_value; tb += Clock_Decrementer_value;
ppc_set_time_base( tb ); ppc_set_time_base( tb );
rtems_timecounter_tick(); rtems_timecounter_tick();

View File

@@ -143,16 +143,23 @@ rtems_isr Clock_isr(
#if CLOCK_DRIVER_USE_FAST_IDLE #if CLOCK_DRIVER_USE_FAST_IDLE
{ {
struct timecounter *tc = _Timecounter;
uint64_t us_per_tick = rtems_configuration_get_microseconds_per_tick();
uint32_t interval = (uint32_t)
((tc->tc_frequency * us_per_tick) / 1000000);
Clock_driver_timecounter_tick(); Clock_driver_timecounter_tick();
if (_SMP_Get_processor_maximum() == 1) { if (_SMP_Get_processor_maximum() == 1) {
struct timecounter *tc;
uint64_t us_per_tick;
uint32_t interval;
Per_CPU_Control *cpu_self;
cpu_self = _Per_CPU_Get();
tc = _Timecounter;
us_per_tick = rtems_configuration_get_microseconds_per_tick();
interval = (uint32_t) ((tc->tc_frequency * us_per_tick) / 1000000);
while ( while (
_Thread_Heir == _Thread_Executing && _Thread_Executing->is_idle cpu_self->thread_dispatch_disable_level == cpu_self->isr_nest_level
&& cpu_self->heir == cpu_self->executing
&& cpu_self->executing->is_idle
) { ) {
ISR_lock_Context lock_context; ISR_lock_Context lock_context;