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:
parent
4832a1a6b0
commit
ced541cc67
@ -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;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user