summaryrefslogtreecommitdiff
path: root/arch/um/os-Linux/time.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/um/os-Linux/time.c')
-rw-r--r--arch/um/os-Linux/time.c15
1 files changed, 9 insertions, 6 deletions
diff --git a/arch/um/os-Linux/time.c b/arch/um/os-Linux/time.c
index 4d5591d96d8c..f3d4547e5227 100644
--- a/arch/um/os-Linux/time.c
+++ b/arch/um/os-Linux/time.c
@@ -15,6 +15,7 @@
#include <kern_util.h>
#include <os.h>
#include <string.h>
+#include "internal.h"
static timer_t event_high_res_timer = 0;
@@ -98,18 +99,20 @@ long long os_nsecs(void)
*/
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);
}