freezer: introduce freezer-friendly waiting macros
authorRafael J. Wysocki <rjw@sisk.pl>
Thu, 18 Oct 2007 10:04:45 +0000 (03:04 -0700)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>
Thu, 18 Oct 2007 21:37:19 +0000 (14:37 -0700)
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: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Pavel Machek <pavel@ucw.cz>
Cc: Nigel Cunningham <nigel@nigel.suspend2.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
drivers/input/gameport/gameport.c
drivers/input/serio/serio.c
drivers/input/touchscreen/ucb1400_ts.c
drivers/media/dvb/dvb-core/dvb_frontend.c
drivers/usb/core/hub.c
drivers/usb/storage/usb.c
include/linux/freezer.h

index 20896d5e5f0e640389161dbecde47c1d3b21992e..ec1b6cfefcd3274d9e645e7ee2e944dd0ded0d93 100644 (file)
@@ -448,9 +448,8 @@ static int gameport_thread(void *nothing)
        set_freezable();
        do {
                gameport_handle_event();
-               wait_event_interruptible(gameport_wait,
+               wait_event_freezable(gameport_wait,
                        kthread_should_stop() || !list_empty(&gameport_event_list));
-               try_to_freeze();
        } while (!kthread_should_stop());
 
        printk(KERN_DEBUG "gameport: kgameportd exiting\n");
index b3bc15acd3f5604979874f4311c5f56daf8fd1eb..7f5293828fbff2e5325c612a93f3ff449cdfa958 100644 (file)
@@ -387,9 +387,8 @@ static int serio_thread(void *nothing)
        set_freezable();
        do {
                serio_handle_event();
-               wait_event_interruptible(serio_wait,
+               wait_event_freezable(serio_wait,
                        kthread_should_stop() || !list_empty(&serio_event_list));
-               try_to_freeze();
        } while (!kthread_should_stop());
 
        printk(KERN_DEBUG "serio: kseriod exiting\n");
index 86aed64ec0fb9dd54c5ed3ec1b134f62a2615d6e..89373b01d8f5694148dab2f6ccf6d67839c65ee6 100644 (file)
@@ -333,10 +333,9 @@ static int ucb1400_ts_thread(void *_ucb)
                        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(),
                        timeout);
-               try_to_freeze();
        }
 
        /* Send the "pen off" if we are stopping with the pen still active */
index b203640ef1c587e7c4f294a7b0be8f2bd9f923a8..445f0266557754f739b5b406abf8f5e5f55a63a0 100644 (file)
@@ -527,7 +527,8 @@ static int dvb_frontend_thread(void *data)
                up(&fepriv->sem);           /* is locked when we enter the thread... */
 restart:
                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);
 
                if (kthread_should_stop() || dvb_frontend_is_exiting(fe)) {
index 60a8f55a0cc7d552887dcbb17c34584c3d8cc071..036c3dea855e66d4df3186dd83df3ecbd20542d7 100644 (file)
@@ -2870,10 +2870,9 @@ static int hub_thread(void *__unused)
        set_freezable();
        do {
                hub_events();
-               wait_event_interruptible(khubd_wait,
+               wait_event_freezable(khubd_wait,
                                !list_empty(&hub_event_list) ||
                                kthread_should_stop());
-               try_to_freeze();
        } while (!kthread_should_stop() || !list_empty(&hub_event_list));
 
        pr_debug("%s: khubd exiting\n", usbcore_name);
index 3451e8d03ab0e4653ff2f7208077f565f7294e19..ac6114eea0c3008f6f328ecd1bcf74368c837929 100644 (file)
@@ -907,12 +907,9 @@ static int usb_stor_scan_thread(void * __us)
        if (delay_use > 0) {
                printk(KERN_DEBUG "usb-storage: waiting for device "
                                "to settle before scanning\n");
-retry:
-               wait_event_interruptible_timeout(us->delay_wait,
+               wait_event_freezable_timeout(us->delay_wait,
                                test_bit(US_FLIDX_DISCONNECTING, &us->flags),
                                delay_use * HZ);
-               if (try_to_freeze())
-                       goto retry;
        }
 
        /* If the device is still connected, perform the scanning */
index efded00ad08c5003bebd89964bb8b8619630a2c2..08934995c7ab5463e5f4064f4e2fff5ccfb4af94 100644 (file)
@@ -4,6 +4,7 @@
 #define FREEZER_H_INCLUDED
 
 #include <linux/sched.h>
+#include <linux/wait.h>
 
 #ifdef CONFIG_PM_SLEEP
 /*
@@ -126,6 +127,36 @@ static inline void set_freezable(void)
        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 */
 static inline int frozen(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) {}
 static inline void freezer_count(void) {}
 static inline int freezer_should_skip(struct task_struct *p) { return 0; }
 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 /* FREEZER_H_INCLUDED */