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 task that's 138 * sleeping in TASK_UNINTERRUPTIBLE or TASK_KILLABLE state to be frozen. Note 139 * that neither return any clear indication of whether a freeze event happened 140 * while in this function. 141 */ 142 143 /* Like schedule(), but should not block the freezer. */ 144 #define freezable_schedule() \ 145 ({ \ 146 freezer_do_not_count(); \ 147 schedule(); \ 148 freezer_count(); \ 149 }) 150 151 /* Like schedule_timeout_killable(), but should not block the freezer. */ 152 #define freezable_schedule_timeout_killable(timeout) \ 153 ({ \ 154 long __retval; \ 155 freezer_do_not_count(); \ 156 __retval = schedule_timeout_killable(timeout); \ 157 freezer_count(); \ 158 __retval; \ 159 }) 160 161 /* 162 * Freezer-friendly wrappers around wait_event_interruptible(), 163 * wait_event_killable() and wait_event_interruptible_timeout(), originally 164 * defined in <linux/wait.h> 165 */ 166 167 #define wait_event_freezekillable(wq, condition) \ 168 ({ \ 169 int __retval; \ 170 freezer_do_not_count(); \ 171 __retval = wait_event_killable(wq, (condition)); \ 172 freezer_count(); \ 173 __retval; \ 174 }) 175 176 #define wait_event_freezable(wq, condition) \ 177 ({ \ 178 int __retval; \ 179 for (;;) { \ 180 __retval = wait_event_interruptible(wq, \ 181 (condition) || freezing(current)); \ 182 if (__retval || (condition)) \ 183 break; \ 184 try_to_freeze(); \ 185 } \ 186 __retval; \ 187 }) 188 189 #define wait_event_freezable_timeout(wq, condition, timeout) \ 190 ({ \ 191 long __retval = timeout; \ 192 for (;;) { \ 193 __retval = wait_event_interruptible_timeout(wq, \ 194 (condition) || freezing(current), \ 195 __retval); \ 196 if (__retval <= 0 || (condition)) \ 197 break; \ 198 try_to_freeze(); \ 199 } \ 200 __retval; \ 201 }) 202 203 #else /* !CONFIG_FREEZER */ 204 static inline bool frozen(struct task_struct *p) { return false; } 205 static inline bool freezing(struct task_struct *p) { return false; } 206 static inline void __thaw_task(struct task_struct *t) {} 207 208 static inline bool __refrigerator(bool check_kthr_stop) { return false; } 209 static inline int freeze_processes(void) { return -ENOSYS; } 210 static inline int freeze_kernel_threads(void) { return -ENOSYS; } 211 static inline void thaw_processes(void) {} 212 static inline void thaw_kernel_threads(void) {} 213 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