core: Introduce default CPU exception handler

The CPU session interfaces comes with the ability to install an
exception handler per thread. This patch enhances the feature with the
provision of a default signal handler that is used if no thread-specific
handler is installed. The default signal handler can be set by
specifying an invalid thread capability and a valid signal context
capability.

Furthermore, this patch relaxes the requirement of the order of the
calls of 'exception_handler' and 'set_pager'. Originally, the exception
handler could be installed not before setting a pager. Now, we remember
the installed exception handler in the 'Cpu_thread' and propagate to to
the platform thread at a later time.
This commit is contained in:
Norman Feske 2013-01-03 20:29:18 +01:00
parent 9b24115c08
commit 9f82764316
8 changed files with 170 additions and 34 deletions

View File

@ -47,14 +47,19 @@ namespace Genode {
{
private:
Platform_thread _platform_thread;
bool _bound; /* pd binding flag */
Platform_thread _platform_thread;
bool _bound; /* pd binding flag */
Signal_context_capability _sigh; /* exception handler */
public:
Cpu_thread_component(const char *name, unsigned priority, addr_t)
: _platform_thread(name, priority), _bound(false) { }
Cpu_thread_component(const char *name, unsigned priority, addr_t utcb,
Signal_context_capability sigh)
:
_platform_thread(name, priority), _bound(false), _sigh(sigh)
{
update_exception_sigh();
}
/************************
@ -64,6 +69,17 @@ namespace Genode {
inline Platform_thread * platform_thread() { return &_platform_thread; }
inline bool bound() const { return _bound; }
inline void bound(bool b) { _bound = b; }
void sigh(Signal_context_capability sigh)
{
sigh = sigh;
update_exception_sigh();
}
/**
* Propagate exception handler to platform thread
*/
void update_exception_sigh();
};
@ -88,6 +104,12 @@ namespace Genode {
created with this
session */
/**
* Exception handler that will be invoked unless overridden by a
* call of 'Cpu_session::exception_handler'.
*/
Signal_context_capability _default_exception_handler;
/**
* Lookup thread in CPU session by its capability
*

View File

@ -46,8 +46,15 @@ namespace Genode {
Pager_capability add_client(Thread_capability thread) {
return _local()->add_client(thread); }
void fault_handler(Signal_context_capability handler) {
return _local()->fault_handler(handler); }
void fault_handler(Signal_context_capability handler)
{
/*
* On Linux, page faults are never reflected to RM clients. They
* are always handled by the kernel. If a segmentation fault
* occurs, this condition is being reflected as a CPU exception
* to the handler registered via 'Cpu_session::exception_handler'.
*/
}
State state() {
return _local()->state(); }

View File

@ -47,15 +47,19 @@ namespace Genode {
{
private:
Platform_thread _platform_thread;
bool _bound; /* pd binding flag */
Platform_thread _platform_thread;
bool _bound; /* pd binding flag */
Signal_context_capability _sigh; /* exception handler */
public:
Cpu_thread_component(const char *name, unsigned priority,
addr_t utcb)
: _platform_thread(name, priority, utcb), _bound(false) { }
Cpu_thread_component(const char *name, unsigned priority, addr_t utcb,
Signal_context_capability sigh)
:
_platform_thread(name, priority, utcb), _bound(false), _sigh(sigh)
{
update_exception_sigh();
}
/************************
@ -65,6 +69,17 @@ namespace Genode {
inline Platform_thread * platform_thread() { return &_platform_thread; }
inline bool bound() const { return _bound; }
inline void bound(bool b) { _bound = b; }
void sigh(Signal_context_capability sigh)
{
sigh = sigh;
update_exception_sigh();
}
/**
* Propagate exception handler to platform thread
*/
void update_exception_sigh();
};
@ -83,6 +98,12 @@ namespace Genode {
created with this
session */
/**
* Exception handler that will be invoked unless overridden by a
* call of 'Cpu_session::exception_handler'.
*/
Signal_context_capability _default_exception_handler;
/**
* Lookup thread in CPU session by its capability
*
@ -127,11 +148,9 @@ namespace Genode {
** CPU session interface **
***************************/
Thread_capability create_thread(Name const &, addr_t utcb);
Thread_capability create_thread(Name const &, addr_t);
Ram_dataspace_capability utcb(Thread_capability thread);
void kill_thread(Thread_capability);
Thread_capability first();
Thread_capability next(Thread_capability);
int set_pager(Thread_capability, Pager_capability);
int start(Thread_capability, addr_t, addr_t);
void pause(Thread_capability thread_cap);

View File

@ -47,14 +47,19 @@ namespace Genode {
{
private:
Platform_thread _platform_thread;
bool _bound; /* pd binding flag */
Platform_thread _platform_thread;
bool _bound; /* pd binding flag */
Signal_context_capability _sigh; /* exception handler */
public:
Cpu_thread_component(const char *name, unsigned priority, addr_t)
: _platform_thread(name, priority), _bound(false) { }
Cpu_thread_component(const char *name, unsigned priority, addr_t utcb,
Signal_context_capability sigh)
:
_platform_thread(name, priority, utcb), _bound(false), _sigh(sigh)
{
update_exception_sigh();
}
/************************
@ -64,6 +69,17 @@ namespace Genode {
inline Platform_thread * platform_thread() { return &_platform_thread; }
inline bool bound() const { return _bound; }
inline void bound(bool b) { _bound = b; }
void sigh(Signal_context_capability sigh)
{
sigh = sigh;
update_exception_sigh();
}
/**
* Propagate exception handler to platform thread
*/
void update_exception_sigh();
};
@ -87,6 +103,11 @@ namespace Genode {
unsigned _priority; /* priority of threads
created with this
session */
/**
* Exception handler that will be invoked unless overridden by a
* call of 'Cpu_session::exception_handler'.
*/
Signal_context_capability _default_exception_handler;
/**
* Lookup thread in CPU session by its capability
@ -134,7 +155,6 @@ namespace Genode {
Thread_capability create_thread(Name const &, addr_t);
Ram_dataspace_capability utcb(Thread_capability thread);
void kill_thread(Thread_capability);
int set_pager(Thread_capability, Pager_capability);
int start(Thread_capability, addr_t, addr_t);
@ -150,9 +170,9 @@ namespace Genode {
void affinity(Thread_capability, unsigned);
/***********************************
/******************************
** NOVA specific extensions **
***********************************/
******************************/
Native_capability native_cap(Thread_capability);
Native_capability pause_sync(Thread_capability);

View File

@ -147,6 +147,16 @@ namespace Genode {
/**
* Register signal handler for exceptions of the specified thread
*
* If 'thread' is an invalid capability, the default exception
* handler for the CPU session is set. This handler is used for
* all threads that have no explicitly installed exception handler.
* The new default signal handler will take effect for threads
* created after the call.
*
* On Linux, this exception is delivered when the process triggers
* a SIGCHLD. On other platforms, this exception is delivered on
* the occurrence of CPU exceptions such as division by zero.
*/
virtual void exception_handler(Thread_capability thread,
Signal_context_capability handler) = 0;

View File

@ -166,6 +166,11 @@ namespace Genode {
/**
* Register signal handler for region-manager faults
*
* On Linux, this signal is never delivered because page-fault handling
* is performed by the Linux kernel. On microkernel platforms,
* unresolvable page faults (traditionally called segmentation fault)
* will result in the delivery of the signal.
*/
virtual void fault_handler(Signal_context_capability handler) = 0;

View File

@ -25,6 +25,13 @@
using namespace Genode;
void Cpu_thread_component::update_exception_sigh()
{
if (platform_thread()->pager())
platform_thread()->pager()->exception_handler(_sigh);
};
Thread_capability Cpu_session_component::create_thread(Name const &name,
addr_t utcb)
{
@ -34,7 +41,8 @@ Thread_capability Cpu_session_component::create_thread(Name const &name,
Cpu_thread_component *thread = 0;
try {
thread = new(&_thread_alloc) Cpu_thread_component(name.string(),
_priority, utcb);
_priority, utcb,
_default_exception_handler);
} catch (Allocator::Out_of_memory) {
throw Out_of_metadata();
}
@ -81,6 +89,7 @@ int Cpu_session_component::set_pager(Thread_capability thread_cap,
if (!p) return -2;
thread->platform_thread()->pager(p);
p->thread_cap(thread->cap());
return 0;
@ -93,6 +102,12 @@ int Cpu_session_component::start(Thread_capability thread_cap,
Cpu_thread_component *thread = _lookup_thread(thread_cap);
if (!thread) return -1;
/*
* If an exception handler was installed prior to the call of 'set_pager',
* we need to update the pager object with the current exception handler.
*/
thread->update_exception_sigh();
return thread->platform_thread()->start((void *)ip, (void *)sp);
}
@ -146,10 +161,27 @@ void
Cpu_session_component::exception_handler(Thread_capability thread_cap,
Signal_context_capability sigh_cap)
{
Cpu_thread_component *thread = _lookup_thread(thread_cap);
if (!thread || !thread->platform_thread()->pager()) return;
/*
* By specifying an invalid thread capability, the caller sets the default
* exception handler for the CPU session.
*/
if (!thread_cap.valid()) {
_default_exception_handler = sigh_cap;
return;
}
thread->platform_thread()->pager()->exception_handler(sigh_cap);
/*
* If an invalid signal handler is specified for a valid thread, we revert
* the signal handler to the CPU session's default signal handler.
*/
if (!sigh_cap.valid()) {
sigh_cap = _default_exception_handler;
}
Cpu_thread_component *thread = _lookup_thread(thread_cap);
if (!thread) return;
thread->sigh(sigh_cap);
}

View File

@ -46,15 +46,19 @@ namespace Genode {
{
private:
Platform_thread _platform_thread;
bool _bound; /* pd binding flag */
Platform_thread _platform_thread;
bool _bound; /* pd binding flag */
Signal_context_capability _sigh; /* exception handler */
public:
Cpu_thread_component(const char *name, unsigned priority,
addr_t utcb)
: _platform_thread(name, priority, utcb), _bound(false) { }
Cpu_thread_component(const char *name, unsigned priority, addr_t utcb,
Signal_context_capability sigh)
:
_platform_thread(name, priority, utcb), _bound(false), _sigh(sigh)
{
update_exception_sigh();
}
/************************
@ -64,6 +68,17 @@ namespace Genode {
inline Platform_thread * platform_thread() { return &_platform_thread; }
inline bool bound() const { return _bound; }
inline void bound(bool b) { _bound = b; }
void sigh(Signal_context_capability sigh)
{
sigh = sigh;
update_exception_sigh();
}
/**
* Propagate exception handler to platform thread
*/
void update_exception_sigh();
};
@ -82,6 +97,12 @@ namespace Genode {
created with this
session */
/**
* Exception handler that will be invoked unless overridden by a
* call of 'Cpu_session::exception_handler'.
*/
Signal_context_capability _default_exception_handler;
/**
* Lookup thread in CPU session by its capability
*