extern int get_current_pid(void);
extern int copy_from_user_proc(void *to, void *from, int size);
extern char *uml_strdup(const char *string);
+int uml_need_resched(void);
extern unsigned long to_irq_stack(unsigned long *mask_out);
extern unsigned long from_irq_stack(int nested);
/* Is in_interrupt() really needed? */
}
+int uml_need_resched(void)
+{
+ return need_resched();
+}
+
extern exitcall_t __uml_exitcall_begin, __uml_exitcall_end;
void do_uml_exitcalls(void)
#include <um_malloc.h>
#include <sys/ucontext.h>
#include <timetravel.h>
+#include "internal.h"
void (*sig_info[NSIG])(int, struct siginfo *, struct uml_pt_regs *, void *mc) = {
[SIGTRAP] = relay_signal,
set_handler(SIGALRM);
}
+int timer_alarm_pending(void)
+{
+ return !!(signals_pending & SIGALRM_MASK);
+}
+
void set_sigstack(void *sig_stack, int size)
{
stack_t stack = {
#include <kern_util.h>
#include <os.h>
#include <string.h>
+#include "internal.h"
static timer_t event_high_res_timer = 0;
*/
void os_idle_sleep(void)
{
- struct itimerspec its;
sigset_t set, old;
- /* block SIGALRM while we analyze the timer state */
+ /* Block SIGALRM while performing the need_resched check. */
sigemptyset(&set);
sigaddset(&set, SIGALRM);
sigprocmask(SIG_BLOCK, &set, &old);
- /* check the timer, and if it'll fire then wait for it */
- timer_gettime(event_high_res_timer, &its);
- if (its.it_value.tv_sec || its.it_value.tv_nsec)
+ /*
+ * Because disabling IRQs does not block SIGALRM, it is also
+ * necessary to check for any pending timer alarms.
+ */
+ if (!uml_need_resched() && !timer_alarm_pending())
sigsuspend(&old);
- /* either way, restore the signal mask */
+
+ /* Restore the signal mask. */
sigprocmask(SIG_UNBLOCK, &set, NULL);
}