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