diff --git a/repos/os/include/suoritin/component.h b/repos/os/include/suoritin/component.h new file mode 100644 index 0000000000..bc4859c7bb --- /dev/null +++ b/repos/os/include/suoritin/component.h @@ -0,0 +1,153 @@ +#pragma once +/* Genode includes */ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + + + +namespace Tukija { + namespace Suoritin { + class Session_component; + template class Allocator; + class Root_component; + } +} + +template +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(env.rm().attach(*_interface_cap)); + } + + Alloc_result try_alloc(size_t) override + { + T *pos = _pos; + if (pos >= static_cast(_dataspace) + _interface_size) + return Alloc_result(Genode::Ram_allocator::Alloc_error::OUT_OF_RAM); + + pos++; + return Alloc_result(static_cast(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::Rpc_object +{ + private: + Genode::Affinity _affinity; + Genode::Env &_env; + Genode::Ram_dataspace_capability _workers_interface_cap{}; + Genode::Ram_dataspace_capability _channels_interface_cap{}; + + Allocator> _worker_allocator; + Allocator> _channel_allocator; + + unsigned long no_channels{0}; + unsigned long no_workers{0}; + + template + void construct(FUNC const &fn, Allocator> &alloc, Genode::Registry> ®istry) { + T* object = nullptr; + + try { + try { + object = new (alloc) Genode::Registered(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::Env &env, + Genode::Affinity &affinity) + : Genode::Rpc_object(), + _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)), + _channel_allocator(env, &_channels_interface_cap, _affinity.space().total()*sizeof(Genode::Registered)) + { + } + + void create_channel() override + { + try { + construct([&](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->_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}; + } +}; + +class Tukija::Suoritin::Root_component +: public Genode::Root_component +{ + private: + Genode::Registry> sessions{}; + Genode::Env &_env; + + public: + Session_component *_create_session(const char *) override + { + Genode::log("Creating new TASKING session"); + return new(md_alloc()) Genode::Registered(sessions, _env, Genode::Affinity(_env.cpu().affinity_space(), Genode::Affinity::Location(0,0,_env.cpu().affinity_space().width(), _env.cpu().affinity_space().height()))); + } + + Root_component(Genode::Env &env, Genode::Allocator &alloc) + : Genode::Root_component(env.ep(), alloc), _env(env) + { + Genode::log("Started TASKING service"); + } +}; \ No newline at end of file