hw: pager thread per cpu

Instatiate a separate pager thread for each cpu core. Every time a pager
object gets managed by the Pager_entrypoint, assign it to the pager thread
on the same cpu core.

Ref genodelabs/genode#5318
This commit is contained in:
Stefan Kalkowski 2024-08-19 09:51:19 +02:00 committed by Christian Helmuth
parent ae1e4918a7
commit fd78fb4de3
4 changed files with 86 additions and 31 deletions

View File

@ -22,6 +22,16 @@
using namespace Core;
static unsigned _nr_of_cpus = 0;
static void *_pager_thread_memory = nullptr;
void Core::init_pager_thread_per_cpu_memory(unsigned const cpus, void * mem)
{
_nr_of_cpus = cpus;
_pager_thread_memory = mem;
}
void Core::init_page_fault_handling(Rpc_entrypoint &) { }
@ -78,11 +88,12 @@ void Pager_object::print(Output &out) const
Pager_object::Pager_object(Cpu_session_capability cpu_session_cap,
Thread_capability thread_cap, addr_t const badge,
Affinity::Location, Session_label const &,
Affinity::Location location, Session_label const &,
Cpu_session::Name const &)
:
Object_pool<Pager_object>::Entry(Kernel_object<Kernel::Signal_context>::_cap),
_badge(badge), _cpu_session_cap(cpu_session_cap), _thread_cap(thread_cap)
_badge(badge), _location(location),
_cpu_session_cap(cpu_session_cap), _thread_cap(thread_cap)
{ }
@ -90,27 +101,46 @@ Pager_object::Pager_object(Cpu_session_capability cpu_session_cap,
** Pager_entrypoint **
**********************/
void Pager_entrypoint::dissolve(Pager_object &o)
{
Kernel::kill_signal_context(Capability_space::capid(o.cap()));
remove(&o);
}
Pager_entrypoint::Pager_entrypoint(Rpc_cap_factory &)
Pager_entrypoint::Thread::Thread(Affinity::Location cpu)
:
Thread(Weight::DEFAULT_WEIGHT, "pager_ep", PAGER_EP_STACK_SIZE,
Type::NORMAL),
Genode::Thread(Weight::DEFAULT_WEIGHT, "pager_ep", PAGER_EP_STACK_SIZE, cpu),
_kobj(_kobj.CALLED_FROM_CORE)
{
start();
}
void Pager_entrypoint::dissolve(Pager_object &o)
{
Kernel::kill_signal_context(Capability_space::capid(o.cap()));
unsigned const cpu = o.location().xpos();
if (cpu >= _cpus)
error("Invalid location of pager object ", cpu);
else
_threads[cpu].remove(&o);
}
Pager_capability Pager_entrypoint::manage(Pager_object &o)
{
o.start_paging(_kobj);
insert(&o);
unsigned const cpu = o.location().xpos();
if (cpu >= _cpus) {
error("Invalid location of pager object ", cpu);
} else {
o.start_paging(_threads[cpu]._kobj);
_threads[cpu].insert(&o);
}
return reinterpret_cap_cast<Pager_object>(o.cap());
}
Pager_entrypoint::Pager_entrypoint(Rpc_cap_factory &)
:
_cpus(_nr_of_cpus),
_threads((Thread*)_pager_thread_memory)
{
for (unsigned i = 0; i < _cpus; i++)
construct_at<Thread>((void*)&_threads[i], Affinity::Location(i, 0));
}

View File

@ -30,6 +30,8 @@
namespace Core {
class Platform;
/**
* Interface used by generic region_map code
*/
@ -55,6 +57,8 @@ namespace Core {
enum { PAGER_EP_STACK_SIZE = sizeof(addr_t) * 2048 };
extern void init_page_fault_handling(Rpc_entrypoint &);
void init_pager_thread_per_cpu_memory(unsigned const cpus, void * mem);
}
@ -104,6 +108,7 @@ class Core::Pager_object : private Object_pool<Pager_object>::Entry,
private:
unsigned long const _badge;
Affinity::Location _location;
Cpu_session_capability _cpu_session_cap;
Thread_capability _thread_cap;
@ -130,6 +135,8 @@ class Core::Pager_object : private Object_pool<Pager_object>::Entry,
*/
unsigned long badge() const { return _badge; }
Affinity::Location location() { return _location; }
/**
* Resume faulter
*/
@ -198,20 +205,40 @@ class Core::Pager_object : private Object_pool<Pager_object>::Entry,
};
class Core::Pager_entrypoint : public Object_pool<Pager_object>,
public Thread,
private Ipc_pager
class Core::Pager_entrypoint
{
private:
Kernel_object<Kernel::Signal_receiver> _kobj;
friend class Platform;
class Thread : public Object_pool<Pager_object>,
public Genode::Thread,
private Ipc_pager
{
private:
friend class Pager_entrypoint;
Kernel_object<Kernel::Signal_receiver> _kobj;
public:
explicit Thread(Affinity::Location);
/**********************
** Thread interface **
**********************/
void entry() override;
};
unsigned const _cpus;
Thread *_threads;
public:
/**
* Constructor
*/
Pager_entrypoint(Rpc_cap_factory &);
explicit Pager_entrypoint(Rpc_cap_factory &);
/**
* Associate pager object 'obj' with entry point
@ -222,13 +249,6 @@ class Core::Pager_entrypoint : public Object_pool<Pager_object>,
* Dissolve pager object 'obj' from entry point
*/
void dissolve(Pager_object &obj);
/**********************
** Thread interface **
**********************/
void entry() override;
};
#endif /* _CORE__PAGER_H_ */

View File

@ -19,6 +19,7 @@
/* base-hw core includes */
#include <map_local.h>
#include <pager.h>
#include <platform.h>
#include <platform_pd.h>
#include <kernel/main.h>
@ -253,6 +254,10 @@ Platform::Platform()
);
}
unsigned const cpus = _boot_info().cpus;
size_t size = cpus * sizeof(Pager_entrypoint::Thread);
init_pager_thread_per_cpu_memory(cpus, _core_mem_alloc.alloc(size));
class Idle_thread_trace_source : public Trace::Source::Info_accessor,
private Trace::Control,
private Trace::Source

View File

@ -20,7 +20,7 @@
using namespace Core;
void Pager_entrypoint::entry()
void Pager_entrypoint::Thread::entry()
{
Untyped_capability cap;