Commit e42837bc authored by Rafael J. Wysocki's avatar Rafael J. Wysocki Committed by Linus Torvalds

freezer: introduce freezer-friendly waiting macros

Introduce freezer-friendly wrappers around wait_event_interruptible() and
wait_event_interruptible_timeout(), originally defined in <linux/wait.h>, to
be used in freezable kernel threads.  Make some of the freezable kernel
threads use them.

This is necessary for the freezer to stop sending signals to kernel threads,
which is implemented in the next patch.
Signed-off-by: default avatarRafael J. Wysocki <rjw@sisk.pl>
Acked-by: default avatarPavel Machek <pavel@ucw.cz>
Cc: Nigel Cunningham <nigel@nigel.suspend2.net>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 2e131895
...@@ -448,9 +448,8 @@ static int gameport_thread(void *nothing) ...@@ -448,9 +448,8 @@ static int gameport_thread(void *nothing)
set_freezable(); set_freezable();
do { do {
gameport_handle_event(); gameport_handle_event();
wait_event_interruptible(gameport_wait, wait_event_freezable(gameport_wait,
kthread_should_stop() || !list_empty(&gameport_event_list)); kthread_should_stop() || !list_empty(&gameport_event_list));
try_to_freeze();
} while (!kthread_should_stop()); } while (!kthread_should_stop());
printk(KERN_DEBUG "gameport: kgameportd exiting\n"); printk(KERN_DEBUG "gameport: kgameportd exiting\n");
......
...@@ -387,9 +387,8 @@ static int serio_thread(void *nothing) ...@@ -387,9 +387,8 @@ static int serio_thread(void *nothing)
set_freezable(); set_freezable();
do { do {
serio_handle_event(); serio_handle_event();
wait_event_interruptible(serio_wait, wait_event_freezable(serio_wait,
kthread_should_stop() || !list_empty(&serio_event_list)); kthread_should_stop() || !list_empty(&serio_event_list));
try_to_freeze();
} while (!kthread_should_stop()); } while (!kthread_should_stop());
printk(KERN_DEBUG "serio: kseriod exiting\n"); printk(KERN_DEBUG "serio: kseriod exiting\n");
......
...@@ -333,10 +333,9 @@ static int ucb1400_ts_thread(void *_ucb) ...@@ -333,10 +333,9 @@ static int ucb1400_ts_thread(void *_ucb)
timeout = msecs_to_jiffies(10); timeout = msecs_to_jiffies(10);
} }
wait_event_interruptible_timeout(ucb->ts_wait, wait_event_freezable_timeout(ucb->ts_wait,
ucb->irq_pending || ucb->ts_restart || kthread_should_stop(), ucb->irq_pending || ucb->ts_restart || kthread_should_stop(),
timeout); timeout);
try_to_freeze();
} }
/* Send the "pen off" if we are stopping with the pen still active */ /* Send the "pen off" if we are stopping with the pen still active */
......
...@@ -527,7 +527,8 @@ static int dvb_frontend_thread(void *data) ...@@ -527,7 +527,8 @@ static int dvb_frontend_thread(void *data)
up(&fepriv->sem); /* is locked when we enter the thread... */ up(&fepriv->sem); /* is locked when we enter the thread... */
restart: restart:
timeout = wait_event_interruptible_timeout(fepriv->wait_queue, timeout = wait_event_interruptible_timeout(fepriv->wait_queue,
dvb_frontend_should_wakeup(fe) || kthread_should_stop(), dvb_frontend_should_wakeup(fe) || kthread_should_stop()
|| freezing(current),
fepriv->delay); fepriv->delay);
if (kthread_should_stop() || dvb_frontend_is_exiting(fe)) { if (kthread_should_stop() || dvb_frontend_is_exiting(fe)) {
......
...@@ -2870,10 +2870,9 @@ static int hub_thread(void *__unused) ...@@ -2870,10 +2870,9 @@ static int hub_thread(void *__unused)
set_freezable(); set_freezable();
do { do {
hub_events(); hub_events();
wait_event_interruptible(khubd_wait, wait_event_freezable(khubd_wait,
!list_empty(&hub_event_list) || !list_empty(&hub_event_list) ||
kthread_should_stop()); kthread_should_stop());
try_to_freeze();
} while (!kthread_should_stop() || !list_empty(&hub_event_list)); } while (!kthread_should_stop() || !list_empty(&hub_event_list));
pr_debug("%s: khubd exiting\n", usbcore_name); pr_debug("%s: khubd exiting\n", usbcore_name);
......
...@@ -907,12 +907,9 @@ static int usb_stor_scan_thread(void * __us) ...@@ -907,12 +907,9 @@ static int usb_stor_scan_thread(void * __us)
if (delay_use > 0) { if (delay_use > 0) {
printk(KERN_DEBUG "usb-storage: waiting for device " printk(KERN_DEBUG "usb-storage: waiting for device "
"to settle before scanning\n"); "to settle before scanning\n");
retry: wait_event_freezable_timeout(us->delay_wait,
wait_event_interruptible_timeout(us->delay_wait,
test_bit(US_FLIDX_DISCONNECTING, &us->flags), test_bit(US_FLIDX_DISCONNECTING, &us->flags),
delay_use * HZ); delay_use * HZ);
if (try_to_freeze())
goto retry;
} }
/* If the device is still connected, perform the scanning */ /* If the device is still connected, perform the scanning */
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#define FREEZER_H_INCLUDED #define FREEZER_H_INCLUDED
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/wait.h>
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
/* /*
...@@ -126,6 +127,36 @@ static inline void set_freezable(void) ...@@ -126,6 +127,36 @@ static inline void set_freezable(void)
current->flags &= ~PF_NOFREEZE; current->flags &= ~PF_NOFREEZE;
} }
/*
* Freezer-friendly wrappers around wait_event_interruptible() and
* wait_event_interruptible_timeout(), originally defined in <linux/wait.h>
*/
#define wait_event_freezable(wq, condition) \
({ \
int __retval; \
do { \
__retval = wait_event_interruptible(wq, \
(condition) || freezing(current)); \
if (__retval && !freezing(current)) \
break; \
else if (!(condition)) \
__retval = -ERESTARTSYS; \
} while (try_to_freeze()); \
__retval; \
})
#define wait_event_freezable_timeout(wq, condition, timeout) \
({ \
long __retval = timeout; \
do { \
__retval = wait_event_interruptible_timeout(wq, \
(condition) || freezing(current), \
__retval); \
} while (try_to_freeze()); \
__retval; \
})
#else /* !CONFIG_PM_SLEEP */ #else /* !CONFIG_PM_SLEEP */
static inline int frozen(struct task_struct *p) { return 0; } static inline int frozen(struct task_struct *p) { return 0; }
static inline int freezing(struct task_struct *p) { return 0; } static inline int freezing(struct task_struct *p) { return 0; }
...@@ -143,6 +174,13 @@ static inline void freezer_do_not_count(void) {} ...@@ -143,6 +174,13 @@ static inline void freezer_do_not_count(void) {}
static inline void freezer_count(void) {} static inline void freezer_count(void) {}
static inline int freezer_should_skip(struct task_struct *p) { return 0; } static inline int freezer_should_skip(struct task_struct *p) { return 0; }
static inline void set_freezable(void) {} static inline void set_freezable(void) {}
#define wait_event_freezable(wq, condition) \
wait_event_interruptible(wq, condition)
#define wait_event_freezable_timeout(wq, condition, timeout) \
wait_event_interruptible_timeout(wq, condition, timeout)
#endif /* !CONFIG_PM_SLEEP */ #endif /* !CONFIG_PM_SLEEP */
#endif /* FREEZER_H_INCLUDED */ #endif /* FREEZER_H_INCLUDED */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment