linux/include/linux/freezer.h
<<
>>
Prefs
   1/* Freezer declarations */
   2
   3#ifndef FREEZER_H_INCLUDED
   4#define FREEZER_H_INCLUDED
   5
   6#include <linux/sched.h>
   7#include <linux/wait.h>
   8
   9#ifdef CONFIG_PM_SLEEP
  10/*
  11 * Check if a process has been frozen
  12 */
  13static inline int frozen(struct task_struct *p)
  14{
  15        return p->flags & PF_FROZEN;
  16}
  17
  18/*
  19 * Check if there is a request to freeze a process
  20 */
  21static inline int freezing(struct task_struct *p)
  22{
  23        return test_tsk_thread_flag(p, TIF_FREEZE);
  24}
  25
  26/*
  27 * Request that a process be frozen
  28 */
  29static inline void set_freeze_flag(struct task_struct *p)
  30{
  31        set_tsk_thread_flag(p, TIF_FREEZE);
  32}
  33
  34/*
  35 * Sometimes we may need to cancel the previous 'freeze' request
  36 */
  37static inline void clear_freeze_flag(struct task_struct *p)
  38{
  39        clear_tsk_thread_flag(p, TIF_FREEZE);
  40}
  41
  42/*
  43 * Wake up a frozen process
  44 *
  45 * task_lock() is taken to prevent the race with refrigerator() which may
  46 * occur if the freezing of tasks fails.  Namely, without the lock, if the
  47 * freezing of tasks failed, thaw_tasks() might have run before a task in
  48 * refrigerator() could call frozen_process(), in which case the task would be
  49 * frozen and no one would thaw it.
  50 */
  51static inline int thaw_process(struct task_struct *p)
  52{
  53        task_lock(p);
  54        if (frozen(p)) {
  55                p->flags &= ~PF_FROZEN;
  56                task_unlock(p);
  57                wake_up_process(p);
  58                return 1;
  59        }
  60        clear_freeze_flag(p);
  61        task_unlock(p);
  62        return 0;
  63}
  64
  65extern void refrigerator(void);
  66extern int freeze_processes(void);
  67extern void thaw_processes(void);
  68
  69static inline int try_to_freeze(void)
  70{
  71        if (freezing(current)) {
  72                refrigerator();
  73                return 1;
  74        } else
  75                return 0;
  76}
  77
  78/*
  79 * The PF_FREEZER_SKIP flag should be set by a vfork parent right before it
  80 * calls wait_for_completion(&vfork) and reset right after it returns from this
  81 * function.  Next, the parent should call try_to_freeze() to freeze itself
  82 * appropriately in case the child has exited before the freezing of tasks is
  83 * complete.  However, we don't want kernel threads to be frozen in unexpected
  84 * places, so we allow them to block freeze_processes() instead or to set
  85 * PF_NOFREEZE if needed and PF_FREEZER_SKIP is only set for userland vfork
  86 * parents.  Fortunately, in the ____call_usermodehelper() case the parent won't
  87 * really block freeze_processes(), since ____call_usermodehelper() (the child)
  88 * does a little before exec/exit and it can't be frozen before waking up the
  89 * parent.
  90 */
  91
  92/*
  93 * If the current task is a user space one, tell the freezer not to count it as
  94 * freezable.
  95 */
  96static inline void freezer_do_not_count(void)
  97{
  98        if (current->mm)
  99                current->flags |= PF_FREEZER_SKIP;
 100}
 101
 102/*
 103 * If the current task is a user space one, tell the freezer to count it as
 104 * freezable again and try to freeze it.
 105 */
 106static inline void freezer_count(void)
 107{
 108        if (current->mm) {
 109                current->flags &= ~PF_FREEZER_SKIP;
 110                try_to_freeze();
 111        }
 112}
 113
 114/*
 115 * Check if the task should be counted as freezeable by the freezer
 116 */
 117static inline int freezer_should_skip(struct task_struct *p)
 118{
 119        return !!(p->flags & PF_FREEZER_SKIP);
 120}
 121
 122/*
 123 * Tell the freezer that the current task should be frozen by it
 124 */
 125static inline void set_freezable(void)
 126{
 127        current->flags &= ~PF_NOFREEZE;
 128}
 129
 130/*
 131 * Freezer-friendly wrappers around wait_event_interruptible() and
 132 * wait_event_interruptible_timeout(), originally defined in <linux/wait.h>
 133 */
 134
 135#define wait_event_freezable(wq, condition)                             \
 136({                                                                      \
 137        int __retval;                                                   \
 138        do {                                                            \
 139                __retval = wait_event_interruptible(wq,                 \
 140                                (condition) || freezing(current));      \
 141                if (__retval && !freezing(current))                     \
 142                        break;                                          \
 143                else if (!(condition))                                  \
 144                        __retval = -ERESTARTSYS;                        \
 145        } while (try_to_freeze());                                      \
 146        __retval;                                                       \
 147})
 148
 149
 150#define wait_event_freezable_timeout(wq, condition, timeout)            \
 151({                                                                      \
 152        long __retval = timeout;                                        \
 153        do {                                                            \
 154                __retval = wait_event_interruptible_timeout(wq,         \
 155                                (condition) || freezing(current),       \
 156                                __retval);                              \
 157        } while (try_to_freeze());                                      \
 158        __retval;                                                       \
 159})
 160#else /* !CONFIG_PM_SLEEP */
 161static inline int frozen(struct task_struct *p) { return 0; }
 162static inline int freezing(struct task_struct *p) { return 0; }
 163static inline void set_freeze_flag(struct task_struct *p) {}
 164static inline void clear_freeze_flag(struct task_struct *p) {}
 165static inline int thaw_process(struct task_struct *p) { return 1; }
 166
 167static inline void refrigerator(void) {}
 168static inline int freeze_processes(void) { BUG(); return 0; }
 169static inline void thaw_processes(void) {}
 170
 171static inline int try_to_freeze(void) { return 0; }
 172
 173static inline void freezer_do_not_count(void) {}
 174static inline void freezer_count(void) {}
 175static inline int freezer_should_skip(struct task_struct *p) { return 0; }
 176static inline void set_freezable(void) {}
 177
 178#define wait_event_freezable(wq, condition)                             \
 179                wait_event_interruptible(wq, condition)
 180
 181#define wait_event_freezable_timeout(wq, condition, timeout)            \
 182                wait_event_interruptible_timeout(wq, condition, timeout)
 183
 184#endif /* !CONFIG_PM_SLEEP */
 185
 186#endif  /* FREEZER_H_INCLUDED */
 187