diff --git a/repos/dde_linux/src/app/wireguard/main.cc b/repos/dde_linux/src/app/wireguard/main.cc
index 805bcc6590..98a880cc07 100644
--- a/repos/dde_linux/src/app/wireguard/main.cc
+++ b/repos/dde_linux/src/app/wireguard/main.cc
@@ -59,7 +59,7 @@ class Wireguard::Main : private Entrypoint::Io_progress_handler,
void _handle_signal()
{
lx_user_handle_io();
- Lx_kit::env().scheduler.schedule();
+ Lx_kit::env().scheduler.execute();
}
void _handle_config() { _config_rom.update(); }
diff --git a/repos/dde_linux/src/include/lx_kit/scheduler.h b/repos/dde_linux/src/include/lx_kit/scheduler.h
index 3e2e12aebf..d0ba22f2e5 100644
--- a/repos/dde_linux/src/include/lx_kit/scheduler.h
+++ b/repos/dde_linux/src/include/lx_kit/scheduler.h
@@ -14,6 +14,7 @@
* version 2.
*/
+#include
#include
#include
@@ -29,14 +30,21 @@ class Lx_kit::Scheduler
{
private:
+ Scheduler(Scheduler const &) = delete;
+ Scheduler& operator=(const Scheduler&) = delete;
+
List _present_list { };
Task * _current { nullptr };
Task * _idle { nullptr };
- Genode::Entrypoint &ep;
+ Genode::Entrypoint &_ep;
void _idle_pre_post_process();
+ void _schedule();
+
+ Signal_handler _execute_schedule;
+
public:
Task & current();
@@ -48,7 +56,10 @@ class Lx_kit::Scheduler
void add(Task & task);
void remove(Task & task);
- void schedule();
+ void schedule() { _execute_schedule.local_submit(); }
+
+ void execute();
+
void unblock_irq_handler();
void unblock_time_handler();
@@ -57,7 +68,12 @@ class Lx_kit::Scheduler
template
void for_each_task(FN const & fn);
- Scheduler(Genode::Entrypoint &ep) : ep(ep) { }
+ Scheduler(Genode::Entrypoint &ep)
+ :
+ _ep { ep },
+ _execute_schedule { _ep, *this,
+ &Scheduler::_schedule }
+ { }
};
diff --git a/repos/dde_linux/src/lib/lx_emul/init.cc b/repos/dde_linux/src/lib/lx_emul/init.cc
index 92dc85e743..8ede087777 100644
--- a/repos/dde_linux/src/lib/lx_emul/init.cc
+++ b/repos/dde_linux/src/lib/lx_emul/init.cc
@@ -65,9 +65,16 @@ extern "C" void lx_emul_start_kernel(void * dtb)
extern "C" void lx_emul_execute_kernel_until(int (*condition)(void*), void * args)
{
- Lx_kit::env().scheduler.schedule();
+ do {
+ /*
+ * Assume we have to execute all scheduled tasks once before
+ * it makes sense to check the condition.
+ */
+ Lx_kit::env().scheduler.execute();
+
+ if (condition(args))
+ break;
- while (!condition(args)) {
Lx_kit::env().env.ep().wait_and_dispatch_one_io_signal();
- }
+ } while (true);
}
diff --git a/repos/dde_linux/src/lib/lx_kit/scheduler.cc b/repos/dde_linux/src/lib/lx_kit/scheduler.cc
index 187c8f4531..001cc039e4 100644
--- a/repos/dde_linux/src/lib/lx_kit/scheduler.cc
+++ b/repos/dde_linux/src/lib/lx_kit/scheduler.cc
@@ -101,11 +101,11 @@ Task & Scheduler::task(void * lx_task)
}
-void Scheduler::schedule()
+void Scheduler::execute()
{
/* sanity check that right thread & stack is in use */
auto const thread = Genode::Thread::myself();
- if (!ep.rpc_ep().myself(addr_t(&thread))) {
+ if (!_ep.rpc_ep().myself(addr_t(&thread))) {
Genode::error("Lx_kit::Scheduler called by invalid thread/stack ",
thread->name(), " ",
Genode::Hex(thread->mystack().base), "-",
@@ -114,6 +114,16 @@ void Scheduler::schedule()
Genode::sleep_forever();
}
+ _schedule();
+}
+
+
+/*
+ * This signal handler function must only be called from within an EP
+ * context, see check in 'execute()'.
+ */
+void Scheduler::_schedule()
+{
_idle_pre_post_process();
/*
diff --git a/repos/dde_linux/src/lib/wifi/socket_call.cc b/repos/dde_linux/src/lib/wifi/socket_call.cc
index 353027155b..65aed725f7 100644
--- a/repos/dde_linux/src/lib/wifi/socket_call.cc
+++ b/repos/dde_linux/src/lib/wifi/socket_call.cc
@@ -415,7 +415,7 @@ class Lx::Socket
void _handle()
{
lx_emul_task_unblock(socketcall_task_struct_ptr);
- Lx_kit::env().scheduler.schedule();
+ Lx_kit::env().scheduler.execute();
}
void _handle_blockade()
@@ -511,7 +511,7 @@ void wifi_kick_socketcall()
if (!_socket) { return; }
lx_emul_task_unblock(socketcall_task_struct_ptr);
- Lx_kit::env().scheduler.schedule();
+ Lx_kit::env().scheduler.execute();
}
diff --git a/repos/dde_linux/src/lib/wifi/wlan.cc b/repos/dde_linux/src/lib/wifi/wlan.cc
index 26056ca4cd..a74fab8be5 100644
--- a/repos/dde_linux/src/lib/wifi/wlan.cc
+++ b/repos/dde_linux/src/lib/wifi/wlan.cc
@@ -79,7 +79,7 @@ void Wifi::set_rfkill(bool blocked)
lx_emul_rfkill_switch_all(blocked);
lx_emul_task_unblock(rfkill_task_struct_ptr);
- Lx_kit::env().scheduler.schedule();
+ Lx_kit::env().scheduler.execute();
/*
* We have to open the device again after unblocking
@@ -88,7 +88,7 @@ void Wifi::set_rfkill(bool blocked)
* unconditionally and that will bring the netdevice UP again.
*/
lx_emul_task_unblock(uplink_task_struct_ptr);
- Lx_kit::env().scheduler.schedule();
+ Lx_kit::env().scheduler.execute();
if (rfkill_helper.constructed())
rfkill_helper->submit_notification();
@@ -120,7 +120,7 @@ struct Firmware_helper
if (_calling_task)
lx_emul_task_unblock((struct task_struct*)_calling_task);
- Lx_kit::env().scheduler.schedule();
+ Lx_kit::env().scheduler.execute();
}
Wifi::Firmware_request_handler &_request_handler;
diff --git a/repos/pc/src/drivers/framebuffer/intel/pc/main.cc b/repos/pc/src/drivers/framebuffer/intel/pc/main.cc
index 678d5ae4f0..9aeb82e288 100644
--- a/repos/pc/src/drivers/framebuffer/intel/pc/main.cc
+++ b/repos/pc/src/drivers/framebuffer/intel/pc/main.cc
@@ -177,7 +177,7 @@ void Framebuffer::Driver::config_update()
update_in_progress = true;
lx_emul_task_unblock(lx_user_task);
- Lx_kit::env().scheduler.schedule();
+ Lx_kit::env().scheduler.execute();
}
diff --git a/repos/pc/src/drivers/usb_host/pc/main.cc b/repos/pc/src/drivers/usb_host/pc/main.cc
index 5832f2d8e7..34d068c2b7 100644
--- a/repos/pc/src/drivers/usb_host/pc/main.cc
+++ b/repos/pc/src/drivers/usb_host/pc/main.cc
@@ -61,7 +61,7 @@ struct Main : private Entrypoint::Io_progress_handler
void handle_signal()
{
lx_user_handle_io();
- Lx_kit::env().scheduler.schedule();
+ Lx_kit::env().scheduler.execute();
}
Main(Env & env) : env(env)