1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-12-25 06:23:53 +01:00

native: irq_cpu: Rewrite IRQs (de)registration

This commit is contained in:
Benoît Canet 2015-07-04 20:26:51 +02:00
parent 4832a1a6b0
commit ced541cc67

View File

@ -356,6 +356,55 @@ void native_isr_entry(int sig, siginfo_t *info, void *context)
#endif
}
/**
* Add or remove handler for signal
*
* To be called with interrupts disabled
*
*/
void set_signal_handler(int sig, bool add)
{
struct sigaction sa;
int ret;
/* update the signal mask so enableIRQ()/disableIRQ() will be aware */
if (add) {
_native_syscall_enter();
ret = sigdelset(&_native_sig_set, sig);
_native_syscall_leave();
} else {
_native_syscall_enter();
ret = sigaddset(&_native_sig_set, sig);
_native_syscall_leave();
}
if (ret == -1) {
err(EXIT_FAILURE, "set_signal_handler: sigdelset");
}
memset(&sa, 0, sizeof(sa));
/* Disable other signal during execution of the handler for this signal. */
memcpy(&sa.sa_mask, &_native_sig_set_dint, sizeof(sa.sa_mask));
/* restart interrupted systems call and custom signal stack */
sa.sa_flags = SA_RESTART | SA_ONSTACK;
if (add) {
sa.sa_flags |= SA_SIGINFO; /* sa.sa_sigaction is used */
sa.sa_sigaction = native_isr_entry;
} else
{
sa.sa_handler = SIG_IGN;
}
_native_syscall_enter();
if (sigaction(sig, &sa, NULL)) {
err(EXIT_FAILURE, "set_signal_handler: sigaction");
}
_native_syscall_leave();
}
/**
* register signal/interrupt handler for signal sig
*
@ -366,26 +415,12 @@ int register_interrupt(int sig, _native_callback_t handler)
{
DEBUG("register_interrupt\n");
_native_syscall_enter();
if (sigdelset(&_native_sig_set, sig)) {
err(EXIT_FAILURE, "register_interrupt: sigdelset");
}
unsigned state = disableIRQ();
native_irq_handlers[sig] = handler;
set_signal_handler(sig, true);
/* set current dINT sigmask for all signals */
struct sigaction sa;
sa.sa_sigaction = native_isr_entry;
sa.sa_mask = _native_sig_set_dint;
sa.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
for (int i = 0; i < 255; i++) {
if (native_irq_handlers[i] != NULL) {
if (sigaction(sig, &sa, NULL)) {
err(EXIT_FAILURE, "register_interrupt: sigaction");
}
}
}
_native_syscall_leave();
restoreIRQ(state);
return 0;
}
@ -397,31 +432,12 @@ int unregister_interrupt(int sig)
{
DEBUG("unregister_interrupt\n");
_native_syscall_enter();
if (sigaddset(&_native_sig_set, sig) == -1) {
err(EXIT_FAILURE, "unregister_interrupt: sigaddset");
}
unsigned state = disableIRQ();
set_signal_handler(sig, false);
native_irq_handlers[sig] = NULL;
/* reset signal handler for sig */
struct sigaction sa;
sa.sa_handler = SIG_IGN; /* there may be late signals, so we need to ignore those */
sa.sa_mask = _native_sig_set_dint;
sa.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
if (sigaction(sig, &sa, NULL)) {
err(EXIT_FAILURE, "unregister_interrupt: sigaction");
}
/* change sigmask for remaining signal handlers */
sa.sa_sigaction = native_isr_entry;
for (int i = 0; i < 255; i++) {
if (native_irq_handlers[i] != NULL) {
if (sigaction(sig, &sa, NULL)) {
err(EXIT_FAILURE, "unregister_interrupt: sigaction");
}
}
}
_native_syscall_leave();
restoreIRQ(state);
return 0;
}