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; case KILL_PD: do_kill_pd(user); return;
default: default:
PERR("invalid syscall"); PERR("invalid syscall");
user->crash(); user->stop();
reset_lap_time(); reset_lap_time();
} }
} }

View File

@ -17,21 +17,21 @@
using namespace Kernel; 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; Fifo_element _handlers_fe;
Signal_receiver * _receiver; Signal_receiver * _receiver;
/**
* Backend for for destructor and cancel_waiting
*/
void _cancel_waiting();
/** /**
* Let the handler block for signal receipt * Let the handler block for signal receipt
* *
@ -86,7 +91,12 @@ class Kernel::Signal_handler
/** /**
* Destructor * 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 class Kernel::Signal_context_killer
@ -97,6 +107,11 @@ class Kernel::Signal_context_killer
Signal_context * _context; Signal_context * _context;
/**
* Backend for for destructor and cancel_waiting
*/
void _cancel_waiting();
/** /**
* Notice that the destruction is pending * Notice that the destruction is pending
*/ */
@ -117,7 +132,12 @@ class Kernel::Signal_context_killer
/** /**
* Destructor * 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 class Kernel::Signal_receiver_killer
@ -128,6 +148,11 @@ class Kernel::Signal_receiver_killer
Signal_receiver * _receiver; Signal_receiver * _receiver;
/**
* Backend for for destructor and cancel_waiting
*/
void _cancel_waiting();
/** /**
* Notice that the destruction is pending * Notice that the destruction is pending
*/ */
@ -148,7 +173,12 @@ class Kernel::Signal_receiver_killer
/** /**
* Destructor * 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 class Kernel::Signal_context
@ -188,7 +218,7 @@ class Kernel::Signal_context
/** /**
* Notice that the killer of the context has been destructed * Notice that the killer of the context has been destructed
*/ */
void _killer_destructed() { _killer = 0; } void _killer_cancelled() { _killer = 0; }
/** /**
* Destructor * Destructor
@ -275,6 +305,7 @@ class Kernel::Signal_receiver
public Signal_context_killer public Signal_context_killer
{ {
friend class Signal_context; friend class Signal_context;
friend class Signal_handler;
friend class Signal_receiver_killer; friend class Signal_receiver_killer;
private: 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; 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 * Create a context that is assigned to the receiver
* *

View File

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