on_sig_stack(ts, sp) ? SS_ONSTACK : 0;
}
+int host_interrupt_signal = SIGRTMAX;
+
/*
* The BSD ABIs use the same signal numbers across all the CPU architectures, so
* (unlike Linux) these functions are just the identity mapping. This might not
uintptr_t pc = 0;
bool sync_sig = false;
+ if (host_sig == host_interrupt_signal) {
+ ts->signal_pending = 1;
+ cpu_exit(thread_cpu);
+ return;
+ }
+
/*
* Non-spoofed SIGSEGV and SIGBUS are synchronous, and need special
* handling wrt signal blocking and unwinding.
for (i = 1; i <= TARGET_NSIG; i++) {
host_sig = target_to_host_signal(i);
+ if (host_sig == host_interrupt_signal) {
+ continue;
+ }
sigaction(host_sig, NULL, &oact);
if (oact.sa_sigaction == (void *)SIG_IGN) {
sigact_table[i - 1]._sa_handler = TARGET_SIG_IGN;
sigaction(host_sig, &act, NULL);
}
}
+ sigaction(host_interrupt_signal, &act, NULL);
}
static void handle_pending_signal(CPUArchState *env, int sig,
}
}
+int host_interrupt_signal;
+
static void signal_table_init(const char *rtsig_map)
{
int hsig, tsig, count;
* Attempts for configure "missing" signals via sigaction will be
* silently ignored.
*
- * Reserve one signal for internal usage (see below).
+ * Reserve two signals for internal usage (see below).
*/
- hsig = SIGRTMIN + 1;
+ hsig = SIGRTMIN + 2;
for (tsig = TARGET_SIGRTMIN;
hsig <= SIGRTMAX && tsig <= TARGET_NSIG;
hsig++, tsig++) {
host_to_target_signal_table[SIGABRT] = 0;
for (hsig = SIGRTMIN; hsig <= SIGRTMAX; hsig++) {
if (!host_to_target_signal_table[hsig]) {
- host_to_target_signal_table[hsig] = TARGET_SIGABRT;
- break;
+ if (host_interrupt_signal) {
+ host_to_target_signal_table[hsig] = TARGET_SIGABRT;
+ break;
+ } else {
+ host_interrupt_signal = hsig;
+ }
}
}
if (hsig > SIGRTMAX) {
- fprintf(stderr, "No rt signals left for SIGABRT mapping\n");
+ fprintf(stderr,
+ "No rt signals left for interrupt and SIGABRT mapping\n");
exit(EXIT_FAILURE);
}
}
sigact_table[tsig - 1]._sa_handler = thand;
}
+
+ sigaction(host_interrupt_signal, &act, NULL);
}
/* Force a synchronously taken signal. The kernel force_sig() function
bool sync_sig = false;
void *sigmask;
+ if (host_sig == host_interrupt_signal) {
+ ts->signal_pending = 1;
+ cpu_exit(thread_cpu);
+ return;
+ }
+
/*
* Non-spoofed SIGSEGV and SIGBUS are synchronous, and need special
* handling wrt signal blocking and unwinding. Non-spoofed SIGILL,