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 * Check if a process has been frozen 17 */ 18 static inline bool frozen(struct task_struct *p) 19 { 20 return p->flags & PF_FROZEN; 21 } 22 23 extern bool freezing_slow_path(struct task_struct *p); 24 25 /* 26 * Check if there is a request to freeze a process 27 */ 28 static 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() */ 36 extern void __thaw_task(struct task_struct *t); 37 38 extern bool __refrigerator(bool check_kthr_stop); 39 extern int freeze_processes(void); 40 extern int freeze_kernel_threads(void); 41 extern void thaw_processes(void); 42 extern void thaw_kernel_threads(void); 43 44 static inline bool try_to_freeze(void) 45 { 46 might_sleep(); 47 if (likely(!freezing(current))) 48 return false; 49 return __refrigerator(false); 50 } 51 52 extern bool freeze_task(struct task_struct *p); 53 extern bool set_freezable(void); 54 55 #ifdef CONFIG_CGROUP_FREEZER 56 extern bool cgroup_freezing(struct task_struct *task); 57 #else /* !CONFIG_CGROUP_FREEZER */ 58 static 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 */ 89 static 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 */ 101 static 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 */ 123 static 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 */ 203 static inline bool frozen(struct task_struct *p) { return false; } 204 static inline bool freezing(struct task_struct *p) { return false; } 205 static inline void __thaw_task(struct task_struct *t) {} 206 207 static inline bool __refrigerator(bool check_kthr_stop) { return false; } 208 static inline int freeze_processes(void) { return -ENOSYS; } 209 static inline int freeze_kernel_threads(void) { return -ENOSYS; } 210 static inline void thaw_processes(void) {} 211 static inline void thaw_kernel_threads(void) {} 212 213 static inline bool try_to_freeze_nowarn(void) { return false; } 214 static inline bool try_to_freeze(void) { return false; } 215 216 static inline void freezer_do_not_count(void) {} 217 static inline void freezer_count(void) {} 218 static inline int freezer_should_skip(struct task_struct *p) { return 0; } 219 static 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