]> Pileus Git - ~andy/linux/blobdiff - include/linux/freezer.h
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph...
[~andy/linux] / include / linux / freezer.h
index a5386e3ee756d6c85981b033dc0000deebfa59b7..d09af4b67cf121ad91fd4ca02bec01560b6110fd 100644 (file)
@@ -5,71 +5,59 @@
 
 #include <linux/sched.h>
 #include <linux/wait.h>
+#include <linux/atomic.h>
 
 #ifdef CONFIG_FREEZER
+extern atomic_t system_freezing_cnt;   /* nr of freezing conds in effect */
+extern bool pm_freezing;               /* PM freezing in effect */
+extern bool pm_nosig_freezing;         /* PM nosig freezing in effect */
+
 /*
  * Check if a process has been frozen
  */
-static inline int frozen(struct task_struct *p)
+static inline bool frozen(struct task_struct *p)
 {
        return p->flags & PF_FROZEN;
 }
 
-/*
- * Check if there is a request to freeze a process
- */
-static inline int freezing(struct task_struct *p)
-{
-       return test_tsk_thread_flag(p, TIF_FREEZE);
-}
-
-/*
- * Request that a process be frozen
- */
-static inline void set_freeze_flag(struct task_struct *p)
-{
-       set_tsk_thread_flag(p, TIF_FREEZE);
-}
+extern bool freezing_slow_path(struct task_struct *p);
 
 /*
- * Sometimes we may need to cancel the previous 'freeze' request
+ * Check if there is a request to freeze a process
  */
-static inline void clear_freeze_flag(struct task_struct *p)
-{
-       clear_tsk_thread_flag(p, TIF_FREEZE);
-}
-
-static inline bool should_send_signal(struct task_struct *p)
+static inline bool freezing(struct task_struct *p)
 {
-       return !(p->flags & PF_FREEZER_NOSIG);
+       if (likely(!atomic_read(&system_freezing_cnt)))
+               return false;
+       return freezing_slow_path(p);
 }
 
 /* Takes and releases task alloc lock using task_lock() */
-extern int thaw_process(struct task_struct *p);
+extern void __thaw_task(struct task_struct *t);
 
-extern void refrigerator(void);
+extern bool __refrigerator(bool check_kthr_stop);
 extern int freeze_processes(void);
 extern int freeze_kernel_threads(void);
 extern void thaw_processes(void);
+extern void thaw_kernel_threads(void);
 
-static inline int try_to_freeze(void)
+static inline bool try_to_freeze(void)
 {
-       if (freezing(current)) {
-               refrigerator();
-               return 1;
-       } else
-               return 0;
+       might_sleep();
+       if (likely(!freezing(current)))
+               return false;
+       return __refrigerator(false);
 }
 
-extern bool freeze_task(struct task_struct *p, bool sig_only);
-extern void cancel_freezing(struct task_struct *p);
+extern bool freeze_task(struct task_struct *p);
+extern bool set_freezable(void);
 
 #ifdef CONFIG_CGROUP_FREEZER
-extern int cgroup_freezing_or_frozen(struct task_struct *task);
+extern bool cgroup_freezing(struct task_struct *task);
 #else /* !CONFIG_CGROUP_FREEZER */
-static inline int cgroup_freezing_or_frozen(struct task_struct *task)
+static inline bool cgroup_freezing(struct task_struct *task)
 {
-       return 0;
+       return false;
 }
 #endif /* !CONFIG_CGROUP_FREEZER */
 
@@ -80,33 +68,27 @@ static inline int cgroup_freezing_or_frozen(struct task_struct *task)
  * appropriately in case the child has exited before the freezing of tasks is
  * complete.  However, we don't want kernel threads to be frozen in unexpected
  * places, so we allow them to block freeze_processes() instead or to set
- * PF_NOFREEZE if needed and PF_FREEZER_SKIP is only set for userland vfork
- * parents.  Fortunately, in the ____call_usermodehelper() case the parent won't
- * really block freeze_processes(), since ____call_usermodehelper() (the child)
- * does a little before exec/exit and it can't be frozen before waking up the
- * parent.
+ * PF_NOFREEZE if needed. Fortunately, in the ____call_usermodehelper() case the
+ * parent won't really block freeze_processes(), since ____call_usermodehelper()
+ * (the child) does a little before exec/exit and it can't be frozen before
+ * waking up the parent.
  */
 
-/*
- * If the current task is a user space one, tell the freezer not to count it as
- * freezable.
- */
+
+/* Tell the freezer not to count the current task as freezable. */
 static inline void freezer_do_not_count(void)
 {
-       if (current->mm)
-               current->flags |= PF_FREEZER_SKIP;
+       current->flags |= PF_FREEZER_SKIP;
 }
 
 /*
- * If the current task is a user space one, tell the freezer to count it as
- * freezable again and try to freeze it.
+ * Tell the freezer to count the current task as freezable again and try to
+ * freeze it.
  */
 static inline void freezer_count(void)
 {
-       if (current->mm) {
-               current->flags &= ~PF_FREEZER_SKIP;
-               try_to_freeze();
-       }
+       current->flags &= ~PF_FREEZER_SKIP;
+       try_to_freeze();
 }
 
 /*
@@ -118,21 +100,29 @@ static inline int freezer_should_skip(struct task_struct *p)
 }
 
 /*
- * Tell the freezer that the current task should be frozen by it
+ * These macros are intended to be used whenever you want allow a task that's
+ * sleeping in TASK_UNINTERRUPTIBLE or TASK_KILLABLE state to be frozen. Note
+ * that neither return any clear indication of whether a freeze event happened
+ * while in this function.
  */
-static inline void set_freezable(void)
-{
-       current->flags &= ~PF_NOFREEZE;
-}
 
-/*
- * Tell the freezer that the current task should be frozen by it and that it
- * should send a fake signal to the task to freeze it.
- */
-static inline void set_freezable_with_signal(void)
-{
-       current->flags &= ~(PF_NOFREEZE | PF_FREEZER_NOSIG);
-}
+/* Like schedule(), but should not block the freezer. */
+#define freezable_schedule()                                           \
+({                                                                     \
+       freezer_do_not_count();                                         \
+       schedule();                                                     \
+       freezer_count();                                                \
+})
+
+/* Like schedule_timeout_killable(), but should not block the freezer. */
+#define freezable_schedule_timeout_killable(timeout)                   \
+({                                                                     \
+       long __retval;                                                  \
+       freezer_do_not_count();                                         \
+       __retval = schedule_timeout_killable(timeout);                  \
+       freezer_count();                                                \
+       __retval;                                                       \
+})
 
 /*
  * Freezer-friendly wrappers around wait_event_interruptible(),
@@ -152,47 +142,52 @@ static inline void set_freezable_with_signal(void)
 #define wait_event_freezable(wq, condition)                            \
 ({                                                                     \
        int __retval;                                                   \
-       do {                                                            \
+       for (;;) {                                                      \
                __retval = wait_event_interruptible(wq,                 \
                                (condition) || freezing(current));      \
-               if (__retval && !freezing(current))                     \
+               if (__retval || (condition))                            \
                        break;                                          \
-               else if (!(condition))                                  \
-                       __retval = -ERESTARTSYS;                        \
-       } while (try_to_freeze());                                      \
+               try_to_freeze();                                        \
+       }                                                               \
        __retval;                                                       \
 })
 
-
 #define wait_event_freezable_timeout(wq, condition, timeout)           \
 ({                                                                     \
        long __retval = timeout;                                        \
-       do {                                                            \
+       for (;;) {                                                      \
                __retval = wait_event_interruptible_timeout(wq,         \
                                (condition) || freezing(current),       \
                                __retval);                              \
-       } while (try_to_freeze());                                      \
+               if (__retval <= 0 || (condition))                       \
+                       break;                                          \
+               try_to_freeze();                                        \
+       }                                                               \
        __retval;                                                       \
 })
+
 #else /* !CONFIG_FREEZER */
-static inline int frozen(struct task_struct *p) { return 0; }
-static inline int freezing(struct task_struct *p) { return 0; }
-static inline void set_freeze_flag(struct task_struct *p) {}
-static inline void clear_freeze_flag(struct task_struct *p) {}
-static inline int thaw_process(struct task_struct *p) { return 1; }
+static inline bool frozen(struct task_struct *p) { return false; }
+static inline bool freezing(struct task_struct *p) { return false; }
+static inline void __thaw_task(struct task_struct *t) {}
 
-static inline void refrigerator(void) {}
+static inline bool __refrigerator(bool check_kthr_stop) { return false; }
 static inline int freeze_processes(void) { return -ENOSYS; }
 static inline int freeze_kernel_threads(void) { return -ENOSYS; }
 static inline void thaw_processes(void) {}
+static inline void thaw_kernel_threads(void) {}
 
-static inline int try_to_freeze(void) { return 0; }
+static inline bool try_to_freeze(void) { return false; }
 
 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) {}
-static inline void set_freezable_with_signal(void) {}
+
+#define freezable_schedule()  schedule()
+
+#define freezable_schedule_timeout_killable(timeout)                   \
+       schedule_timeout_killable(timeout)
 
 #define wait_event_freezable(wq, condition)                            \
                wait_event_interruptible(wq, condition)