lx_emul: stop ticking in idle task

Fixes #4540
This commit is contained in:
Alexander Boettcher 2022-06-17 15:14:25 +02:00 committed by Christian Helmuth
parent d27c504261
commit a23f6209ae
9 changed files with 47 additions and 0 deletions

View File

@ -44,6 +44,8 @@ void lx_emul_task_name(struct task_struct * task, const char * name);
void *lx_emul_task_stack(struct task_struct const * task);
char lx_emul_task_another_runnable(void);
#ifdef __cplusplus
}
#endif

View File

@ -45,6 +45,8 @@ class Lx_kit::Scheduler
void unblock_irq_handler();
void unblock_time_handler();
bool another_runnable(Task *);
Task & task(void * t);
template <typename FN>

View File

@ -64,6 +64,7 @@ try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags)
lx_emul_task_unblock(p);
p->__state = TASK_RUNNING;
return 1;
}

View File

@ -13,6 +13,7 @@
#include <linux/interrupt.h>
#include <linux/bottom_half.h>
#include <linux/tick.h>
#define CREATE_TRACE_POINTS
#include <trace/events/irq.h>

View File

@ -17,6 +17,7 @@
#include <linux/of_irq.h>
#include <linux/slab.h>
#include <linux/irqchip.h>
#include <linux/tick.h>
#include <../kernel/irq/internals.h>
static int dde_irq_set_wake(struct irq_data *d, unsigned int on)
@ -174,6 +175,9 @@ int lx_emul_irq_task_function(void * data)
if (!dde_irq_domain)
continue;
/* check restarting ticking which may stopped in idle task */
tick_nohz_idle_restart_tick();
irq_enter();
irq = irq_find_mapping(dde_irq_domain, lx_emul_irq_last());

View File

@ -15,6 +15,7 @@
#include <lx_emul/irq.h>
#include <linux/irq.h>
#include <linux/irqchip.h>
#include <linux/tick.h>
#include <../kernel/irq/internals.h>
@ -46,6 +47,9 @@ int lx_emul_irq_task_function(void * data)
for (;;) {
lx_emul_task_schedule(true);
/* check restarting ticking which may stopped in idle task */
tick_nohz_idle_restart_tick();
irq_enter();
irq = lx_emul_irq_last();

View File

@ -73,8 +73,16 @@ static void timer_loop(void)
{
for (;;) {
tick_nohz_idle_enter();
if (!lx_emul_task_another_runnable())
tick_nohz_idle_stop_tick();
lx_emul_task_schedule(true);
lx_emul_time_handle();
/* check restarting ticking */
tick_nohz_idle_restart_tick();
tick_nohz_idle_exit();
}
}

View File

@ -100,3 +100,11 @@ extern "C" void * lx_emul_task_stack(struct task_struct const * t)
return ret;
}
extern "C" char lx_emul_task_another_runnable()
{
Lx_kit::Task & task = Lx_kit::env().scheduler.current();
return Lx_kit::env().scheduler.another_runnable(&task);
}

View File

@ -127,3 +127,20 @@ void Scheduler::schedule()
/* clear current as no task is running */
_current = nullptr;
}
bool Scheduler::another_runnable(Task * skip)
{
for (Task * t = _present_list.first(); t; t = t->next()) {
if (!t->runnable())
continue;
if (skip && t == skip)
continue;
return true;
};
return false;
}