Commit dd5ec0f4e72bed3d0e589e21fdf46eedafc106b7

Authored by Colin Cross
Committed by Rafael J. Wysocki
1 parent 8ee492d659

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>

Showing 1 changed file with 61 additions and 0 deletions Side-by-side Diff

include/linux/freezer.h
... ... @@ -180,6 +180,32 @@
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 {
... ... @@ -201,6 +227,20 @@
201 227 }
202 228  
203 229 /*
  230 + * Like schedule_hrtimeout_range(), but should not block the freezer. Do not
  231 + * call this with locks held.
  232 + */
  233 +static inline int freezable_schedule_hrtimeout_range(ktime_t *expires,
  234 + unsigned long delta, const enum hrtimer_mode mode)
  235 +{
  236 + int __retval;
  237 + freezer_do_not_count();
  238 + __retval = schedule_hrtimeout_range(expires, delta, mode);
  239 + freezer_count();
  240 + return __retval;
  241 +}
  242 +
  243 +/*
204 244 * Freezer-friendly wrappers around wait_event_interruptible(),
205 245 * wait_event_killable() and wait_event_interruptible_timeout(), originally
206 246 * defined in <linux/wait.h>
... ... @@ -244,6 +284,16 @@
244 284 __retval; \
245 285 })
246 286  
  287 +#define wait_event_freezable_exclusive(wq, condition) \
  288 +({ \
  289 + int __retval; \
  290 + freezer_do_not_count(); \
  291 + __retval = wait_event_interruptible_exclusive(wq, condition); \
  292 + freezer_count(); \
  293 + __retval; \
  294 +})
  295 +
  296 +
247 297 #else /* !CONFIG_FREEZER */
248 298 static inline bool frozen(struct task_struct *p) { return false; }
249 299 static inline bool freezing(struct task_struct *p) { return false; }
250 300  
251 301  
... ... @@ -267,17 +317,28 @@
267 317  
268 318 #define freezable_schedule_unsafe() schedule()
269 319  
  320 +#define freezable_schedule_timeout(timeout) schedule_timeout(timeout)
  321 +
  322 +#define freezable_schedule_timeout_interruptible(timeout) \
  323 + schedule_timeout_interruptible(timeout)
  324 +
270 325 #define freezable_schedule_timeout_killable(timeout) \
271 326 schedule_timeout_killable(timeout)
272 327  
273 328 #define freezable_schedule_timeout_killable_unsafe(timeout) \
274 329 schedule_timeout_killable(timeout)
275 330  
  331 +#define freezable_schedule_hrtimeout_range(expires, delta, mode) \
  332 + schedule_hrtimeout_range(expires, delta, mode)
  333 +
276 334 #define wait_event_freezable(wq, condition) \
277 335 wait_event_interruptible(wq, condition)
278 336  
279 337 #define wait_event_freezable_timeout(wq, condition, timeout) \
280 338 wait_event_interruptible_timeout(wq, condition, timeout)
  339 +
  340 +#define wait_event_freezable_exclusive(wq, condition) \
  341 + wait_event_interruptible_exclusive(wq, condition)
281 342  
282 343 #define wait_event_freezekillable(wq, condition) \
283 344 wait_event_killable(wq, condition)