mirror of
https://github.com/torvalds/linux.git
synced 2026-05-31 02:24:24 +02:00
um: Determine sleep based on need_resched()
With SMP and NO_HZ enabled, the CPU may still need to sleep even if the timer is disarmed. Switch to deciding whether to sleep based on pending resched. Additionally, because disabling IRQs does not block SIGALRM, it is also necessary to check for any pending timer alarms. This is a preparation for adding SMP support. Signed-off-by: Tiwei Bie <tiwei.btw@antgroup.com> Link: https://patch.msgid.link/20251027001815.1666872-4-tiwei.bie@linux.dev Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
9e5a9f1c9b
commit
2670917c2f
|
|
@ -51,6 +51,7 @@ extern int __uml_cant_sleep(void);
|
|||
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);
|
||||
|
|
|
|||
|
|
@ -223,6 +223,11 @@ int __uml_cant_sleep(void) {
|
|||
/* 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)
|
||||
|
|
|
|||
|
|
@ -15,6 +15,11 @@ void scan_elf_aux(char **envp);
|
|||
*/
|
||||
void check_tmpexec(void);
|
||||
|
||||
/*
|
||||
* signal.c
|
||||
*/
|
||||
int timer_alarm_pending(void);
|
||||
|
||||
/*
|
||||
* skas/process.c
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
#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,
|
||||
|
|
@ -159,6 +160,11 @@ void timer_set_signal_handler(void)
|
|||
set_handler(SIGALRM);
|
||||
}
|
||||
|
||||
int timer_alarm_pending(void)
|
||||
{
|
||||
return !!(signals_pending & SIGALRM_MASK);
|
||||
}
|
||||
|
||||
void set_sigstack(void *sig_stack, int size)
|
||||
{
|
||||
stack_t stack = {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user