Skip to content

Commit

Permalink
hw: sanitze cpu context
Browse files Browse the repository at this point in the history
* Rename Kernel::Cpu_job to Kernel::Cpu_context (alias Kernel::Cpu::Context)
* State first Cpu affinity of Cpu::Context at construction time
* Move cpu affinity argument from kernel syscall create_thread to start_thread
* Ensure that Cpu pointer is always valid

Fix genodelabs#5319
  • Loading branch information
skalk committed Aug 13, 2024
1 parent b20ac9e commit abc73d9
Show file tree
Hide file tree
Showing 19 changed files with 269 additions and 288 deletions.
5 changes: 2 additions & 3 deletions repos/base-hw/src/core/kernel/core_interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,10 +137,9 @@ namespace Kernel {
* \retval 0 suceeded
* \retval !=0 failed
*/
inline int start_thread(Thread & thread, unsigned const cpu_id,
Pd & pd, Native_utcb & utcb)
inline int start_thread(Thread & thread, Pd & pd, Native_utcb & utcb)
{
return (int)call(call_id_start_thread(), (Call_arg)&thread, cpu_id,
return (int)call(call_id_start_thread(), (Call_arg)&thread,
(Call_arg)&pd, (Call_arg)&utcb);
}

Expand Down
85 changes: 41 additions & 44 deletions repos/base-hw/src/core/kernel/cpu.cc
Original file line number Diff line number Diff line change
Expand Up @@ -27,35 +27,35 @@
using namespace Kernel;


/*************
** Cpu_job **
*************/
/*****************
** Cpu_context **
*****************/

void Cpu_job::_activate() { _cpu->schedule(this); }
void Cpu_context::_activate() { _cpu().schedule(*this); }


void Cpu_job::_deactivate()
void Cpu_context::_deactivate()
{
assert(_cpu->id() == Cpu::executing_id());
_cpu->scheduler().unready(*this);
assert(_cpu().id() == Cpu::executing_id());
_cpu().scheduler().unready(*this);
}


void Cpu_job::_yield()
void Cpu_context::_yield()
{
assert(_cpu->id() == Cpu::executing_id());
_cpu->scheduler().yield();
assert(_cpu().id() == Cpu::executing_id());
_cpu().scheduler().yield();
}


void Cpu_job::_interrupt(Irq::Pool &user_irq_pool, unsigned const /* cpu_id */)
void Cpu_context::_interrupt(Irq::Pool &user_irq_pool)
{
/* let the IRQ controller take a pending IRQ for handling, if any */
unsigned irq_id;
if (_cpu->pic().take_request(irq_id))
if (_cpu().pic().take_request(irq_id))

/* let the CPU of this job handle the IRQ if it is a CPU-local one */
if (!_cpu->handle_if_cpu_local_interrupt(irq_id)) {
/* let the CPU of this context handle the IRQ if it is a CPU-local one */
if (!_cpu().handle_if_cpu_local_interrupt(irq_id)) {

/* it isn't a CPU-local IRQ, so, it must be a user IRQ */
User_irq * irq = User_irq::object(user_irq_pool, irq_id);
Expand All @@ -64,38 +64,37 @@ void Cpu_job::_interrupt(Irq::Pool &user_irq_pool, unsigned const /* cpu_id */)
}

/* let the IRQ controller finish the currently taken IRQ */
_cpu->pic().finish_request();
_cpu().pic().finish_request();
}


void Cpu_job::affinity(Cpu &cpu)
void Cpu_context::affinity(Cpu &cpu)
{
_cpu = &cpu;
_cpu->scheduler().insert(*this);
_cpu().scheduler().remove(*this);
_cpu_ptr = &cpu;
_cpu().scheduler().insert(*this);
}


void Cpu_job::quota(unsigned const q)
void Cpu_context::quota(unsigned const q)
{
if (_cpu)
_cpu->scheduler().quota(*this, q);
else
Context::quota(q);
_cpu().scheduler().quota(*this, q);
}


Cpu_job::Cpu_job(Priority const p, unsigned const q)
Cpu_context::Cpu_context(Cpu &cpu,
Priority const priority,
unsigned const quota)
:
Context(p, q), _cpu(0)
{ }
Context(priority, quota), _cpu_ptr(&cpu)
{
_cpu().scheduler().insert(*this);
}


Cpu_job::~Cpu_job()
Cpu_context::~Cpu_context()
{
if (!_cpu)
return;

_cpu->scheduler().remove(*this);
_cpu().scheduler().remove(*this);
}


Expand All @@ -112,19 +111,17 @@ Cpu::Idle_thread::Idle_thread(Board::Address_space_id_allocator &addr_space_id_a
Cpu &cpu,
Pd &core_pd)
:
Thread { addr_space_id_alloc, user_irq_pool, cpu_pool, core_pd,
Priority::min(), 0, "idle", Thread::IDLE }
Thread { addr_space_id_alloc, user_irq_pool, cpu_pool, cpu,
core_pd, Priority::min(), 0, "idle", Thread::IDLE }
{
regs->ip = (addr_t)&idle_thread_main;

affinity(cpu);
Thread::_pd = &core_pd;
}


void Cpu::schedule(Job * const job)
void Cpu::schedule(Context &context)
{
_scheduler.ready(*static_cast<Scheduler::Context*>(job));
_scheduler.ready(static_cast<Scheduler::Context&>(context));
if (_id != executing_id() && _scheduler.need_to_schedule())
trigger_ip_interrupt();
}
Expand All @@ -142,26 +139,26 @@ bool Cpu::handle_if_cpu_local_interrupt(unsigned const irq_id)
}


Cpu_job & Cpu::schedule()
Cpu::Context & Cpu::handle_exception_and_schedule()
{
/* update scheduler */
Job & old_job = scheduled_job();
old_job.exception(*this);
Context &context = current_context();
context.exception();

if (_state == SUSPEND || _state == HALT)
return _halt_job;

/* update schedule if necessary */
if (_scheduler.need_to_schedule()) {
_timer.process_timeouts();
_scheduler.update(_timer.time());
time_t t = _scheduler.current_time_left();
_timer.set_timeout(&_timeout, t);
time_t duration = _timer.schedule_timeout();
old_job.update_execution_time(duration);
context.update_execution_time(duration);
}

/* return new job */
return scheduled_job();
/* return current context */
return current_context();
}


Expand Down
31 changes: 17 additions & 14 deletions repos/base-hw/src/core/kernel/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,11 @@ namespace Kernel {
class Kernel::Cpu : public Core::Cpu, private Irq::Pool,
public Genode::List<Cpu>::Element
{
private:
public:

using Job = Cpu_job;
using Context = Cpu_context;

private:

/**
* Inter-processor-interrupt object of the cpu
Expand Down Expand Up @@ -83,13 +85,14 @@ class Kernel::Cpu : public Core::Cpu, private Irq::Pool,
Pd &core_pd);
};

struct Halt_job : Job
struct Halt_job : Cpu_context
{
Halt_job() : Job (0, 0) { }
Halt_job(Cpu &cpu)
: Cpu_context(cpu, 0, 0) { }

void exception(Kernel::Cpu &) override { }
void proceed(Kernel::Cpu &) override;
} _halt_job { };
void exception() override { }
void proceed() override;
} _halt_job { *this };

enum State { RUN, HALT, SUSPEND };

Expand Down Expand Up @@ -140,25 +143,25 @@ class Kernel::Cpu : public Core::Cpu, private Irq::Pool,
bool handle_if_cpu_local_interrupt(unsigned const irq_id);

/**
* Schedule 'job' at this CPU
* Schedule 'context' at this CPU
*/
void schedule(Job * const job);
void schedule(Context& context);

/**
* Return the job that should be executed at next
* Return the context that should be executed next
*/
Cpu_job& schedule();
Context& handle_exception_and_schedule();

Board::Pic & pic() { return _pic; }
Timer & timer() { return _timer; }

addr_t stack_start();

/**
* Returns the currently active job
* Returns the currently scheduled context
*/
Job & scheduled_job() {
return static_cast<Job&>(_scheduler.current().helping_destination()); }
Context & current_context() {
return static_cast<Context&>(_scheduler.current().helping_destination()); }

unsigned id() const { return _id; }
Scheduler &scheduler() { return _scheduler; }
Expand Down
79 changes: 31 additions & 48 deletions repos/base-hw/src/core/kernel/cpu_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,45 +22,38 @@
namespace Kernel {

class Cpu;

/**
* Context of a job (thread, VM, idle) that shall be executed by a CPU
*/
class Cpu_job;
class Cpu_context;
}


class Kernel::Cpu_job : private Scheduler::Context
/**
* Context (thread, vcpu) that shall be executed by a CPU
*/
class Kernel::Cpu_context : private Scheduler::Context
{
private:

friend class Cpu; /* static_cast from 'Scheduler::Context' to 'Cpu_job' */
friend class Cpu;

time_t _execution_time { 0 };
Cpu *_cpu_ptr;

/*
* Noncopyable
*/
Cpu_job(Cpu_job const &);
Cpu_job &operator = (Cpu_job const &);
Cpu_context(Cpu_context const &);
Cpu_context &operator = (Cpu_context const &);

protected:

Cpu * _cpu;
Cpu &_cpu() const { return *_cpu_ptr; }

/**
* Handle interrupt exception that occured during execution on CPU 'id'
* Handle interrupt exception
*/
void _interrupt(Irq::Pool &user_irq_pool, unsigned const id);
void _interrupt(Irq::Pool &user_irq_pool);

/**
* Activate our own CPU-share
*/
void _activate();

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

/**
Expand All @@ -69,47 +62,34 @@ class Kernel::Cpu_job : private Scheduler::Context
void _yield();

/**
* Return wether we are allowed to help job 'j' with our CPU-share
* Return possibility to help context 'j' scheduling-wise
*/
bool _helping_possible(Cpu_job const &j) const { return j._cpu == _cpu; }
bool _helping_possible(Cpu_context const &j) const {
return j._cpu_ptr == _cpu_ptr; }

void _help(Cpu_context &context) { Context::help(context); }

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

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

public:

using Context = Scheduler::Context;
using Priority = Scheduler::Priority;

/**
* Handle exception that occured during execution on CPU 'id'
*/
virtual void exception(Cpu & cpu) = 0;

/**
* Continue execution on CPU 'id'
*/
virtual void proceed(Cpu & cpu) = 0;

/**
* Construct a job with scheduling priority 'p' and time quota 'q'
*/
Cpu_job(Priority const p, unsigned const q);
Cpu_context(Cpu &cpu,
Priority const priority,
unsigned const quota);

/**
* Destructor
*/
virtual ~Cpu_job();
virtual ~Cpu_context();

/**
* Link job to CPU 'cpu'
* Link context to CPU 'cpu'
*/
void affinity(Cpu &cpu);

/**
* Set CPU quota of the job to 'q'
* Set CPU quota of the context to 'q'
*/
void quota(unsigned const q);

Expand All @@ -123,12 +103,15 @@ class Kernel::Cpu_job : private Scheduler::Context
*/
time_t execution_time() const { return _execution_time; }

/**
* Handle exception that occured during execution of this context
*/
virtual void exception() = 0;

/***************
** Accessors **
***************/

void cpu(Cpu &cpu) { _cpu = &cpu; }
/**
* Continue execution of this context
*/
virtual void proceed() = 0;
};

#endif /* _CORE__KERNEL__CPU_CONTEXT_H_ */
Loading

0 comments on commit abc73d9

Please sign in to comment.