mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-22 06:57:51 +00:00
lx_kit: decouple schedule execution
Prior to this commit, whenever an external event occurred, for example timer or interrupt, the corresponding I/O signal handler was triggered. This handler unblocked the task waiting for the event and initiated the immediate execution of all unblocked tasks. Since these tasks may hit serialization points, e.g. synchronously waiting for packet stream operations, that require handling of other I/O signals this leads to nested execution. This, however, is not supported and mixes application and I/O level signal handling. The flagging of the scheduling intent is now decoupled from its execution by using an application level signal handler that is run in the context of the components main entrypoint. The I/O signal handler now triggers the scheduling execution by sending a local signal to the EP. Since it might be necessary to execute a pending schedule from the EP directly the scheduler is extended with the 'execute' member function that performs the check that the scheduler is called from within the EP and triggers the execution afterwards. Issue #4927.
This commit is contained in:
parent
1f1fafb0cf
commit
caac994da8
@ -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(); }
|
||||
|
@ -14,6 +14,7 @@
|
||||
* version 2.
|
||||
*/
|
||||
|
||||
#include <base/entrypoint.h>
|
||||
#include <util/list.h>
|
||||
#include <lx_kit/task.h>
|
||||
|
||||
@ -29,14 +30,21 @@ class Lx_kit::Scheduler
|
||||
{
|
||||
private:
|
||||
|
||||
Scheduler(Scheduler const &) = delete;
|
||||
Scheduler& operator=(const Scheduler&) = delete;
|
||||
|
||||
List<Task> _present_list { };
|
||||
Task * _current { nullptr };
|
||||
Task * _idle { nullptr };
|
||||
|
||||
Genode::Entrypoint &ep;
|
||||
Genode::Entrypoint &_ep;
|
||||
|
||||
void _idle_pre_post_process();
|
||||
|
||||
void _schedule();
|
||||
|
||||
Signal_handler<Scheduler> _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 <typename FN>
|
||||
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 }
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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();
|
||||
|
||||
/*
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user