Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

freezer: add new freezable helpers using freezer_do_not_count()

Freezing tasks will wake up almost every userspace task from
where it is blocking and force it to run until it hits a
call to try_to_sleep(), generally on the exit path from the syscall
it is blocking in. On resume each task will run again, usually
restarting the syscall and running until it hits the same
blocking call as it was originally blocked in.

To allow tasks to avoid running on every suspend/resume cycle,
this patch adds additional freezable wrappers around blocking calls
that call freezer_do_not_count(). Combined with the previous patch,
these tasks will not run during suspend or resume unless they wake
up for another reason, in which case they will run until they hit
the try_to_freeze() in freezer_count(), and then continue processing
the wakeup after tasks are thawed.

Additional patches will convert the most common locations that
userspace blocks in to use freezable helpers.

Acked-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Colin Cross <ccross@android.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

authored by

Colin Cross and committed by
Rafael J. Wysocki
dd5ec0f4 8ee492d6

+61
+61
include/linux/freezer.h
··· 180 180 freezer_count_unsafe(); 181 181 } 182 182 183 + /* 184 + * Like freezable_schedule_timeout(), but should not block the freezer. Do not 185 + * call this with locks held. 186 + */ 187 + static 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 + */ 200 + static 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 + 183 209 /* Like schedule_timeout_killable(), but should not block the freezer. */ 184 210 static inline long freezable_schedule_timeout_killable(long timeout) 185 211 { ··· 223 197 freezer_do_not_count(); 224 198 __retval = schedule_timeout_killable(timeout); 225 199 freezer_count_unsafe(); 200 + return __retval; 201 + } 202 + 203 + /* 204 + * Like schedule_hrtimeout_range(), but should not block the freezer. Do not 205 + * call this with locks held. 206 + */ 207 + static inline int freezable_schedule_hrtimeout_range(ktime_t *expires, 208 + unsigned long delta, const enum hrtimer_mode mode) 209 + { 210 + int __retval; 211 + freezer_do_not_count(); 212 + __retval = schedule_hrtimeout_range(expires, delta, mode); 213 + freezer_count(); 226 214 return __retval; 227 215 } 228 216 ··· 284 244 __retval; \ 285 245 }) 286 246 247 + #define wait_event_freezable_exclusive(wq, condition) \ 248 + ({ \ 249 + int __retval; \ 250 + freezer_do_not_count(); \ 251 + __retval = wait_event_interruptible_exclusive(wq, condition); \ 252 + freezer_count(); \ 253 + __retval; \ 254 + }) 255 + 256 + 287 257 #else /* !CONFIG_FREEZER */ 288 258 static inline bool frozen(struct task_struct *p) { return false; } 289 259 static inline bool freezing(struct task_struct *p) { return false; } ··· 317 267 318 268 #define freezable_schedule_unsafe() schedule() 319 269 270 + #define freezable_schedule_timeout(timeout) schedule_timeout(timeout) 271 + 272 + #define freezable_schedule_timeout_interruptible(timeout) \ 273 + schedule_timeout_interruptible(timeout) 274 + 320 275 #define freezable_schedule_timeout_killable(timeout) \ 321 276 schedule_timeout_killable(timeout) 322 277 323 278 #define freezable_schedule_timeout_killable_unsafe(timeout) \ 324 279 schedule_timeout_killable(timeout) 325 280 281 + #define freezable_schedule_hrtimeout_range(expires, delta, mode) \ 282 + schedule_hrtimeout_range(expires, delta, mode) 283 + 326 284 #define wait_event_freezable(wq, condition) \ 327 285 wait_event_interruptible(wq, condition) 328 286 329 287 #define wait_event_freezable_timeout(wq, condition, timeout) \ 330 288 wait_event_interruptible_timeout(wq, condition, timeout) 289 + 290 + #define wait_event_freezable_exclusive(wq, condition) \ 291 + wait_event_interruptible_exclusive(wq, condition) 331 292 332 293 #define wait_event_freezekillable(wq, condition) \ 333 294 wait_event_killable(wq, condition)