summary refs log tree commit diff
path: root/arch/um/os-Linux
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2020-12-02 20:58:07 +0100
committerRichard Weinberger <richard@nod.at>2020-12-13 22:22:49 +0100
commita374b7cb1ea648a27ceaa2dea19aa967725e938b (patch)
tree3caccdb36c1cc214f10a2f2d2e267acee1f101a6 /arch/um/os-Linux
parent92dcd3d31843fbe1a95d880dc912e1f6beac6632 (diff)
downloadlinux-a374b7cb1ea648a27ceaa2dea19aa967725e938b.tar.gz
um: Support suspend to RAM
With all the previous bits in place, we can now also support
suspend to RAM, in the sense that everything is suspended,
not just most, including userspace, processes like in s2idle.

Since um_idle_sleep() now waits forever, we can simply call
that to "suspend" the system.

As before, you can wake it up using SIGUSR1 since we're just
in a pause() call that only needs to return.

In order to implement selective resume from certain devices,
and not have any arbitrary device interrupt wake up, suspend
interrupts by removing SIGIO notification (O_ASYNC) from all
the FDs that are not supposed to wake up the system. However,
swap out the handler so we don't actually handle the SIGIO as
an interrupt.

Since we're in pause(), the mere act of receiving SIGIO wakes
us up, and then after things have been restored enough, re-set
O_ASYNC for all previously suspended FDs, reinstall the proper
SIGIO handler, and send SIGIO to self to process anything that
might now be pending.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Richard Weinberger <richard@nod.at>
Diffstat (limited to 'arch/um/os-Linux')
-rw-r--r--arch/um/os-Linux/signal.c5
1 files changed, 5 insertions, 0 deletions
diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c
index 0a2ea84033b4..510e956b4320 100644
--- a/arch/um/os-Linux/signal.c
+++ b/arch/um/os-Linux/signal.c
@@ -234,6 +234,11 @@ void set_handler(int sig)
 		panic("sigprocmask failed - errno = %d\n", errno);
 }
 
+void send_sigio_to_self(void)
+{
+	kill(os_getpid(), SIGIO);
+}
+
 int change_sig(int signal, int on)
 {
 	sigset_t sigset;