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#include <linux/atomic.h>
   9
  10#ifdef CONFIG_FREEZER
  11extern atomic_t system_freezing_cnt;    /* nr of freezing conds in effect */
  12extern bool pm_freezing;                /* PM freezing in effect */
  13extern bool pm_nosig_freezing;          /* PM nosig freezing in effect */
  14
  15/*
  16 * Check if a process has been frozen
  17 */
  18static inline bool frozen(struct task_struct *p)
  19{
  20        return p->flags & PF_FROZEN;
  21}
  22
  23extern bool freezing_slow_path(struct task_struct *p);
  24
  25/*
  26 * Check if there is a request to freeze a process
  27 */
  28static inline bool freezing(struct task_struct *p)
  29{
  30        if (likely(!atomic_read(&system_freezing_cnt)))
  31                return false;
  32        return freezing_slow_path(p);
  33}
  34
  35/* Takes and releases task alloc lock using task_lock() */
  36extern void __thaw_task(struct task_struct *t);
  37
  38extern bool __refrigerator(bool check_kthr_stop);
  39extern int freeze_processes(void);
  40extern int freeze_kernel_threads(void);
  41extern void thaw_processes(void);
  42extern void thaw_kernel_threads(void);
  43
  44static inline bool try_to_freeze(void)
  45{
  46        might_sleep();
  47        if (likely(!freezing(current)))
  48                return false;
  49        return __refrigerator(false);
  50}
  51
  52extern bool freeze_task(struct task_struct *p);
  53extern bool set_freezable(void);
  54
  55#ifdef CONFIG_CGROUP_FREEZER
  56extern bool cgroup_freezing(struct task_struct *task);
  57#else /* !CONFIG_CGROUP_FREEZER */
  58static inline bool cgroup_freezing(struct task_struct *task)
  59{
  60        return false;
  61}
  62#endif /* !CONFIG_CGROUP_FREEZER */
  63
  64/*
  65 * The PF_FREEZER_SKIP flag should be set by a vfork parent right before it
  66 * calls wait_for_completion(&vfork) and reset right after it returns from this
  67 * function.  Next, the parent should call try_to_freeze() to freeze itself
  68 * appropriately in case the child has exited before the freezing of tasks is
  69 * complete.  However, we don't want kernel threads to be frozen in unexpected
  70 * places, so we allow them to block freeze_processes() instead or to set
  71 * PF_NOFREEZE if needed. Fortunately, in the ____call_usermodehelper() case the
  72 * parent won't really block freeze_processes(), since ____call_usermodehelper()
  73 * (the child) does a little before exec/exit and it can't be frozen before
  74 * waking up the parent.
  75 */
  76
  77
  78/**
  79 * freezer_do_not_count - tell freezer to ignore %current
  80 *
  81 * Tell freezers to ignore the current task when determining whether the
  82 * target frozen state is reached.  IOW, the current task will be
  83 * considered frozen enough by freezers.
  84 *
  85 * The caller shouldn't do anything which isn't allowed for a frozen task
  86 * until freezer_cont() is called.  Usually, freezer[_do_not]_count() pair
  87 * wrap a scheduling operation and nothing much else.
  88 */
  89static inline void freezer_do_not_count(void)
  90{
  91        current->flags |= PF_FREEZER_SKIP;
  92}
  93
  94/**
  95 * freezer_count - tell freezer to stop ignoring %current
  96 *
  97 * Undo freezer_do_not_count().  It tells freezers that %current should be
  98 * considered again and tries to freeze if freezing condition is already in
  99 * effect.
 100 */
 101static inline void freezer_count(void)
 102{
 103        current->flags &= ~PF_FREEZER_SKIP;
 104        /*
 105         * If freezing is in progress, the following paired with smp_mb()
 106         * in freezer_should_skip() ensures that either we see %true
 107         * freezing() or freezer_should_skip() sees !PF_FREEZER_SKIP.
 108         */
 109        smp_mb();
 110        try_to_freeze();
 111}
 112
 113/**
 114 * freezer_should_skip - whether to skip a task when determining frozen
 115 *                       state is reached
 116 * @p: task in quesion
 117 *
 118 * This function is used by freezers after establishing %true freezing() to
 119 * test whether a task should be skipped when determining the target frozen
 120 * state is reached.  IOW, if this function returns %true, @p is considered
 121 * frozen enough.
 122 */
 123static inline bool freezer_should_skip(struct task_struct *p)
 124{
 125        /*
 126         * The following smp_mb() paired with the one in freezer_count()
 127         * ensures that either freezer_count() sees %true freezing() or we
 128         * see cleared %PF_FREEZER_SKIP and return %false.  This makes it
 129         * impossible for a task to slip frozen state testing after
 130         * clearing %PF_FREEZER_SKIP.
 131         */
 132        smp_mb();
 133        return p->flags & PF_FREEZER_SKIP;
 134}
 135
 136/*
 137 * These macros are intended to be used whenever you want allow a sleeping
 138 * task to be frozen. Note that neither return any clear indication of
 139 * whether a freeze event happened while in this function.
 140 */
 141
 142/* Like schedule(), but should not block the freezer. */
 143#define freezable_schedule()                                            \
 144({                                                                      \
 145        freezer_do_not_count();                                         \
 146        schedule();                                                     \
 147        freezer_count();                                                \
 148})
 149
 150/* Like schedule_timeout_killable(), but should not block the freezer. */
 151#define freezable_schedule_timeout_killable(timeout)                    \
 152({                                                                      \
 153        long __retval;                                                  \
 154        freezer_do_not_count();                                         \
 155        __retval = schedule_timeout_killable(timeout);                  \
 156        freezer_count();                                                \
 157        __retval;                                                       \
 158})
 159
 160/*
 161 * Freezer-friendly wrappers around wait_event_interruptible(),
 162 * wait_event_killable() and wait_event_interruptible_timeout(), originally
 163 * defined in <linux/wait.h>
 164 */
 165
 166#define wait_event_freezekillable(wq, condition)                        \
 167({                                                                      \
 168        int __retval;                                                   \
 169        freezer_do_not_count();                                         \
 170        __retval = wait_event_killable(wq, (condition));                \
 171        freezer_count();                                                \
 172        __retval;                                                       \
 173})
 174
 175#define wait_event_freezable(wq, condition)                             \
 176({                                                                      \
 177        int __retval;                                                   \
 178        for (;;) {                                                      \
 179                __retval = wait_event_interruptible(wq,                 \
 180                                (condition) || freezing(current));      \
 181                if (__retval || (condition))                            \
 182                        break;                                          \
 183                try_to_freeze();                                        \
 184        }                                                               \
 185        __retval;                                                       \
 186})
 187
 188#define wait_event_freezable_timeout(wq, condition, timeout)            \
 189({                                                                      \
 190        long __retval = timeout;                                        \
 191        for (;;) {                                                      \
 192                __retval = wait_event_interruptible_timeout(wq,         \
 193                                (condition) || freezing(current),       \
 194                                __retval);                              \
 195                if (__retval <= 0 || (condition))                       \
 196                        break;                                          \
 197                try_to_freeze();                                        \
 198        }                                                               \
 199        __retval;                                                       \
 200})
 201
 202#else /* !CONFIG_FREEZER */
 203static inline bool frozen(struct task_struct *p) { return false; }
 204static inline bool freezing(struct task_struct *p) { return false; }
 205static inline void __thaw_task(struct task_struct *t) {}
 206
 207static inline bool __refrigerator(bool check_kthr_stop) { return false; }
 208static inline int freeze_processes(void) { return -ENOSYS; }
 209static inline int freeze_kernel_threads(void) { return -ENOSYS; }
 210static inline void thaw_processes(void) {}
 211static inline void thaw_kernel_threads(void) {}
 212
 213static inline bool try_to_freeze_nowarn(void) { return false; }
 214static inline bool try_to_freeze(void) { return false; }
 215
 216static inline void freezer_do_not_count(void) {}
 217static inline void freezer_count(void) {}
 218static inline int freezer_should_skip(struct task_struct *p) { return 0; }
 219static inline void set_freezable(void) {}
 220
 221#define freezable_schedule()  schedule()
 222
 223#define freezable_schedule_timeout_killable(timeout)                    \
 224        schedule_timeout_killable(timeout)
 225
 226#define wait_event_freezable(wq, condition)                             \
 227                wait_event_interruptible(wq, condition)
 228
 229#define wait_event_freezable_timeout(wq, condition, timeout)            \
 230                wait_event_interruptible_timeout(wq, condition, timeout)
 231
 232#define wait_event_freezekillable(wq, condition)                \
 233                wait_event_killable(wq, condition)
 234
 235#endif /* !CONFIG_FREEZER */
 236
 237#endif  /* FREEZER_H_INCLUDED */
 238