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_FREEZER
  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
  42static inline bool should_send_signal(struct task_struct *p)
  43{
  44        return !(p->flags & PF_FREEZER_NOSIG);
  45}
  46
  47/* Takes and releases task alloc lock using task_lock() */
  48extern int thaw_process(struct task_struct *p);
  49
  50extern void refrigerator(void);
  51extern int freeze_processes(void);
  52extern int freeze_kernel_threads(void);
  53extern void thaw_processes(void);
  54
  55static inline int try_to_freeze(void)
  56{
  57        if (freezing(current)) {
  58                refrigerator();
  59                return 1;
  60        } else
  61                return 0;
  62}
  63
  64extern bool freeze_task(struct task_struct *p, bool sig_only);
  65extern void cancel_freezing(struct task_struct *p);
  66
  67#ifdef CONFIG_CGROUP_FREEZER
  68extern int cgroup_freezing_or_frozen(struct task_struct *task);
  69#else /* !CONFIG_CGROUP_FREEZER */
  70static inline int cgroup_freezing_or_frozen(struct task_struct *task)
  71{
  72        return 0;
  73}
  74#endif /* !CONFIG_CGROUP_FREEZER */
  75
  76/*
  77 * The PF_FREEZER_SKIP flag should be set by a vfork parent right before it
  78 * calls wait_for_completion(&vfork) and reset right after it returns from this
  79 * function.  Next, the parent should call try_to_freeze() to freeze itself
  80 * appropriately in case the child has exited before the freezing of tasks is
  81 * complete.  However, we don't want kernel threads to be frozen in unexpected
  82 * places, so we allow them to block freeze_processes() instead or to set
  83 * PF_NOFREEZE if needed and PF_FREEZER_SKIP is only set for userland vfork
  84 * parents.  Fortunately, in the ____call_usermodehelper() case the parent won't
  85 * really block freeze_processes(), since ____call_usermodehelper() (the child)
  86 * does a little before exec/exit and it can't be frozen before waking up the
  87 * parent.
  88 */
  89
  90/*
  91 * If the current task is a user space one, tell the freezer not to count it as
  92 * freezable.
  93 */
  94static inline void freezer_do_not_count(void)
  95{
  96        if (current->mm)
  97                current->flags |= PF_FREEZER_SKIP;
  98}
  99
 100/*
 101 * If the current task is a user space one, tell the freezer to count it as
 102 * freezable again and try to freeze it.
 103 */
 104static inline void freezer_count(void)
 105{
 106        if (current->mm) {
 107                current->flags &= ~PF_FREEZER_SKIP;
 108                try_to_freeze();
 109        }
 110}
 111
 112/*
 113 * Check if the task should be counted as freezable by the freezer
 114 */
 115static inline int freezer_should_skip(struct task_struct *p)
 116{
 117        return !!(p->flags & PF_FREEZER_SKIP);
 118}
 119
 120/*
 121 * Tell the freezer that the current task should be frozen by it
 122 */
 123static inline void set_freezable(void)
 124{
 125        current->flags &= ~PF_NOFREEZE;
 126}
 127
 128/*
 129 * Tell the freezer that the current task should be frozen by it and that it
 130 * should send a fake signal to the task to freeze it.
 131 */
 132static inline void set_freezable_with_signal(void)
 133{
 134        current->flags &= ~(PF_NOFREEZE | PF_FREEZER_NOSIG);
 135}
 136
 137/*
 138 * Freezer-friendly wrappers around wait_event_interruptible(),
 139 * wait_event_killable() and wait_event_interruptible_timeout(), originally
 140 * defined in <linux/wait.h>
 141 */
 142
 143#define wait_event_freezekillable(wq, condition)                        \
 144({                                                                      \
 145        int __retval;                                                   \
 146        freezer_do_not_count();                                         \
 147        __retval = wait_event_killable(wq, (condition));                \
 148        freezer_count();                                                \
 149        __retval;                                                       \
 150})
 151
 152#define wait_event_freezable(wq, condition)                             \
 153({                                                                      \
 154        int __retval;                                                   \
 155        do {                                                            \
 156                __retval = wait_event_interruptible(wq,                 \
 157                                (condition) || freezing(current));      \
 158                if (__retval && !freezing(current))                     \
 159                        break;                                          \
 160                else if (!(condition))                                  \
 161                        __retval = -ERESTARTSYS;                        \
 162        } while (try_to_freeze());                                      \
 163        __retval;                                                       \
 164})
 165
 166
 167#define wait_event_freezable_timeout(wq, condition, timeout)            \
 168({                                                                      \
 169        long __retval = timeout;                                        \
 170        do {                                                            \
 171                __retval = wait_event_interruptible_timeout(wq,         \
 172                                (condition) || freezing(current),       \
 173                                __retval);                              \
 174        } while (try_to_freeze());                                      \
 175        __retval;                                                       \
 176})
 177#else /* !CONFIG_FREEZER */
 178static inline int frozen(struct task_struct *p) { return 0; }
 179static inline int freezing(struct task_struct *p) { return 0; }
 180static inline void set_freeze_flag(struct task_struct *p) {}
 181static inline void clear_freeze_flag(struct task_struct *p) {}
 182static inline int thaw_process(struct task_struct *p) { return 1; }
 183
 184static inline void refrigerator(void) {}
 185static inline int freeze_processes(void) { return -ENOSYS; }
 186static inline int freeze_kernel_threads(void) { return -ENOSYS; }
 187static inline void thaw_processes(void) {}
 188
 189static inline int try_to_freeze(void) { return 0; }
 190
 191static inline void freezer_do_not_count(void) {}
 192static inline void freezer_count(void) {}
 193static inline int freezer_should_skip(struct task_struct *p) { return 0; }
 194static inline void set_freezable(void) {}
 195static inline void set_freezable_with_signal(void) {}
 196
 197#define wait_event_freezable(wq, condition)                             \
 198                wait_event_interruptible(wq, condition)
 199
 200#define wait_event_freezable_timeout(wq, condition, timeout)            \
 201                wait_event_interruptible_timeout(wq, condition, timeout)
 202
 203#define wait_event_freezekillable(wq, condition)                \
 204                wait_event_killable(wq, condition)
 205
 206#endif /* !CONFIG_FREEZER */
 207
 208#endif  /* FREEZER_H_INCLUDED */
 209