Skip to content

Commit

Permalink
hw: generalize IPC-helping to a common mechanism
Browse files Browse the repository at this point in the history
* Removes helping from Ipc_node and Thread class
* Implement helping as mechanism of Scheduler::Context

Ref genodelabs#5318
  • Loading branch information
skalk committed Aug 13, 2024
1 parent a5db994 commit ec5ad80
Show file tree
Hide file tree
Showing 10 changed files with 82 additions and 113 deletions.
6 changes: 3 additions & 3 deletions repos/base-hw/src/core/kernel/cpu.cc
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@ using namespace Kernel;
** Cpu_job **
*************/

void Cpu_job::_activate_own_share() { _cpu->schedule(this); }
void Cpu_job::_activate() { _cpu->schedule(this); }


void Cpu_job::_deactivate_own_share()
void Cpu_job::_deactivate()
{
assert(_cpu->id() == Cpu::executing_id());
_cpu->scheduler().unready(*this);
Expand Down Expand Up @@ -124,7 +124,7 @@ Cpu::Idle_thread::Idle_thread(Board::Address_space_id_allocator &addr_space_id_a

void Cpu::schedule(Job * const job)
{
_scheduler.ready(job->context());
_scheduler.ready(*static_cast<Scheduler::Context*>(job));
if (_id != executing_id() && _scheduler.need_to_schedule())
trigger_ip_interrupt();
}
Expand Down
5 changes: 1 addition & 4 deletions repos/base-hw/src/core/kernel/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,7 @@ class Kernel::Cpu : public Core::Cpu, private Irq::Pool,
Halt_job() : Job (0, 0) { }

void exception(Kernel::Cpu &) override { }

void proceed(Kernel::Cpu &) override;

Kernel::Cpu_job* helping_destination() override { return this; }
} _halt_job { };

enum State { RUN, HALT, SUSPEND };
Expand Down Expand Up @@ -161,7 +158,7 @@ class Kernel::Cpu : public Core::Cpu, private Irq::Pool,
* Returns the currently active job
*/
Job & scheduled_job() {
return *static_cast<Job *>(&_scheduler.current())->helping_destination(); }
return static_cast<Job&>(_scheduler.current().helping_destination()); }

unsigned id() const { return _id; }
Scheduler &scheduler() { return _scheduler; }
Expand Down
21 changes: 7 additions & 14 deletions repos/base-hw/src/core/kernel/cpu_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,12 @@ class Kernel::Cpu_job : private Scheduler::Context
/**
* Activate our own CPU-share
*/
void _activate_own_share();
void _activate();

/**
* Deactivate our own CPU-share
*/
void _deactivate_own_share();
void _deactivate();

/**
* Yield the currently scheduled CPU share of this context
Expand All @@ -73,6 +73,11 @@ class Kernel::Cpu_job : private Scheduler::Context
*/
bool _helping_possible(Cpu_job const &j) const { return j._cpu == _cpu; }

using Context::ready;
using Context::helping_finished;

void help(Cpu_job &job) { Context::help(job); }

public:

using Context = Scheduler::Context;
Expand All @@ -88,11 +93,6 @@ class Kernel::Cpu_job : private Scheduler::Context
*/
virtual void proceed(Cpu & cpu) = 0;

/**
* Return which job currently uses our CPU-share
*/
virtual Cpu_job * helping_destination() = 0;

/**
* Construct a job with scheduling priority 'p' and time quota 'q'
*/
Expand All @@ -113,11 +113,6 @@ class Kernel::Cpu_job : private Scheduler::Context
*/
void quota(unsigned const q);

/**
* Return wether our CPU-share is currently active
*/
bool own_share_active() { return Context::ready(); }

/**
* Update total execution time
*/
Expand All @@ -134,8 +129,6 @@ class Kernel::Cpu_job : private Scheduler::Context
***************/

void cpu(Cpu &cpu) { _cpu = &cpu; }

Context &context() { return *this; }
};

#endif /* _CORE__KERNEL__CPU_CONTEXT_H_ */
16 changes: 2 additions & 14 deletions repos/base-hw/src/core/kernel/ipc_node.cc
Original file line number Diff line number Diff line change
Expand Up @@ -57,19 +57,13 @@ void Ipc_node::_cancel_send()
}


bool Ipc_node::_helping() const
{
return _out.state == Out::SEND_HELPING && _out.node;
}


bool Ipc_node::ready_to_send() const
{
return _out.state == Out::READY && !_in.waiting();
}


void Ipc_node::send(Ipc_node &node, bool help)
void Ipc_node::send(Ipc_node &node)
{
node._in.queue.enqueue(_queue_item);

Expand All @@ -78,13 +72,7 @@ void Ipc_node::send(Ipc_node &node, bool help)
node._thread.ipc_await_request_succeeded();
}
_out.node = &node;
_out.state = help ? Out::SEND_HELPING : Out::SEND;
}


Thread &Ipc_node::helping_destination()
{
return _helping() ? _out.node->helping_destination() : _thread;
_out.state = Out::SEND;
}


Expand Down
31 changes: 3 additions & 28 deletions repos/base-hw/src/core/kernel/ipc_node.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,14 @@ class Kernel::Ipc_node

struct Out
{
enum State { READY, SEND, SEND_HELPING, DESTRUCT };
enum State { READY, SEND, DESTRUCT };

State state { READY };
Ipc_node *node { nullptr };

bool sending() const
{
return state == SEND_HELPING || state == SEND;
return state == SEND;
}
};

Expand All @@ -76,11 +76,6 @@ class Kernel::Ipc_node
*/
void _cancel_send();

/**
* Return wether this IPC node is helping another one
*/
bool _helping() const;

/**
* Noncopyable
*/
Expand All @@ -102,28 +97,8 @@ class Kernel::Ipc_node
* Send a message and wait for the according reply
*
* \param node targeted IPC node
* \param help wether the request implies a helping relationship
*/
void send(Ipc_node &node, bool help);

/**
* Return final destination of the helping-chain
* this IPC node is part of, or its own thread otherwise
*/
Thread &helping_destination();

/**
* Call 'fn' of type 'void (Ipc_node *)' for each helper
*/
void for_each_helper(auto const &fn)
{
_in.queue.for_each([fn] (Queue_item &item) {
Ipc_node &node { item.object() };

if (node._helping())
fn(node._thread);
});
}
void send(Ipc_node &node);

/**
* Return whether this IPC node is ready to wait for messages
Expand Down
48 changes: 42 additions & 6 deletions repos/base-hw/src/core/kernel/scheduler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,29 @@
using namespace Kernel;


void Scheduler::Context::help(Scheduler::Context &c)
{
_destination = &c;
c._helper_list.insert(&_helper_le);
}


void Scheduler::Context::helping_finished()
{
if (!_destination)
return;

_destination->_helper_list.remove(&_helper_le);
_destination = nullptr;
}


Scheduler::Context& Scheduler::Context::helping_destination()
{
return (_destination) ? _destination->helping_destination() : *this;
}


void Scheduler::_consumed(unsigned const time)
{
if (_super_period_left > time) {
Expand Down Expand Up @@ -149,7 +172,10 @@ void Scheduler::update(time_t time)

void Scheduler::ready(Context &c)
{
assert(!c.ready() && &c != &_idle);
assert(&c != &_idle);

if (c.ready())
return;

c._ready = true;

Expand All @@ -170,23 +196,33 @@ void Scheduler::ready(Context &c)
_slack_list.insert_head(&c._slack_le);

if (!keep_current && _state == UP_TO_DATE) _state = OUT_OF_DATE;

for (Context::List_element *helper = c._helper_list.first();
helper; helper = helper->next())
if (!helper->object()->ready()) ready(*helper->object());
}


void Scheduler::unready(Context &c)
{
assert(c.ready() && &c != &_idle);
assert(&c != &_idle);

if (!c.ready())
return;

if (&c == _current && _state == UP_TO_DATE) _state = OUT_OF_DATE;

c._ready = false;
_slack_list.remove(&c._slack_le);

if (!c._quota)
return;
if (c._quota) {
_rpl[c._priority].remove(&c._priotized_le);
_upl[c._priority].insert_tail(&c._priotized_le);
}

_rpl[c._priority].remove(&c._priotized_le);
_upl[c._priority].insert_tail(&c._priotized_le);
for (Context::List_element *helper = c._helper_list.first();
helper; helper = helper->next())
if (helper->object()->ready()) unready(*helper->object());
}


Expand Down
9 changes: 9 additions & 0 deletions repos/base-hw/src/core/kernel/scheduler.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ class Kernel::Scheduler
friend class Scheduler_test::Context;

using List_element = Genode::List_element<Context>;
using List = Genode::List<List_element>;

unsigned _priority;
unsigned _quota;
Expand All @@ -74,6 +75,10 @@ class Kernel::Scheduler
List_element _slack_le { this };
unsigned _slack_time_left { 0 };

List_element _helper_le { this };
List _helper_list {};
Context *_destination { nullptr };

bool _ready { false };

void _reset() { _priotized_time_left = _quota; }
Expand All @@ -88,6 +93,10 @@ class Kernel::Scheduler

bool ready() const { return _ready; }
void quota(unsigned const q) { _quota = q; }

void help(Context &c);
void helping_finished();
Context& helping_destination();
};

private:
Expand Down
Loading

0 comments on commit ec5ad80

Please sign in to comment.