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