1/* Freezer declarations */ 2 3#ifndef FREEZER_H_INCLUDED 4#define FREEZER_H_INCLUDED 5 6#include <linux/debug_locks.h> 7#include <linux/sched.h> 8#include <linux/wait.h> 9#include <linux/atomic.h> 10 11#ifdef CONFIG_FREEZER 12extern atomic_t system_freezing_cnt; /* nr of freezing conds in effect */ 13extern bool pm_freezing; /* PM freezing in effect */ 14extern bool pm_nosig_freezing; /* PM nosig freezing in effect */ 15 16/* 17 * Timeout for stopping processes 18 */ 19extern unsigned int freeze_timeout_msecs; 20 21/* 22 * Check if a process has been frozen 23 */ 24static inline bool frozen(struct task_struct *p) 25{ 26 return p->flags & PF_FROZEN; 27} 28 29extern bool freezing_slow_path(struct task_struct *p); 30 31/* 32 * Check if there is a request to freeze a process 33 */ 34static inline bool freezing(struct task_struct *p) 35{ 36 if (likely(!atomic_read(&system_freezing_cnt))) 37 return false; 38 return freezing_slow_path(p); 39} 40 41/* Takes and releases task alloc lock using task_lock() */ 42extern void __thaw_task(struct task_struct *t); 43 44extern bool __refrigerator(bool check_kthr_stop); 45extern int freeze_processes(void); 46extern int freeze_kernel_threads(void); 47extern void thaw_processes(void); 48extern void thaw_kernel_threads(void); 49 50/* 51 * DO NOT ADD ANY NEW CALLERS OF THIS FUNCTION 52 * If try_to_freeze causes a lockdep warning it means the caller may deadlock 53 */ 54static inline bool try_to_freeze_unsafe(void) 55{ 56 might_sleep(); 57 if (likely(!freezing(current))) 58 return false; 59 return __refrigerator(false); 60} 61 62static inline bool try_to_freeze(void) 63{ 64 if (!(current->flags & PF_NOFREEZE)) 65 debug_check_no_locks_held(); 66 return try_to_freeze_unsafe(); 67} 68 69extern bool freeze_task(struct task_struct *p); 70extern bool set_freezable(void); 71 72#ifdef CONFIG_CGROUP_FREEZER 73extern bool cgroup_freezing(struct task_struct *task); 74#else /* !CONFIG_CGROUP_FREEZER */ 75static inline bool cgroup_freezing(struct task_struct *task) 76{ 77 return false; 78} 79#endif /* !CONFIG_CGROUP_FREEZER */ 80 81/* 82 * The PF_FREEZER_SKIP flag should be set by a vfork parent right before it 83 * calls wait_for_completion(&vfork) and reset right after it returns from this 84 * function. Next, the parent should call try_to_freeze() to freeze itself 85 * appropriately in case the child has exited before the freezing of tasks is 86 * complete. However, we don't want kernel threads to be frozen in unexpected 87 * places, so we allow them to block freeze_processes() instead or to set 88 * PF_NOFREEZE if needed. Fortunately, in the ____call_usermodehelper() case the 89 * parent won't really block freeze_processes(), since ____call_usermodehelper() 90 * (the child) does a little before exec/exit and it can't be frozen before 91 * waking up the parent. 92 */ 93 94 95/** 96 * freezer_do_not_count - tell freezer to ignore %current 97 * 98 * Tell freezers to ignore the current task when determining whether the 99 * target frozen state is reached. IOW, the current task will be 100 * considered frozen enough by freezers. 101 * 102 * The caller shouldn't do anything which isn't allowed for a frozen task 103 * until freezer_cont() is called. Usually, freezer[_do_not]_count() pair 104 * wrap a scheduling operation and nothing much else. 105 */ 106static inline void freezer_do_not_count(void) 107{ 108 current->flags |= PF_FREEZER_SKIP; 109} 110 111/** 112 * freezer_count - tell freezer to stop ignoring %current 113 * 114 * Undo freezer_do_not_count(). It tells freezers that %current should be 115 * considered again and tries to freeze if freezing condition is already in 116 * effect. 117 */ 118static inline void freezer_count(void) 119{ 120 current->flags &= ~PF_FREEZER_SKIP; 121 /* 122 * If freezing is in progress, the following paired with smp_mb() 123 * in freezer_should_skip() ensures that either we see %true 124 * freezing() or freezer_should_skip() sees !PF_FREEZER_SKIP. 125 */ 126 smp_mb(); 127 try_to_freeze(); 128} 129 130/* DO NOT ADD ANY NEW CALLERS OF THIS FUNCTION */ 131static inline void freezer_count_unsafe(void) 132{ 133 current->flags &= ~PF_FREEZER_SKIP; 134 smp_mb(); 135 try_to_freeze_unsafe(); 136} 137 138/** 139 * freezer_should_skip - whether to skip a task when determining frozen 140 * state is reached 141 * @p: task in quesion 142 * 143 * This function is used by freezers after establishing %true freezing() to 144 * test whether a task should be skipped when determining the target frozen 145 * state is reached. IOW, if this function returns %true, @p is considered 146 * frozen enough. 147 */ 148static inline bool freezer_should_skip(struct task_struct *p) 149{ 150 /* 151 * The following smp_mb() paired with the one in freezer_count() 152 * ensures that either freezer_count() sees %true freezing() or we 153 * see cleared %PF_FREEZER_SKIP and return %false. This makes it 154 * impossible for a task to slip frozen state testing after 155 * clearing %PF_FREEZER_SKIP. 156 */ 157 smp_mb(); 158 return p->flags & PF_FREEZER_SKIP; 159} 160 161/* 162 * These functions are intended to be used whenever you want allow a sleeping 163 * task to be frozen. Note that neither return any clear indication of 164 * whether a freeze event happened while in this function. 165 */ 166 167/* Like schedule(), but should not block the freezer. */ 168static inline void freezable_schedule(void) 169{ 170 freezer_do_not_count(); 171 schedule(); 172 freezer_count(); 173} 174 175/* DO NOT ADD ANY NEW CALLERS OF THIS FUNCTION */ 176static inline void freezable_schedule_unsafe(void) 177{ 178 freezer_do_not_count(); 179 schedule(); 180 freezer_count_unsafe(); 181} 182 183/* 184 * Like freezable_schedule_timeout(), but should not block the freezer. Do not 185 * call this with locks held. 186 */ 187static inline long freezable_schedule_timeout(long timeout) 188{ 189 long __retval; 190 freezer_do_not_count(); 191 __retval = schedule_timeout(timeout); 192 freezer_count(); 193 return __retval; 194} 195 196/* 197 * Like schedule_timeout_interruptible(), but should not block the freezer. Do not 198 * call this with locks held. 199 */ 200static inline long freezable_schedule_timeout_interruptible(long timeout) 201{ 202 long __retval; 203 freezer_do_not_count(); 204 __retval = schedule_timeout_interruptible(timeout); 205 freezer_count(); 206 return __retval; 207} 208 209/* Like schedule_timeout_killable(), but should not block the freezer. */ 210static inline long freezable_schedule_timeout_killable(long timeout) 211{ 212 long __retval; 213 freezer_do_not_count(); 214 __retval = schedule_timeout_killable(timeout); 215 freezer_count(); 216 return __retval; 217} 218 219/* DO NOT ADD ANY NEW CALLERS OF THIS FUNCTION */ 220static inline long freezable_schedule_timeout_killable_unsafe(long timeout) 221{ 222 long __retval; 223 freezer_do_not_count(); 224 __retval = schedule_timeout_killable(timeout); 225 freezer_count_unsafe(); 226 return __retval; 227} 228 229/* 230 * Like schedule_hrtimeout_range(), but should not block the freezer. Do not 231 * call this with locks held. 232 */ 233static inline int freezable_schedule_hrtimeout_range(ktime_t *expires, 234 unsigned long delta, const enum hrtimer_mode mode) 235{ 236 int __retval; 237 freezer_do_not_count(); 238 __retval = schedule_hrtimeout_range(expires, delta, mode); 239 freezer_count(); 240 return __retval; 241} 242 243/* 244 * Freezer-friendly wrappers around wait_event_interruptible(), 245 * wait_event_killable() and wait_event_interruptible_timeout(), originally 246 * defined in <linux/wait.h> 247 */ 248 249/* DO NOT ADD ANY NEW CALLERS OF THIS FUNCTION */ 250#define wait_event_freezekillable_unsafe(wq, condition) \ 251({ \ 252 int __retval; \ 253 freezer_do_not_count(); \ 254 __retval = wait_event_killable(wq, (condition)); \ 255 freezer_count_unsafe(); \ 256 __retval; \ 257}) 258 259#else /* !CONFIG_FREEZER */ 260static inline bool frozen(struct task_struct *p) { return false; } 261static inline bool freezing(struct task_struct *p) { return false; } 262static inline void __thaw_task(struct task_struct *t) {} 263 264static inline bool __refrigerator(bool check_kthr_stop) { return false; } 265static inline int freeze_processes(void) { return -ENOSYS; } 266static inline int freeze_kernel_threads(void) { return -ENOSYS; } 267static inline void thaw_processes(void) {} 268static inline void thaw_kernel_threads(void) {} 269 270static inline bool try_to_freeze_nowarn(void) { return false; } 271static inline bool try_to_freeze(void) { return false; } 272 273static inline void freezer_do_not_count(void) {} 274static inline void freezer_count(void) {} 275static inline int freezer_should_skip(struct task_struct *p) { return 0; } 276static inline void set_freezable(void) {} 277 278#define freezable_schedule() schedule() 279 280#define freezable_schedule_unsafe() schedule() 281 282#define freezable_schedule_timeout(timeout) schedule_timeout(timeout) 283 284#define freezable_schedule_timeout_interruptible(timeout) \ 285 schedule_timeout_interruptible(timeout) 286 287#define freezable_schedule_timeout_killable(timeout) \ 288 schedule_timeout_killable(timeout) 289 290#define freezable_schedule_timeout_killable_unsafe(timeout) \ 291 schedule_timeout_killable(timeout) 292 293#define freezable_schedule_hrtimeout_range(expires, delta, mode) \ 294 schedule_hrtimeout_range(expires, delta, mode) 295 296#define wait_event_freezekillable_unsafe(wq, condition) \ 297 wait_event_killable(wq, condition) 298 299#endif /* !CONFIG_FREEZER */ 300 301#endif /* FREEZER_H_INCLUDED */ 302