mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-19 03:06:39 +00:00
parent
2223e72c7f
commit
e33ea2a8b7
@ -532,6 +532,8 @@ namespace Kernel
|
||||
* Blocks the caller until the last delivered signal of the targeted
|
||||
* context is acknowledged. Then the context gets destructed, losing
|
||||
* all submits that were not delivered when this syscall occured.
|
||||
*
|
||||
* Restricted to core threads.
|
||||
*/
|
||||
inline bool kill_signal_context(unsigned context_id) {
|
||||
return syscall(KILL_SIGNAL_CONTEXT, (Syscall_arg)context_id); }
|
||||
|
@ -54,16 +54,17 @@ namespace Genode
|
||||
virtual ~Signal_session() { }
|
||||
|
||||
/**
|
||||
* Create a new signal-receiver kernel-object
|
||||
* Create and manage a new signal receiver
|
||||
*
|
||||
* \return a cap that acts as reference to the created object
|
||||
*
|
||||
* \throw Out_of_metadata
|
||||
* \throw Exception
|
||||
*/
|
||||
virtual Signal_receiver_capability alloc_receiver() = 0;
|
||||
|
||||
/**
|
||||
* Create a new signal-context kernel-object
|
||||
* Create and manage a new signal context
|
||||
*
|
||||
* \param r names the signal receiver that shall provide
|
||||
* the new context
|
||||
@ -73,29 +74,35 @@ namespace Genode
|
||||
* \return a cap that acts as reference to the created object
|
||||
*
|
||||
* \throw Out_of_metadata
|
||||
* \throw Exception
|
||||
*/
|
||||
virtual Signal_context_capability
|
||||
alloc_context(Signal_receiver_capability const r,
|
||||
alloc_context(Signal_receiver_capability r,
|
||||
unsigned const imprint) = 0;
|
||||
|
||||
/**
|
||||
* Free signal-context
|
||||
* Free a signal context
|
||||
*
|
||||
* \param cap capability of signal-context to release
|
||||
*
|
||||
* \throw Exception
|
||||
*/
|
||||
virtual void free_context(Signal_context_capability cap) = 0;
|
||||
|
||||
|
||||
/*********************
|
||||
** RPC declaration **
|
||||
*********************/
|
||||
|
||||
GENODE_RPC_THROW(Rpc_alloc_receiver, Signal_receiver_capability,
|
||||
alloc_receiver, GENODE_TYPE_LIST(Out_of_metadata));
|
||||
alloc_receiver, GENODE_TYPE_LIST(Out_of_metadata,
|
||||
Exception));
|
||||
GENODE_RPC_THROW(Rpc_alloc_context, Signal_context_capability,
|
||||
alloc_context, GENODE_TYPE_LIST(Out_of_metadata),
|
||||
Signal_receiver_capability, unsigned);
|
||||
GENODE_RPC(Rpc_free_context, void, free_context,
|
||||
Signal_context_capability);
|
||||
alloc_context, GENODE_TYPE_LIST(Out_of_metadata,
|
||||
Exception), Signal_receiver_capability, unsigned);
|
||||
GENODE_RPC_THROW(Rpc_free_context, void, free_context,
|
||||
GENODE_TYPE_LIST(Exception),
|
||||
Signal_context_capability);
|
||||
|
||||
GENODE_RPC_INTERFACE(Rpc_alloc_receiver, Rpc_alloc_context,
|
||||
Rpc_free_context);
|
||||
|
@ -111,21 +111,7 @@ Signal_receiver::Signal_receiver()
|
||||
|
||||
void Signal_receiver::_unsynchronized_dissolve(Signal_context * c)
|
||||
{
|
||||
/*
|
||||
* We first destroy the kernel object. This also ensures
|
||||
* that no delivered but unacked signals of this context exist
|
||||
* in userland anymore.
|
||||
*/
|
||||
if (!Kernel::kill_signal_context(c->_cap.dst())) {
|
||||
PERR("failed to kill signal context");
|
||||
|
||||
/* we have to keep the signal context alive for other */
|
||||
while (1) ;
|
||||
}
|
||||
/*
|
||||
* Now we can tell core to regain the memory of the
|
||||
* destructed kernel object.
|
||||
*/
|
||||
/* release core resources */
|
||||
signal_connection()->free_context(c->_cap);
|
||||
|
||||
/* reset the context */
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <base/rpc_server.h>
|
||||
#include <base/slab.h>
|
||||
#include <base/allocator_guard.h>
|
||||
#include <base/object_pool.h>
|
||||
|
||||
namespace Genode
|
||||
{
|
||||
@ -36,9 +37,17 @@ namespace Genode
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* Maps a signal-context name to related core and kernel resources
|
||||
*/
|
||||
class Context;
|
||||
|
||||
typedef Object_pool<Context> Context_pool;
|
||||
|
||||
Allocator_guard _md_alloc;
|
||||
Slab _receivers_slab;
|
||||
Slab _contexts_slab;
|
||||
Context_pool _contexts;
|
||||
char _initial_receivers_sb [RECEIVERS_SB_SIZE];
|
||||
char _initial_contexts_sb [CONTEXTS_SB_SIZE];
|
||||
|
||||
@ -70,11 +79,41 @@ namespace Genode
|
||||
Signal_receiver_capability alloc_receiver();
|
||||
|
||||
Signal_context_capability
|
||||
alloc_context(Signal_receiver_capability const r,
|
||||
unsigned const imprint);
|
||||
void free_context(Signal_context_capability context_cap);
|
||||
alloc_context(Signal_receiver_capability, unsigned const);
|
||||
|
||||
void free_context(Signal_context_capability);
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _CORE__INCLUDE__CAP_SESSION_COMPONENT_H_ */
|
||||
class Genode::Signal_session_component::Context : public Context_pool::Entry
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Context(Untyped_capability cap) : Entry(cap) { }
|
||||
|
||||
/**
|
||||
* Name of signal context
|
||||
*/
|
||||
unsigned id() const { return Context_pool::Entry::cap().dst(); }
|
||||
|
||||
/**
|
||||
* Size of SLAB block occupied by resources and this resource info
|
||||
*/
|
||||
static size_t slab_size()
|
||||
{
|
||||
return sizeof(Context) + Kernel::signal_context_size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Base of region donated to the kernel
|
||||
*/
|
||||
static void * kernel_donation(void * const slab_addr)
|
||||
{
|
||||
return (void *)((addr_t)slab_addr + sizeof(Context));
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _CORE__INCLUDE__CAP_SESSION_COMPONENT_H_ */
|
||||
|
@ -702,6 +702,9 @@ namespace Kernel
|
||||
*/
|
||||
void do_kill_signal_context(Thread * const user)
|
||||
{
|
||||
/* check permissions */
|
||||
assert(user->pd_id() == core_id());
|
||||
|
||||
unsigned id = user->user_arg_1();
|
||||
Signal_context * const c = Signal_context::pool()->object(id);
|
||||
if (!c) { return; }
|
||||
|
@ -13,6 +13,7 @@
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/printf.h>
|
||||
#include <base/sleep.h>
|
||||
#include <kernel/syscalls.h>
|
||||
|
||||
/* core includes */
|
||||
@ -21,12 +22,18 @@
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
/**
|
||||
* Placement new
|
||||
*/
|
||||
void * operator new (size_t, void * p) { return p; }
|
||||
|
||||
|
||||
Signal_session_component::Signal_session_component(Allocator * const md,
|
||||
size_t const ram_quota) :
|
||||
_md_alloc(md, ram_quota),
|
||||
_receivers_slab(Kernel::signal_receiver_size(), RECEIVERS_SB_SIZE,
|
||||
(Slab_block *)&_initial_receivers_sb, &_md_alloc),
|
||||
_contexts_slab(Kernel::signal_context_size(), CONTEXTS_SB_SIZE,
|
||||
_contexts_slab(Context::slab_size(), CONTEXTS_SB_SIZE,
|
||||
(Slab_block *)&_initial_contexts_sb, &_md_alloc)
|
||||
{ }
|
||||
|
||||
@ -40,38 +47,72 @@ Signal_session_component::~Signal_session_component()
|
||||
|
||||
Signal_receiver_capability Signal_session_component::alloc_receiver()
|
||||
{
|
||||
/* create receiver kernel-object */
|
||||
/* allocate resources for receiver */
|
||||
size_t const s = Kernel::signal_receiver_size();
|
||||
void * p;
|
||||
if (!_receivers_slab.alloc(s, &p)) throw Out_of_metadata();
|
||||
if (!_receivers_slab.alloc(s, &p)) {
|
||||
PERR("failed to allocate signal receiver");
|
||||
throw Out_of_metadata();
|
||||
}
|
||||
/* create kernel object for receiver */
|
||||
unsigned const id = Kernel::new_signal_receiver(p);
|
||||
if (!id) throw Out_of_metadata();
|
||||
|
||||
/* return reference to the new kernel-object */
|
||||
Native_capability c(id, 0);
|
||||
if (!id) {
|
||||
PERR("failed to create signal receiver");
|
||||
throw Exception();
|
||||
}
|
||||
/* return receiver capability */
|
||||
Native_capability c(id, id);
|
||||
return reinterpret_cap_cast<Signal_receiver>(c);
|
||||
}
|
||||
|
||||
|
||||
Signal_context_capability
|
||||
Signal_session_component::alloc_context(Signal_receiver_capability r,
|
||||
unsigned imprint)
|
||||
unsigned const imprint)
|
||||
{
|
||||
/* create context kernel-object */
|
||||
size_t const s = Kernel::signal_context_size();
|
||||
/* allocate resources for context */
|
||||
void * p;
|
||||
if (!_contexts_slab.alloc(s, &p)) throw Out_of_metadata();
|
||||
unsigned const id = Kernel::new_signal_context(p, r.dst(), imprint);
|
||||
if (!id) throw Out_of_metadata();
|
||||
if (!_contexts_slab.alloc(Context::slab_size(), &p)) {
|
||||
PERR("failed to allocate signal-context resources");
|
||||
throw Out_of_metadata();
|
||||
}
|
||||
/* create kernel object for context */
|
||||
void * donation = Context::kernel_donation(p);
|
||||
unsigned const id = Kernel::new_signal_context(donation, r.dst(), imprint);
|
||||
if (!id)
|
||||
{
|
||||
/* clean up */
|
||||
_contexts_slab.free(p, Context::slab_size());
|
||||
PERR("failed to create signal context");
|
||||
throw Exception();
|
||||
}
|
||||
/* remember context ressources */
|
||||
Native_capability cap(id, id);
|
||||
_contexts.insert(new (p) Context(cap));
|
||||
|
||||
/* return reference to the new kernel-object */
|
||||
Native_capability c(id, 0);
|
||||
return reinterpret_cap_cast<Signal_context>(c);
|
||||
/* return context capability */
|
||||
return reinterpret_cap_cast<Signal_context>(cap);
|
||||
}
|
||||
|
||||
/**
|
||||
* FIXME should regain the kernel-object memory from kernel
|
||||
*/
|
||||
void Signal_session_component::free_context(Signal_context_capability cap) {
|
||||
PDBG("Not implemented"); }
|
||||
|
||||
void Signal_session_component::free_context(Signal_context_capability cap)
|
||||
{
|
||||
/* lookup ressource info */
|
||||
Context * const c = _contexts.lookup_and_lock(cap);
|
||||
if (!c) {
|
||||
PERR("unknown signal context");
|
||||
throw Exception();
|
||||
}
|
||||
/* release kernel resources */
|
||||
if (!Kernel::kill_signal_context(c->id()))
|
||||
{
|
||||
/* clean-up */
|
||||
c->release();
|
||||
PERR("failed to kill signal context");
|
||||
throw Exception();
|
||||
}
|
||||
/* release core resources */
|
||||
_contexts.remove_locked(c);
|
||||
c->~Context();
|
||||
_contexts_slab.free(c, Context::slab_size());
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user