hw: kill signal receivers

ref #899
This commit is contained in:
Martin Stein 2013-09-19 16:13:51 +02:00 committed by Norman Feske
parent 26db598fc0
commit 6912e638fb
4 changed files with 115 additions and 75 deletions

View File

@ -899,7 +899,7 @@ namespace Kernel
case KILL_PD: do_kill_pd(user); return;
default:
PERR("invalid syscall");
user->crash();
user->stop();
reset_lap_time();
}
}

View File

@ -17,21 +17,21 @@
using namespace Kernel;
Signal_handler::~Signal_handler()
void Signal_handler::_cancel_waiting()
{
if (_receiver) { _receiver->remove_handler(this); }
if (_receiver) { _receiver->_handler_cancelled(this); }
}
Signal_context_killer::~Signal_context_killer()
void Signal_context_killer::_cancel_waiting()
{
if (_context) { _context->_killer_destructed(); }
if (_context) { _context->_killer_cancelled(); }
}
Signal_receiver_killer::~Signal_receiver_killer()
void Signal_receiver_killer::_cancel_waiting()
{
if (_receiver) { _receiver->_killer_destructed(); }
if (_receiver) { _receiver->_killer_cancelled(); }
}

View File

@ -61,6 +61,11 @@ class Kernel::Signal_handler
Fifo_element _handlers_fe;
Signal_receiver * _receiver;
/**
* Backend for for destructor and cancel_waiting
*/
void _cancel_waiting();
/**
* Let the handler block for signal receipt
*
@ -86,7 +91,12 @@ class Kernel::Signal_handler
/**
* Destructor
*/
virtual ~Signal_handler();
virtual ~Signal_handler() { _cancel_waiting(); }
/**
* Stop waiting for a signal receiver
*/
void cancel_waiting() { _cancel_waiting(); }
};
class Kernel::Signal_context_killer
@ -97,6 +107,11 @@ class Kernel::Signal_context_killer
Signal_context * _context;
/**
* Backend for for destructor and cancel_waiting
*/
void _cancel_waiting();
/**
* Notice that the destruction is pending
*/
@ -117,7 +132,12 @@ class Kernel::Signal_context_killer
/**
* Destructor
*/
virtual ~Signal_context_killer();
virtual ~Signal_context_killer() { _cancel_waiting(); }
/**
* Stop waiting for a signal context
*/
void cancel_waiting() { _cancel_waiting(); }
};
class Kernel::Signal_receiver_killer
@ -128,6 +148,11 @@ class Kernel::Signal_receiver_killer
Signal_receiver * _receiver;
/**
* Backend for for destructor and cancel_waiting
*/
void _cancel_waiting();
/**
* Notice that the destruction is pending
*/
@ -148,7 +173,12 @@ class Kernel::Signal_receiver_killer
/**
* Destructor
*/
virtual ~Signal_receiver_killer();
virtual ~Signal_receiver_killer() { _cancel_waiting(); }
/**
* Stop waiting for a signal receiver
*/
void cancel_waiting() { _cancel_waiting(); }
};
class Kernel::Signal_context
@ -188,7 +218,7 @@ class Kernel::Signal_context
/**
* Notice that the killer of the context has been destructed
*/
void _killer_destructed() { _killer = 0; }
void _killer_cancelled() { _killer = 0; }
/**
* Destructor
@ -275,6 +305,7 @@ class Kernel::Signal_receiver
public Signal_context_killer
{
friend class Signal_context;
friend class Signal_handler;
friend class Signal_receiver_killer;
private:
@ -340,9 +371,17 @@ class Kernel::Signal_receiver
}
/**
* Notice that the killer of the receiver has been destructed
* Notice that the killer of the receiver has cancelled waiting
*/
void _killer_destructed() { _killer = 0; }
void _killer_cancelled() { _killer = 0; }
/**
* Notice that handler 'h' has cancelled waiting
*/
void _handler_cancelled(Signal_handler * const h)
{
_handlers.remove(&h->_handlers_fe);
}
/***************************
@ -386,14 +425,6 @@ class Kernel::Signal_receiver
return 0;
}
/**
* Stop a handler 'h' from waiting for signals of the receiver
*/
void remove_handler(Signal_handler * const h)
{
_handlers.remove(&h->_handlers_fe);
}
/**
* Create a context that is assigned to the receiver
*

View File

@ -97,16 +97,17 @@ class Kernel::Thread
enum State
{
SCHEDULED = 1,
AWAIT_START = 2,
AWAIT_IPC = 3,
AWAIT_RESUME = 4,
AWAIT_PAGER = 5,
AWAIT_PAGER_IPC = 6,
AWAIT_IRQ = 7,
AWAIT_SIGNAL = 8,
AWAIT_SIGNAL_CONTEXT_KILL = 9,
CRASHED = 10,
SCHEDULED = 1,
AWAIT_START = 2,
AWAIT_IPC = 3,
AWAIT_RESUME = 4,
AWAIT_PAGER = 5,
AWAIT_PAGER_IPC = 6,
AWAIT_IRQ = 7,
AWAIT_SIGNAL = 8,
AWAIT_SIGNAL_CONTEXT_KILL = 9,
AWAIT_SIGNAL_RECEIVER_KILL = 10,
STOPPED = 11,
};
Platform_thread * const _platform_thread;
@ -127,22 +128,40 @@ class Kernel::Thread
_state = SCHEDULED;
}
/***************************
** Signal_context_killer **
***************************/
void _signal_context_kill_pending()
{
cpu_scheduler()->remove(this);
assert(_state == SCHEDULED);
_state = AWAIT_SIGNAL_CONTEXT_KILL;
cpu_scheduler()->remove(this);
}
void _signal_context_kill_done()
{
if (_state != AWAIT_SIGNAL_CONTEXT_KILL) {
PDBG("ignore unexpected signal-context destruction");
return;
}
assert(_state == AWAIT_SIGNAL_CONTEXT_KILL);
user_arg_0(0);
_schedule();
}
/****************************
** Signal_receiver_killer **
****************************/
void _signal_receiver_kill_pending()
{
assert(_state == SCHEDULED);
_state = AWAIT_SIGNAL_RECEIVER_KILL;
cpu_scheduler()->remove(this);
}
void _signal_receiver_kill_done()
{
assert(_state == AWAIT_SIGNAL_RECEIVER_KILL);
user_arg_0(0);
_schedule();
}
@ -167,15 +186,6 @@ class Kernel::Thread
}
/****************************
** Signal_receiver_killer **
****************************/
void _signal_receiver_kill_pending() { PERR("not implemented"); }
void _signal_receiver_kill_done() { PERR("not implemented"); }
/**************
** Ipc_node **
**************/
@ -188,7 +198,7 @@ class Kernel::Thread
return;
default:
PERR("wrong thread state to receive IPC");
crash();
stop();
return;
}
}
@ -203,7 +213,7 @@ class Kernel::Thread
return;
default:
PERR("wrong thread state to await IPC");
crash();
stop();
return;
}
}
@ -223,7 +233,7 @@ class Kernel::Thread
return;
default:
PERR("wrong thread state to receive IPC");
crash();
stop();
return;
}
}
@ -233,23 +243,23 @@ class Kernel::Thread
switch (_state) {
case AWAIT_IPC:
PERR("failed to receive IPC");
crash();
stop();
return;
case SCHEDULED:
PERR("failed to receive IPC");
crash();
stop();
return;
case AWAIT_PAGER_IPC:
PERR("failed to get pagefault resolved");
crash();
stop();
return;
case AWAIT_PAGER:
PERR("failed to get pagefault resolved");
crash();
stop();
return;
default:
PERR("wrong thread state to cancel IPC");
crash();
stop();
return;
}
}
@ -286,12 +296,12 @@ class Kernel::Thread
{ }
/**
* Suspend the thread due to unrecoverable misbehavior
* Suspend the thread unrecoverably
*/
void crash()
void stop()
{
if (_state == SCHEDULED) { cpu_scheduler()->remove(this); }
_state = CRASHED;
_state = STOPPED;
}
/**
@ -369,15 +379,6 @@ class Kernel::Thread
_state = AWAIT_RESUME;
}
/**
* Stop this thread
*/
void stop()
{
cpu_scheduler()->remove(this);
_state = AWAIT_START;
}
/**
* Resume this thread
*/
@ -388,36 +389,44 @@ class Kernel::Thread
_schedule();
return 0;
case AWAIT_PAGER:
/* pagefault has been resolved before pager replied */
_state = AWAIT_PAGER_IPC;
return 0;
case AWAIT_PAGER_IPC:
PERR("cancel message receipt");
Ipc_node::cancel_waiting();
return 0;
case SCHEDULED:
return 1;
case AWAIT_IPC:
PDBG("cancel IPC receipt");
PERR("cancel message receipt");
Ipc_node::cancel_waiting();
_schedule();
return 0;
case AWAIT_IRQ:
PDBG("cancel IRQ receipt");
PERR("cancel interrupt receipt");
Irq_receiver::cancel_waiting();
_schedule();
return 0;
case AWAIT_SIGNAL:
PDBG("cancel signal receipt");
_signal_receiver->remove_handler(this);
PERR("cancel signal receipt");
Signal_handler::cancel_waiting();
_schedule();
return 0;
case AWAIT_SIGNAL_CONTEXT_KILL:
PDBG("cancel signal context destruction");
PERR("cancel signal context destruction");
Signal_context_killer::cancel_waiting();
_schedule();
return 0;
case AWAIT_SIGNAL_RECEIVER_KILL:
PERR("cancel signal receiver destruction");
Signal_receiver_killer::cancel_waiting();
_schedule();
return 0;
case AWAIT_START:
default:
PERR("wrong state to resume thread");
crash();
return -1;
case STOPPED:;
}
PERR("failed to resume thread");
return -1;
}
/**