Skip to content

Commit

Permalink
lx_kit: decouple schedule execution
Browse files Browse the repository at this point in the history
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 genodelabs#4927.
  • Loading branch information
cnuke committed Jun 16, 2023
1 parent 79e2629 commit 8b4896e
Show file tree
Hide file tree
Showing 8 changed files with 49 additions and 16 deletions.
2 changes: 1 addition & 1 deletion repos/dde_linux/src/app/wireguard/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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(); }
Expand Down
22 changes: 19 additions & 3 deletions repos/dde_linux/src/include/lx_kit/scheduler.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
* version 2.
*/

#include <base/entrypoint.h>
#include <util/list.h>
#include <lx_kit/task.h>

Expand All @@ -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();
Expand All @@ -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();

Expand All @@ -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 }
{ }
};


Expand Down
13 changes: 10 additions & 3 deletions repos/dde_linux/src/lib/lx_emul/init.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
14 changes: 12 additions & 2 deletions repos/dde_linux/src/lib/lx_kit/scheduler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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), "-",
Expand All @@ -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();

/*
Expand Down
4 changes: 2 additions & 2 deletions repos/dde_linux/src/lib/wifi/socket_call.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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();
}


Expand Down
6 changes: 3 additions & 3 deletions repos/dde_linux/src/lib/wifi/wlan.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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();
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion repos/pc/src/drivers/framebuffer/intel/pc/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}


Expand Down
2 changes: 1 addition & 1 deletion repos/pc/src/drivers/usb_host/pc/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit 8b4896e

Please sign in to comment.