Updated session interface and fixed off-by-one bug in interface allocator.

This commit is contained in:
Michael Mueller
2023-10-13 18:59:29 +02:00
parent 02de7a4e56
commit 80bde5fd90

View File

@@ -13,7 +13,6 @@
*/ */
#pragma once #pragma once
/* Genode includes */ /* Genode includes */
#include <base/session_object.h>
#include <base/affinity.h> #include <base/affinity.h>
#include <base/attached_dataspace.h> #include <base/attached_dataspace.h>
#include <base/component.h> #include <base/component.h>
@@ -25,8 +24,6 @@
#include <suoritin/client.h> #include <suoritin/client.h>
#include <suoritin/connection.h> #include <suoritin/connection.h>
namespace Tukija { namespace Tukija {
namespace Suoritin { namespace Suoritin {
class Session_component; class Session_component;
@@ -41,25 +38,28 @@ class Tukija::Suoritin::Allocator : public Genode::Allocator
using size_t = Genode::size_t; using size_t = Genode::size_t;
private: private:
Genode::Region_map::Local_addr _dataspace{};
size_t _interface_size; size_t _interface_size;
Genode::Region_map::Local_addr _pos {_dataspace}; T* _pos;
T* _interface;
public: Allocator<T>(const Tukija::Suoritin::Allocator<T> &) {}
Allocator(Genode::Env &env, Genode::Ram_dataspace_capability *_interface_cap, size_t interface_size) : _interface_size(interface_size) Allocator<T> &operator=(const Allocator<T>&) {}
public :
Allocator(T *interface, size_t interface_size) : _interface_size(interface_size), _pos(interface), _interface(interface)
{ {
*_interface_cap = env.ram().alloc(interface_size); }
_dataspace = static_cast<T *>(env.rm().attach(*_interface_cap));
}
Alloc_result try_alloc(size_t) override Alloc_result try_alloc(size_t) override
{ {
T *pos = _pos; T *pos = _pos;
if (pos >= static_cast<T*>(_dataspace) + _interface_size) Genode::log("Trying to allocate one interface at ", pos);
return Alloc_result(Genode::Ram_allocator::Alloc_error::OUT_OF_RAM); if (pos >= static_cast<T *>(_interface) + _interface_size)
return Alloc_result(Genode::Ram_allocator::Alloc_error::OUT_OF_RAM);
pos++; _pos++;
return Alloc_result(static_cast<void *>(pos)); return Alloc_result(static_cast<T *>(pos));
} }
void free(void *, size_t) override void free(void *, size_t) override
@@ -69,30 +69,33 @@ public:
bool need_size_for_free() const override { return false; } bool need_size_for_free() const override { return false; }
T *interface() { return _dataspace; } T *interface() { return _interface; }
}; };
class Tukija::Suoritin::Session_component : public Genode::Rpc_object<Tukija::Suoritin::Session> class Tukija::Suoritin::Session_component : public Genode::Session_object<Tukija::Suoritin::Session>
{ {
private: private:
Genode::Affinity _affinity; Genode::Affinity _affinity;
Genode::Env &_env; Genode::Env &_env;
Genode::Ram_dataspace_capability _workers_interface_cap{};
Genode::Ram_dataspace_capability _channels_interface_cap{};
Allocator<Genode::Registered<Worker>> _worker_allocator; Genode::Attached_ram_dataspace _workers_if;
Allocator<Genode::Registered<Channel>> _channel_allocator; Genode::Attached_ram_dataspace _channels_if;
Genode::Attached_ram_dataspace _event_channel;
Allocator<Worker> _worker_allocator;
Allocator<Channel> _channel_allocator;
unsigned long no_channels{0}; unsigned long no_channels{0};
unsigned long no_workers{0}; unsigned long no_workers{0};
template <class T, typename FUNC> template <class T, typename FUNC, typename ...Args>
void construct(FUNC const &fn, Allocator<Genode::Registered<T>> &alloc, Genode::Registry<Genode::Registered<T>> &registry) { void construct(FUNC const &fn, Allocator<T> &alloc, Args ...args) {
T* object = nullptr; T* object = nullptr;
try { try {
try { try {
object = new (alloc) Genode::Registered<T>(registry); object = new (alloc) T(args...);
fn(object); fn(object);
} catch (Genode::Allocator::Out_of_memory) { } catch (Genode::Allocator::Out_of_memory) {
Genode::error("Out of RAM on registering worker."); Genode::error("Out of RAM on registering worker.");
@@ -108,30 +111,40 @@ class Tukija::Suoritin::Session_component : public Genode::Rpc_object<Tukija::Su
public: public:
Session_component(Genode::Env &env, Session_component( Genode::Rpc_entrypoint &session_ep,
Genode::Affinity &affinity) Resources const &resources,
: Genode::Rpc_object<Session>(), Label const &label,
_affinity(affinity.space().total() ? affinity : Genode::Affinity(Genode::Affinity::Space(1,1), Genode::Affinity::Location(0,0,1,1))), Diag const &diag,
_env(env), _worker_allocator(env, &_workers_interface_cap, _affinity.space().total()*sizeof(Genode::Registered<Worker>)), Genode::Env &env,
_channel_allocator(env, &_channels_interface_cap, _affinity.space().total()*sizeof(Genode::Registered<Channel>)) Genode::Affinity &affinity)
:
Genode::Session_object<Session>(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),
_workers_if(env.ram(), env.rm(), sizeof(Worker)*affinity.space().total()),
_channels_if(env.ram(), env.rm(), sizeof(Channel)*affinity.space().total()),
_event_channel(env.ram(), env.rm(), sizeof(Event_channel)),
_worker_allocator(_workers_if.local_addr<Worker>(), _affinity.space().total()*sizeof(Worker)),
_channel_allocator(_channels_if.local_addr<Channel>(), _affinity.space().total()*sizeof(Channel))
{ {
} }
void create_channel() override void create_channel(Worker const &worker) override
{ {
try { try {
construct<Channel>([&](Channel *) {}, _channel_allocator, _channels); construct<Channel>([&](Channel *) {}, _channel_allocator, worker);
} }
catch (...) catch (...)
{ {
Genode::error("Faild to create channel"); Genode::error("Faild to create channel");
} }
no_channels++;
} }
void register_worker(Genode::Thread::Name const &name, Genode::Thread_capability cap) override { void register_worker(Genode::Thread::Name const &name, Genode::Thread_capability cap) override {
try { try {
construct<Worker>([&](Worker *worker) construct<Worker>([&](Worker *w)
{ worker->_cap = cap; { w->_id = (w - workers_if()); },
worker->_name = name; }, _worker_allocator, _workers); _worker_allocator, cap, name);
} }
catch (...) catch (...)
{ {
@@ -139,9 +152,45 @@ class Tukija::Suoritin::Session_component : public Genode::Rpc_object<Tukija::Su
} }
} }
Capability interface_cap() override { Genode::Dataspace_capability worker_if() override
return Capability{_workers_interface_cap, _channels_interface_cap}; {
return _workers_if.cap();
} }
Genode::Dataspace_capability channel_if() override
{
return _channels_if.cap();
}
Genode::Dataspace_capability event_channel() override
{
return _event_channel.cap();
}
/*****
* Internal interface for use by Hoitaja
*****/
inline Worker *workers_if() {
return _workers_if.local_addr<Worker>();
}
inline Channel *channels_if() {
return _channels_if.local_addr<Channel>();
}
inline Worker &worker(unsigned long id) {
return workers_if()[id];
}
void send_request(Genode::Parent::Resource_args &args)
{
Event_channel *evtchn = _event_channel.local_addr<Event_channel>();
evtchn->parent_args = args;
evtchn->parent_flag = true;
}
unsigned long channels() { return no_channels; }
}; };
class Tukija::Suoritin::Root_component class Tukija::Suoritin::Root_component
@@ -152,15 +201,27 @@ class Tukija::Suoritin::Root_component
Genode::Env &_env; Genode::Env &_env;
public: public:
Session_component *_create_session(const char *) override Session_component *_create_session(const char *args) override
{ {
Genode::log("Creating new TASKING session"); Genode::log("Creating new TASKING session");
return new(md_alloc()) Genode::Registered<Session_component>(sessions, _env, Genode::Affinity(_env.cpu().affinity_space(), Genode::Affinity::Location(0,0,_env.cpu().affinity_space().width(), _env.cpu().affinity_space().height()))); return new(md_alloc()) Genode::Registered<Session_component>(sessions,
*this->ep(),
Genode::session_resources_from_args(args),
Genode::session_label_from_args(args),
Genode::session_diag_from_args(args),
_env,
Genode::Affinity(_env.cpu().affinity_space(), Genode::Affinity::Location(0,0,_env.cpu().affinity_space().width(), _env.cpu().affinity_space().height())));
}
/* Interal interface for Hoitaja */
template <typename FN>
void for_each(FN const &fn) {
sessions.for_each(fn);
} }
Root_component(Genode::Env &env, Genode::Allocator &alloc) Root_component(Genode::Env &env, Genode::Allocator &alloc)
: Genode::Root_component<Session_component>(env.ep(), alloc), _env(env) : Genode::Root_component<Session_component>(env.ep(), alloc), _env(env)
{ {
Genode::log("Started TASKING service"); Genode::log("Sta:ted TASKING service");
} }
}; };