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)