parent
2223e72c7f
commit
e33ea2a8b7
|
@ -532,6 +532,8 @@ namespace Kernel
|
||||||
* Blocks the caller until the last delivered signal of the targeted
|
* Blocks the caller until the last delivered signal of the targeted
|
||||||
* context is acknowledged. Then the context gets destructed, losing
|
* context is acknowledged. Then the context gets destructed, losing
|
||||||
* all submits that were not delivered when this syscall occured.
|
* all submits that were not delivered when this syscall occured.
|
||||||
|
*
|
||||||
|
* Restricted to core threads.
|
||||||
*/
|
*/
|
||||||
inline bool kill_signal_context(unsigned context_id) {
|
inline bool kill_signal_context(unsigned context_id) {
|
||||||
return syscall(KILL_SIGNAL_CONTEXT, (Syscall_arg)context_id); }
|
return syscall(KILL_SIGNAL_CONTEXT, (Syscall_arg)context_id); }
|
||||||
|
|
|
@ -54,16 +54,17 @@ namespace Genode
|
||||||
virtual ~Signal_session() { }
|
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
|
* \return a cap that acts as reference to the created object
|
||||||
*
|
*
|
||||||
* \throw Out_of_metadata
|
* \throw Out_of_metadata
|
||||||
|
* \throw Exception
|
||||||
*/
|
*/
|
||||||
virtual Signal_receiver_capability alloc_receiver() = 0;
|
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
|
* \param r names the signal receiver that shall provide
|
||||||
* the new context
|
* the new context
|
||||||
|
@ -73,28 +74,34 @@ namespace Genode
|
||||||
* \return a cap that acts as reference to the created object
|
* \return a cap that acts as reference to the created object
|
||||||
*
|
*
|
||||||
* \throw Out_of_metadata
|
* \throw Out_of_metadata
|
||||||
|
* \throw Exception
|
||||||
*/
|
*/
|
||||||
virtual Signal_context_capability
|
virtual Signal_context_capability
|
||||||
alloc_context(Signal_receiver_capability const r,
|
alloc_context(Signal_receiver_capability r,
|
||||||
unsigned const imprint) = 0;
|
unsigned const imprint) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Free signal-context
|
* Free a signal context
|
||||||
*
|
*
|
||||||
* \param cap capability of signal-context to release
|
* \param cap capability of signal-context to release
|
||||||
|
*
|
||||||
|
* \throw Exception
|
||||||
*/
|
*/
|
||||||
virtual void free_context(Signal_context_capability cap) = 0;
|
virtual void free_context(Signal_context_capability cap) = 0;
|
||||||
|
|
||||||
|
|
||||||
/*********************
|
/*********************
|
||||||
** RPC declaration **
|
** RPC declaration **
|
||||||
*********************/
|
*********************/
|
||||||
|
|
||||||
GENODE_RPC_THROW(Rpc_alloc_receiver, Signal_receiver_capability,
|
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,
|
GENODE_RPC_THROW(Rpc_alloc_context, Signal_context_capability,
|
||||||
alloc_context, GENODE_TYPE_LIST(Out_of_metadata),
|
alloc_context, GENODE_TYPE_LIST(Out_of_metadata,
|
||||||
Signal_receiver_capability, unsigned);
|
Exception), Signal_receiver_capability, unsigned);
|
||||||
GENODE_RPC(Rpc_free_context, void, free_context,
|
GENODE_RPC_THROW(Rpc_free_context, void, free_context,
|
||||||
|
GENODE_TYPE_LIST(Exception),
|
||||||
Signal_context_capability);
|
Signal_context_capability);
|
||||||
|
|
||||||
GENODE_RPC_INTERFACE(Rpc_alloc_receiver, Rpc_alloc_context,
|
GENODE_RPC_INTERFACE(Rpc_alloc_receiver, Rpc_alloc_context,
|
||||||
|
|
|
@ -111,21 +111,7 @@ Signal_receiver::Signal_receiver()
|
||||||
|
|
||||||
void Signal_receiver::_unsynchronized_dissolve(Signal_context * c)
|
void Signal_receiver::_unsynchronized_dissolve(Signal_context * c)
|
||||||
{
|
{
|
||||||
/*
|
/* release core resources */
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
signal_connection()->free_context(c->_cap);
|
signal_connection()->free_context(c->_cap);
|
||||||
|
|
||||||
/* reset the context */
|
/* reset the context */
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include <base/rpc_server.h>
|
#include <base/rpc_server.h>
|
||||||
#include <base/slab.h>
|
#include <base/slab.h>
|
||||||
#include <base/allocator_guard.h>
|
#include <base/allocator_guard.h>
|
||||||
|
#include <base/object_pool.h>
|
||||||
|
|
||||||
namespace Genode
|
namespace Genode
|
||||||
{
|
{
|
||||||
|
@ -36,9 +37,17 @@ namespace Genode
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maps a signal-context name to related core and kernel resources
|
||||||
|
*/
|
||||||
|
class Context;
|
||||||
|
|
||||||
|
typedef Object_pool<Context> Context_pool;
|
||||||
|
|
||||||
Allocator_guard _md_alloc;
|
Allocator_guard _md_alloc;
|
||||||
Slab _receivers_slab;
|
Slab _receivers_slab;
|
||||||
Slab _contexts_slab;
|
Slab _contexts_slab;
|
||||||
|
Context_pool _contexts;
|
||||||
char _initial_receivers_sb [RECEIVERS_SB_SIZE];
|
char _initial_receivers_sb [RECEIVERS_SB_SIZE];
|
||||||
char _initial_contexts_sb [CONTEXTS_SB_SIZE];
|
char _initial_contexts_sb [CONTEXTS_SB_SIZE];
|
||||||
|
|
||||||
|
@ -70,11 +79,41 @@ namespace Genode
|
||||||
Signal_receiver_capability alloc_receiver();
|
Signal_receiver_capability alloc_receiver();
|
||||||
|
|
||||||
Signal_context_capability
|
Signal_context_capability
|
||||||
alloc_context(Signal_receiver_capability const r,
|
alloc_context(Signal_receiver_capability, unsigned const);
|
||||||
unsigned const imprint);
|
|
||||||
void free_context(Signal_context_capability context_cap);
|
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)
|
void do_kill_signal_context(Thread * const user)
|
||||||
{
|
{
|
||||||
|
/* check permissions */
|
||||||
|
assert(user->pd_id() == core_id());
|
||||||
|
|
||||||
unsigned id = user->user_arg_1();
|
unsigned id = user->user_arg_1();
|
||||||
Signal_context * const c = Signal_context::pool()->object(id);
|
Signal_context * const c = Signal_context::pool()->object(id);
|
||||||
if (!c) { return; }
|
if (!c) { return; }
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
|
|
||||||
/* Genode includes */
|
/* Genode includes */
|
||||||
#include <base/printf.h>
|
#include <base/printf.h>
|
||||||
|
#include <base/sleep.h>
|
||||||
#include <kernel/syscalls.h>
|
#include <kernel/syscalls.h>
|
||||||
|
|
||||||
/* core includes */
|
/* core includes */
|
||||||
|
@ -21,12 +22,18 @@
|
||||||
using namespace Genode;
|
using namespace Genode;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Placement new
|
||||||
|
*/
|
||||||
|
void * operator new (size_t, void * p) { return p; }
|
||||||
|
|
||||||
|
|
||||||
Signal_session_component::Signal_session_component(Allocator * const md,
|
Signal_session_component::Signal_session_component(Allocator * const md,
|
||||||
size_t const ram_quota) :
|
size_t const ram_quota) :
|
||||||
_md_alloc(md, ram_quota),
|
_md_alloc(md, ram_quota),
|
||||||
_receivers_slab(Kernel::signal_receiver_size(), RECEIVERS_SB_SIZE,
|
_receivers_slab(Kernel::signal_receiver_size(), RECEIVERS_SB_SIZE,
|
||||||
(Slab_block *)&_initial_receivers_sb, &_md_alloc),
|
(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)
|
(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()
|
Signal_receiver_capability Signal_session_component::alloc_receiver()
|
||||||
{
|
{
|
||||||
/* create receiver kernel-object */
|
/* allocate resources for receiver */
|
||||||
size_t const s = Kernel::signal_receiver_size();
|
size_t const s = Kernel::signal_receiver_size();
|
||||||
void * p;
|
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);
|
unsigned const id = Kernel::new_signal_receiver(p);
|
||||||
if (!id) throw Out_of_metadata();
|
if (!id) {
|
||||||
|
PERR("failed to create signal receiver");
|
||||||
/* return reference to the new kernel-object */
|
throw Exception();
|
||||||
Native_capability c(id, 0);
|
}
|
||||||
|
/* return receiver capability */
|
||||||
|
Native_capability c(id, id);
|
||||||
return reinterpret_cap_cast<Signal_receiver>(c);
|
return reinterpret_cap_cast<Signal_receiver>(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Signal_context_capability
|
Signal_context_capability
|
||||||
Signal_session_component::alloc_context(Signal_receiver_capability r,
|
Signal_session_component::alloc_context(Signal_receiver_capability r,
|
||||||
unsigned imprint)
|
unsigned const imprint)
|
||||||
{
|
{
|
||||||
/* create context kernel-object */
|
/* allocate resources for context */
|
||||||
size_t const s = Kernel::signal_context_size();
|
|
||||||
void * p;
|
void * p;
|
||||||
if (!_contexts_slab.alloc(s, &p)) throw Out_of_metadata();
|
if (!_contexts_slab.alloc(Context::slab_size(), &p)) {
|
||||||
unsigned const id = Kernel::new_signal_context(p, r.dst(), imprint);
|
PERR("failed to allocate signal-context resources");
|
||||||
if (!id) throw Out_of_metadata();
|
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 */
|
/* return context capability */
|
||||||
Native_capability c(id, 0);
|
return reinterpret_cap_cast<Signal_context>(cap);
|
||||||
return reinterpret_cap_cast<Signal_context>(c);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 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