lx_emul: adjust start & stop tick behaviour

Do not start and stop idle ticking within the timer interrupt
routine, but do it around the whole Lx_kit scheduling, which
is always called when Linux code gets active again, either
because of backend signals, interrupts, or timing signals.

This commit implicitly reverts the (incomplete) solution of
issue 

Ref 
This commit is contained in:
Stefan Kalkowski 2023-02-28 13:00:46 +01:00 committed by Christian Helmuth
parent b9b18c92d0
commit 2c1724d7f2
7 changed files with 56 additions and 50 deletions
repos/dde_linux/src
include
lx_emul
lx_kit
lib

@ -44,9 +44,9 @@ 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);
void lx_emul_task_mark_for_removal(struct task_struct const * task);
void lx_emul_task_mark_for_removal(struct task_struct const * task);
void lx_emul_task_set_idle(void);
#ifdef __cplusplus
}

@ -31,13 +31,18 @@ class Lx_kit::Scheduler
List<Task> _present_list { };
Task * _current { nullptr };
Task * _idle { nullptr };
Genode::Entrypoint &ep;
void _idle_pre_post_process();
public:
Task & current();
void idle(Task & idle) { _idle = &idle; }
bool active() const;
void add(Task & task);
@ -47,8 +52,6 @@ class Lx_kit::Scheduler
void unblock_irq_handler();
void unblock_time_handler();
bool another_runnable(Task *);
Task & task(void * t);
template <typename FN>

@ -17,7 +17,6 @@
#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)
@ -173,9 +172,6 @@ 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());

@ -15,7 +15,6 @@
#include <lx_emul/irq.h>
#include <linux/irq.h>
#include <linux/irqchip.h>
#include <linux/tick.h>
#include <../kernel/irq/internals.h>
@ -53,9 +52,6 @@ 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();

@ -69,21 +69,39 @@ static int kernel_init(void * args)
}
static int kernel_idle(void * args)
{
struct task_struct *tsk = current;
set_task_comm(tsk, "idle");
/* set this current task to be the idle task */
lx_emul_task_set_idle();
/*
* Idle task always gets run in the end of each schedule
* and again at the beginning of each schedule
*/
for (;;) {
lx_emul_task_schedule(true);
tick_nohz_idle_enter();
tick_nohz_idle_stop_tick();
lx_emul_task_schedule(true);
tick_nohz_idle_restart_tick();
tick_nohz_idle_exit();
}
return 0;
}
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();
}
}
@ -125,6 +143,7 @@ int lx_emul_init_task_function(void * dtb)
sched_clock_init();
kernel_thread(kernel_init, NULL, CLONE_FS);
kernel_thread(kernel_idle, NULL, CLONE_FS);
pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES);
kthreadd_task = find_task_by_pid_ns(pid, NULL);;

@ -102,15 +102,13 @@ extern "C" void * lx_emul_task_stack(struct task_struct const * t)
}
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);
}
extern "C" void lx_emul_task_mark_for_removal(struct task_struct const *t)
{
Lx_kit::env().scheduler.task((void*)t).mark_for_destruction();
}
extern "C" void lx_emul_task_set_idle(void)
{
return Lx_kit::env().scheduler.idle(Lx_kit::env().scheduler.current());
}

@ -27,6 +27,16 @@
using namespace Genode;
using namespace Lx_kit;
void Scheduler::_idle_pre_post_process()
{
if (!_idle)
return;
_current = _idle;
_idle->run();
}
Task & Scheduler::current()
{
if (!_current) {
@ -104,6 +114,8 @@ void Scheduler::schedule()
Genode::sleep_forever();
}
_idle_pre_post_process();
/*
* Iterate over all tasks and run first runnable.
*
@ -116,9 +128,6 @@ void Scheduler::schedule()
while (true) {
bool at_least_one = false;
/* update jiffies before running task */
//Lx::timer_update_jiffies();
for (Task * t = _present_list.first(); t; ) {
Task *tmp = t;
@ -148,23 +157,8 @@ void Scheduler::schedule()
break;
}
_idle_pre_post_process();
/* 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;
}