From: "Rafael J. Wysocki" <rjw@sisk.pl>
To: Alan Stern <stern@rowland.harvard.edu>
Cc: Linux-pm mailing list <linux-pm@lists.linux-foundation.org>
Subject: Re: [RFC] Add the "icebox"
Date: Mon, 5 Nov 2007 23:11:07 +0100 [thread overview]
Message-ID: <200711052311.08392.rjw@sisk.pl> (raw)
In-Reply-To: <Pine.LNX.4.44L0.0711051611190.2800-100000@iolanthe.rowland.org>
On Monday, 5 of November 2007, Alan Stern wrote:
> Rafael:
>
> This patch adds the icebox, for use by kernel threads that want to
> freeze themselves without using the freezer -- which is likely to crop
> up when the freezer gets eliminated.
>
> It's straightforward enough. It could be used as-is, for example for
> freezing workqueue threads. Using it for other sorts of kernel threads
> seems to be rather difficult, requiring a fair amount of extra code
> that's hard to centralize since each thread will have to be woken up
> its own way.
>
> Do you have any particular suggestions?
I like the idea, but I think that start_icebox() should be called after
freeze_processes(). Similarly, IMO it's better to call stop_icebox() before
thaw_processes().
Greetings,
Rafael
> Index: usb-2.6/include/linux/freezer.h
> ===================================================================
> --- usb-2.6.orig/include/linux/freezer.h
> +++ usb-2.6/include/linux/freezer.h
> @@ -157,6 +157,12 @@ static inline void set_freezable(void)
> } while (try_to_freeze()); \
> __retval; \
> })
> +
> +/*
> + * Kernel threads that want to freeze themselves go into the icebox.
> + */
> +extern void icebox(void);
> +
> #else /* !CONFIG_PM_SLEEP */
> static inline int frozen(struct task_struct *p) { return 0; }
> static inline int freezing(struct task_struct *p) { return 0; }
> @@ -181,6 +187,7 @@ static inline void set_freezable(void) {
> #define wait_event_freezable_timeout(wq, condition, timeout) \
> wait_event_interruptible_timeout(wq, condition, timeout)
>
> +static inline void icebox(void) {}
> #endif /* !CONFIG_PM_SLEEP */
>
> #endif /* FREEZER_H_INCLUDED */
> Index: usb-2.6/kernel/power/power.h
> ===================================================================
> --- usb-2.6.orig/kernel/power/power.h
> +++ usb-2.6/kernel/power/power.h
> @@ -205,3 +205,8 @@ static inline int suspend_devices_and_en
>
> /* kernel/power/process.c */
> extern int pm_notifier_call_chain(unsigned long val);
> +
> +#ifdef CONFIG_PM_SLEEP
> +extern void start_icebox(void);
> +extern void stop_icebox(void);
> +#endif
> Index: usb-2.6/kernel/power/main.c
> ===================================================================
> --- usb-2.6.orig/kernel/power/main.c
> +++ usb-2.6/kernel/power/main.c
> @@ -71,6 +71,8 @@ static int suspend_prepare(void)
> if (!suspend_ops || !suspend_ops->enter)
> return -EPERM;
>
> + start_icebox();
> +
> error = pm_notifier_call_chain(PM_SUSPEND_PREPARE);
> if (error)
> goto Finish;
> @@ -98,6 +100,7 @@ static int suspend_prepare(void)
> thaw_processes();
> pm_restore_console();
> Finish:
> + stop_icebox();
> pm_notifier_call_chain(PM_POST_SUSPEND);
> return error;
> }
> @@ -191,6 +194,7 @@ static void suspend_finish(void)
> {
> thaw_processes();
> pm_restore_console();
> + stop_icebox();
> pm_notifier_call_chain(PM_POST_SUSPEND);
> }
>
> Index: usb-2.6/kernel/power/disk.c
> ===================================================================
> --- usb-2.6.orig/kernel/power/disk.c
> +++ usb-2.6/kernel/power/disk.c
> @@ -389,6 +389,8 @@ int hibernate(void)
> goto Unlock;
> }
>
> + start_icebox();
> +
> error = pm_notifier_call_chain(PM_HIBERNATION_PREPARE);
> if (error)
> goto Exit;
> @@ -431,6 +433,7 @@ int hibernate(void)
> Finish:
> free_basic_memory_bitmaps();
> Exit:
> + stop_icebox();
> pm_notifier_call_chain(PM_POST_HIBERNATION);
> atomic_inc(&snapshot_device_available);
> Unlock:
> @@ -489,6 +492,8 @@ static int software_resume(void)
> goto Unlock;
> }
>
> + start_icebox();
> +
> error = pm_notifier_call_chain(PM_RESTORE_PREPARE);
> if (error)
> goto Finish;
> @@ -516,6 +521,7 @@ static int software_resume(void)
> Done:
> free_basic_memory_bitmaps();
> Finish:
> + stop_icebox();
> pm_notifier_call_chain(PM_POST_RESTORE);
> atomic_inc(&snapshot_device_available);
> /* For success case, the suspend path will release the lock */
> Index: usb-2.6/kernel/power/user.c
> ===================================================================
> --- usb-2.6.orig/kernel/power/user.c
> +++ usb-2.6/kernel/power/user.c
> @@ -45,6 +45,7 @@ static int snapshot_open(struct inode *i
> {
> struct snapshot_data *data;
> int error;
> + unsigned long cancel;
>
> if (!atomic_add_unless(&snapshot_device_available, -1, 0))
> return -EBUSY;
> @@ -61,21 +62,22 @@ static int snapshot_open(struct inode *i
> data = &snapshot_state;
> filp->private_data = data;
> memset(&data->handle, 0, sizeof(struct snapshot_handle));
> + start_icebox();
> if ((filp->f_flags & O_ACCMODE) == O_RDONLY) {
> data->swap = swsusp_resume_device ?
> swap_type_of(swsusp_resume_device, 0, NULL) : -1;
> data->mode = O_RDONLY;
> error = pm_notifier_call_chain(PM_RESTORE_PREPARE);
> - if (error)
> - pm_notifier_call_chain(PM_POST_RESTORE);
> + cancel = PM_POST_RESTORE;
> } else {
> data->swap = -1;
> data->mode = O_WRONLY;
> error = pm_notifier_call_chain(PM_HIBERNATION_PREPARE);
> - if (error)
> - pm_notifier_call_chain(PM_POST_HIBERNATION);
> + cancel = PM_POST_HIBERNATION;
> }
> if (error) {
> + stop_icebox();
> + pm_notifier_call_chain(cancel);
> atomic_inc(&snapshot_device_available);
> return error;
> }
> @@ -99,6 +101,7 @@ static int snapshot_release(struct inode
> thaw_processes();
> mutex_unlock(&pm_mutex);
> }
> + stop_icebox();
> pm_notifier_call_chain(data->mode == O_WRONLY ?
> PM_POST_HIBERNATION : PM_POST_RESTORE);
> atomic_inc(&snapshot_device_available);
> Index: usb-2.6/kernel/power/process.c
> ===================================================================
> --- usb-2.6.orig/kernel/power/process.c
> +++ usb-2.6/kernel/power/process.c
> @@ -14,6 +14,8 @@
> #include <linux/syscalls.h>
> #include <linux/freezer.h>
>
> +#include "power.h"
> +
> /*
> * Timeout for stopping processes
> */
> @@ -305,3 +307,49 @@ int pm_notifier_call_chain(unsigned long
> return (blocking_notifier_call_chain(&pm_chain_head, val, NULL)
> == NOTIFY_BAD) ? -EINVAL : 0;
> }
> +
> +/*
> + * Routines for kernel threads that want to freeze themselves
> + */
> +static DECLARE_WAIT_QUEUE_HEAD(icebox_wait_queue_head);
> +static int icebox_active;
> +
> +/**
> + * start_icebox -- activate the icebox
> + *
> + * Kernel power code should call this routine before sending the
> + * PM_HIBERNATION_PREPARE or PM_SUSPEND_PREPARE notifications.
> + */
> +void start_icebox(void)
> +{
> + icebox_active = 1;
> +}
> +
> +/**
> + * stop_icebox -- deactivate the icebox and awaken waiting threads
> + *
> + * Kernel power code should call this routine before sending the
> + * PM_POST_HIBERNATION or PM_POST_SUSPEND notifications.
> + */
> +void stop_icebox(void)
> +{
> + icebox_active = 0;
> + wake_up_all(&icebox_wait_queue_head);
> +}
> +
> +/**
> + * icebox -- place for kernel threads to wait during suspend or hibernation
> + *
> + * Threads can call this routine at any time. It will return immediately
> + * unless a system suspend or hibernation has started and the icebox is
> + * active, in which case it won't return until the suspend/hibernation
> + * is over.
> + *
> + * Freezable kernel threads should use this routine rather than relying on
> + * the freezer.
> + */
> +void icebox(void)
> +{
> + wait_event(icebox_wait_queue_head, !icebox_active);
> +}
> +EXPORT_SYMBOL_GPL(icebox);
>
>
>
--
"Premature optimization is the root of all evil." - Donald Knuth
next prev parent reply other threads:[~2007-11-05 22:11 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-11-05 21:27 [RFC] Add the "icebox" Alan Stern
2007-11-05 22:11 ` Rafael J. Wysocki [this message]
2007-11-06 15:08 ` Alan Stern
2007-11-07 17:16 ` Alan Stern
2007-11-07 22:31 ` Rafael J. Wysocki
2007-11-07 22:28 ` Alan Stern
2007-11-07 23:32 ` Rafael J. Wysocki
2007-11-07 8:58 ` Johannes Berg
2007-11-07 15:47 ` Alan Stern
2007-11-07 15:54 ` Johannes Berg
2007-11-07 16:47 ` Alan Stern
2007-11-07 16:53 ` Johannes Berg
2007-11-07 19:49 ` Mark Gross
2007-11-07 20:02 ` Alan Stern
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=200711052311.08392.rjw@sisk.pl \
--to=rjw@sisk.pl \
--cc=linux-pm@lists.linux-foundation.org \
--cc=stern@rowland.harvard.edu \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox