mirror of
https://github.com/mmueller41/genode.git
synced 2026-01-21 12:32:56 +01:00
hoitaja: Added new CPU interface providing abstraction for task-parallelism.
This commit is contained in:
38
repos/os/include/suoritin/client.h
Normal file
38
repos/os/include/suoritin/client.h
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* \brief Suoritin - Task-based CPU Client Interface
|
||||||
|
* \author Michael Müller
|
||||||
|
* \date 2023-07-12
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2010-2020 Genode Labs GmbH
|
||||||
|
* Copyright (C) 2023 Michael Müller, Osnabrück University
|
||||||
|
*
|
||||||
|
* This file is part of EalánOS, which is distributed
|
||||||
|
* under the terms of the GNU Affero General Public License version 3.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <suoritin/session.h>
|
||||||
|
#include <base/rpc_client.h>
|
||||||
|
#include <base/affinity.h>
|
||||||
|
|
||||||
|
struct Tukija::Suoritin::Client : Genode::Rpc_client<Tukija::Suoritin::Session>
|
||||||
|
{
|
||||||
|
explicit Client(Genode::Capability<Tukija::Suoritin::Session> session)
|
||||||
|
: Rpc_client<Tukija::Suoritin::Session>(session) { }
|
||||||
|
|
||||||
|
void create_channel() override
|
||||||
|
{
|
||||||
|
call<Rpc_create_channel>();
|
||||||
|
}
|
||||||
|
|
||||||
|
void register_worker(Genode::Thread::Name const &name, Genode::Thread_capability cap) override
|
||||||
|
{
|
||||||
|
call<Rpc_register_worker>(name, cap);
|
||||||
|
}
|
||||||
|
|
||||||
|
Capability interface_cap() override {
|
||||||
|
return call<Rpc_suoritin_cap>();
|
||||||
|
}
|
||||||
|
};
|
||||||
46
repos/os/include/suoritin/connection.h
Normal file
46
repos/os/include/suoritin/connection.h
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* \brief Suoritin - Task-based CPU Connection
|
||||||
|
* \author Michael Müller
|
||||||
|
* \date 2023-07-12
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2010-2020 Genode Labs GmbH
|
||||||
|
* Copyright (C) 2023 Michael Müller, Osnabrück University
|
||||||
|
*
|
||||||
|
* This file is part of EalánOS, which is distributed
|
||||||
|
* under the terms of the GNU Affero General Public License version 3.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <suoritin/client.h>
|
||||||
|
#include <base/connection.h>
|
||||||
|
|
||||||
|
namespace Tukija {
|
||||||
|
namespace Suoritin {
|
||||||
|
struct Connection;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Tukija::Suoritin::Connection : Genode::Connection<Tukija::Suoritin::Session>, Tukija::Suoritin::Client
|
||||||
|
{
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
RAM_QUOTA = 32768UL
|
||||||
|
};
|
||||||
|
|
||||||
|
Connection(Genode::Env &env, const char *label="", Genode::Affinity const &affinity = Genode::Affinity())
|
||||||
|
: Genode::Connection<Tukija::Suoritin::Session>(env, session(env.parent(), affinity, "ram_quota=%u, cap_quota=%u, label=\"%s\"", RAM_QUOTA, CAP_QUOTA, label)), Tukija::Suoritin::Client(cap()) {}
|
||||||
|
|
||||||
|
void create_channel() override {
|
||||||
|
Tukija::Suoritin::Client::create_channel();
|
||||||
|
}
|
||||||
|
|
||||||
|
void register_worker(Genode::Thread::Name const &name, Genode::Thread_capability cap) override {
|
||||||
|
Tukija::Suoritin::Client::register_worker(name, cap);
|
||||||
|
}
|
||||||
|
|
||||||
|
Tukija::Suoritin::Capability interface_cap() override {
|
||||||
|
return Tukija::Suoritin::Client::interface_cap();
|
||||||
|
}
|
||||||
|
};
|
||||||
101
repos/os/include/suoritin/session.h
Normal file
101
repos/os/include/suoritin/session.h
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
/*
|
||||||
|
* \brief Suoritin - Task-based CPU Service
|
||||||
|
* \author Michael Müller
|
||||||
|
* \date 2023-07-12
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2010-2020 Genode Labs GmbH
|
||||||
|
* Copyright (C) 2023 Michael Müller, Osnabrück University
|
||||||
|
*
|
||||||
|
* This file is part of EalánOS, which is distributed
|
||||||
|
* under the terms of the GNU Affero General Public License version 3.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <session/session.h>
|
||||||
|
#include <base/affinity.h>
|
||||||
|
#include <base/registry.h>
|
||||||
|
#include <cpu_session/client.h>
|
||||||
|
|
||||||
|
namespace Tukija {
|
||||||
|
namespace Suoritin {
|
||||||
|
struct Session;
|
||||||
|
struct Client;
|
||||||
|
class Capability;
|
||||||
|
|
||||||
|
struct Channel;
|
||||||
|
struct Worker;
|
||||||
|
typedef Genode::Registry<Genode::Registered<Channel>> Channel_list;
|
||||||
|
typedef Genode::Registry<Genode::Registered<Worker>> Worker_registry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Tukija::Suoritin::Capability
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
Genode::Ram_dataspace_capability _worker_space;
|
||||||
|
Genode::Ram_dataspace_capability _channel_space;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Capability(Genode::Ram_dataspace_capability worker_space, Genode::Ram_dataspace_capability channel_space) : _worker_space(worker_space), _channel_space(channel_space) {}
|
||||||
|
|
||||||
|
Genode::Ram_dataspace_capability worker_interface() { return _worker_space; }
|
||||||
|
Genode::Ram_dataspace_capability channel_space() { return _channel_space; }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Tukija::Suoritin::Worker : Genode::Interface
|
||||||
|
{
|
||||||
|
Genode::Thread_capability _cap{};
|
||||||
|
Genode::Thread::Name _name{};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Tukija::Suoritin::Channel : Genode::Interface
|
||||||
|
{
|
||||||
|
unsigned long _id{0};
|
||||||
|
unsigned long _length{0};
|
||||||
|
unsigned long _occupancy{0};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Tukija::Suoritin::Session : Genode::Session
|
||||||
|
{
|
||||||
|
static const char *service_name() { return "TASKING"; }
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
CAP_QUOTA = 6
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief List of all channels, i.e. worker queues, of the client cell
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
Channel_list _channels{};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief List of worker threads for this client
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
Worker_registry _workers{};
|
||||||
|
|
||||||
|
virtual ~Session() { }
|
||||||
|
|
||||||
|
/************************
|
||||||
|
** internal interface **
|
||||||
|
************************/
|
||||||
|
Channel_list &channels() { return _channels; }
|
||||||
|
Worker_registry &workers() { return _workers; }
|
||||||
|
|
||||||
|
/********************************
|
||||||
|
** Suoritin session interface **
|
||||||
|
********************************/
|
||||||
|
virtual void create_channel() = 0;
|
||||||
|
virtual void register_worker(Genode::Thread::Name const &name, Genode::Thread_capability cap) = 0;
|
||||||
|
virtual Capability interface_cap() = 0;
|
||||||
|
|
||||||
|
GENODE_RPC(Rpc_create_channel, void, create_channel);
|
||||||
|
GENODE_RPC(Rpc_register_worker, void, register_worker, Genode::Thread::Name const&, Genode::Thread_capability);
|
||||||
|
GENODE_RPC(Rpc_suoritin_cap, Tukija::Suoritin::Capability, interface_cap);
|
||||||
|
|
||||||
|
GENODE_RPC_INTERFACE(Rpc_create_channel, Rpc_register_worker, Rpc_suoritin_cap);
|
||||||
|
};
|
||||||
131
repos/os/src/hoitaja/suoritin/component.cc
Normal file
131
repos/os/src/hoitaja/suoritin/component.cc
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
/* Genode includes */
|
||||||
|
#include <base/session_object.h>
|
||||||
|
#include <base/affinity.h>
|
||||||
|
#include <base/attached_dataspace.h>
|
||||||
|
#include <base/heap.h>
|
||||||
|
#include <base/session_object.h>
|
||||||
|
|
||||||
|
#include <suoritin/session.h>
|
||||||
|
#include <suoritin/client.h>
|
||||||
|
#include <suoritin/connection.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
namespace Tukija {
|
||||||
|
namespace Suoritin {
|
||||||
|
class Session_component;
|
||||||
|
template <class T> class Allocator;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
class Tukija::Suoritin::Allocator : public Genode::Allocator
|
||||||
|
{
|
||||||
|
using size_t = Genode::size_t;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Genode::Region_map::Local_addr _dataspace{};
|
||||||
|
size_t _interface_size;
|
||||||
|
Genode::Region_map::Local_addr _pos {_dataspace};
|
||||||
|
|
||||||
|
public:
|
||||||
|
Allocator(Genode::Env &env, Genode::Ram_dataspace_capability *_interface_cap, size_t interface_size) : _interface_size(interface_size)
|
||||||
|
{
|
||||||
|
*_interface_cap = env.ram().alloc(interface_size);
|
||||||
|
_dataspace = static_cast<T *>(env.rm().attach(*_interface_cap));
|
||||||
|
}
|
||||||
|
|
||||||
|
Alloc_result try_alloc(size_t) override
|
||||||
|
{
|
||||||
|
T *pos = _pos;
|
||||||
|
if (pos >= static_cast<T*>(_dataspace) + _interface_size)
|
||||||
|
return Alloc_result(Genode::Ram_allocator::Alloc_error::OUT_OF_RAM);
|
||||||
|
|
||||||
|
pos++;
|
||||||
|
return Alloc_result(static_cast<void *>(pos));
|
||||||
|
}
|
||||||
|
|
||||||
|
void free(void *, size_t) override
|
||||||
|
{ }
|
||||||
|
|
||||||
|
size_t overhead(size_t) const override { return 0; }
|
||||||
|
|
||||||
|
bool need_size_for_free() const override { return false; }
|
||||||
|
|
||||||
|
T *interface() { return _dataspace; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class Tukija::Suoritin::Session_component : public Genode::Session_object<Tukija::Suoritin::Session>
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
Genode::Affinity _affinity;
|
||||||
|
Genode::Env &_env;
|
||||||
|
Genode::Ram_dataspace_capability _workers_interface_cap{};
|
||||||
|
Genode::Ram_dataspace_capability _channels_interface_cap{};
|
||||||
|
|
||||||
|
Allocator<Genode::Registered<Worker>> _worker_allocator;
|
||||||
|
Allocator<Genode::Registered<Channel>> _channel_allocator;
|
||||||
|
|
||||||
|
unsigned long no_channels{0};
|
||||||
|
unsigned long no_workers{0};
|
||||||
|
|
||||||
|
template <class T, typename FUNC>
|
||||||
|
void construct(FUNC const &fn, Allocator<Genode::Registered<T>> &alloc, Genode::Registry<Genode::Registered<T>> ®istry) {
|
||||||
|
T* object = nullptr;
|
||||||
|
|
||||||
|
try {
|
||||||
|
try {
|
||||||
|
object = new (alloc) Genode::Registered<T>(registry);
|
||||||
|
fn(object);
|
||||||
|
} catch (Genode::Allocator::Out_of_memory) {
|
||||||
|
Genode::error("Out of RAM on registering worker.");
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
} catch (...) {
|
||||||
|
if (object)
|
||||||
|
destroy(alloc, object);
|
||||||
|
Genode::error("Exception caught registering worker");
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
Session_component(Genode::Rpc_entrypoint &session_ep,
|
||||||
|
Genode::Session::Resources const &resources,
|
||||||
|
Genode::Session::Label const &label,
|
||||||
|
Genode::Session::Diag const &diag,
|
||||||
|
Genode::Env &env,
|
||||||
|
Genode::Affinity &affinity)
|
||||||
|
: Session_object(session_ep, resources, label, diag), _affinity(affinity.space().total() ? affinity : Genode::Affinity(Genode::Affinity::Space(1,1), Genode::Affinity::Location(0,0,1,1))),
|
||||||
|
_env(env), _worker_allocator(env, &_workers_interface_cap, _affinity.space().total()*sizeof(Genode::Registered<Worker>)),
|
||||||
|
_channel_allocator(env, &_channels_interface_cap, _affinity.space().total()*sizeof(Genode::Registered<Channel>))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void create_channel() override
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
construct<Channel>([&](Channel *) {}, _channel_allocator, _channels);
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
Genode::error("Faild to create channel");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void register_worker(Genode::Thread::Name const &name, Genode::Thread_capability cap) override {
|
||||||
|
try {
|
||||||
|
construct<Worker>([&](Worker *worker)
|
||||||
|
{ worker->_cap = cap;
|
||||||
|
worker->_name = name; }, _worker_allocator, _workers);
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
Genode::error("Failed to register worker");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Capability interface_cap() override {
|
||||||
|
return Capability{_workers_interface_cap, _channels_interface_cap};
|
||||||
|
}
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user