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

Documentation: PM: Adjust freezing-of-tasks.rst to the freezer changes

The core freezer logic has been modified by commit f5d39b020809
("freezer,sched: Rewrite core freezer logic"), so adjust the
documentation to reflect the new code. The main changes include:

- Drop references to PF_FROZEN and PF_FREEZER_SKIP
- Describe TASK_FROZEN, TASK_FREEZABLE and __TASK_FREEZABLE_UNSAFE
- Replace system_freezing_cnt with freezer_active
- Use a different example for the loop of a freezable kernel thread,
since the old code is gone gone

Signed-off-by: Kevin Hao <haokexin@gmail.com>
[ rjw: Subject and changelog edits, doc text adjustments ]
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

authored by

Kevin Hao and committed by
Rafael J. Wysocki
4bbf0b6a 489c693b

+46 -35
+46 -35
Documentation/power/freezing-of-tasks.rst
··· 14 14 II. How does it work? 15 15 ===================== 16 16 17 - There are three per-task flags used for that, PF_NOFREEZE, PF_FROZEN 18 - and PF_FREEZER_SKIP (the last one is auxiliary). The tasks that have 19 - PF_NOFREEZE unset (all user space processes and some kernel threads) are 20 - regarded as 'freezable' and treated in a special way before the system enters a 21 - suspend state as well as before a hibernation image is created (in what follows 22 - we only consider hibernation, but the description also applies to suspend). 17 + There is one per-task flag (PF_NOFREEZE) and three per-task states 18 + (TASK_FROZEN, TASK_FREEZABLE and __TASK_FREEZABLE_UNSAFE) used for that. 19 + The tasks that have PF_NOFREEZE unset (all user space tasks and some kernel 20 + threads) are regarded as 'freezable' and treated in a special way before the 21 + system enters a sleep state as well as before a hibernation image is created 22 + (hibernation is directly covered by what follows, but the description applies 23 + to system-wide suspend too). 23 24 24 25 Namely, as the first step of the hibernation procedure the function 25 26 freeze_processes() (defined in kernel/power/process.c) is called. A system-wide 26 - variable system_freezing_cnt (as opposed to a per-task flag) is used to indicate 27 - whether the system is to undergo a freezing operation. And freeze_processes() 28 - sets this variable. After this, it executes try_to_freeze_tasks() that sends a 29 - fake signal to all user space processes, and wakes up all the kernel threads. 30 - All freezable tasks must react to that by calling try_to_freeze(), which 31 - results in a call to __refrigerator() (defined in kernel/freezer.c), which sets 32 - the task's PF_FROZEN flag, changes its state to TASK_UNINTERRUPTIBLE and makes 33 - it loop until PF_FROZEN is cleared for it. Then, we say that the task is 34 - 'frozen' and therefore the set of functions handling this mechanism is referred 35 - to as 'the freezer' (these functions are defined in kernel/power/process.c, 36 - kernel/freezer.c & include/linux/freezer.h). User space processes are generally 37 - frozen before kernel threads. 27 + static key freezer_active (as opposed to a per-task flag or state) is used to 28 + indicate whether the system is to undergo a freezing operation. And 29 + freeze_processes() sets this static key. After this, it executes 30 + try_to_freeze_tasks() that sends a fake signal to all user space processes, and 31 + wakes up all the kernel threads. All freezable tasks must react to that by 32 + calling try_to_freeze(), which results in a call to __refrigerator() (defined 33 + in kernel/freezer.c), which changes the task's state to TASK_FROZEN, and makes 34 + it loop until it is woken by an explicit TASK_FROZEN wakeup. Then, that task 35 + is regarded as 'frozen' and so the set of functions handling this mechanism is 36 + referred to as 'the freezer' (these functions are defined in 37 + kernel/power/process.c, kernel/freezer.c & include/linux/freezer.h). User space 38 + tasks are generally frozen before kernel threads. 38 39 39 40 __refrigerator() must not be called directly. Instead, use the 40 41 try_to_freeze() function (defined in include/linux/freezer.h), that checks ··· 44 43 For user space processes try_to_freeze() is called automatically from the 45 44 signal-handling code, but the freezable kernel threads need to call it 46 45 explicitly in suitable places or use the wait_event_freezable() or 47 - wait_event_freezable_timeout() macros (defined in include/linux/freezer.h) 48 - that combine interruptible sleep with checking if the task is to be frozen and 49 - calling try_to_freeze(). The main loop of a freezable kernel thread may look 46 + wait_event_freezable_timeout() macros (defined in include/linux/wait.h) 47 + that put the task to sleep (TASK_INTERRUPTIBLE) or freeze it (TASK_FROZEN) if 48 + freezer_active is set. The main loop of a freezable kernel thread may look 50 49 like the following one:: 51 50 52 51 set_freezable(); 53 - do { 54 - hub_events(); 55 - wait_event_freezable(khubd_wait, 56 - !list_empty(&hub_event_list) || 57 - kthread_should_stop()); 58 - } while (!kthread_should_stop() || !list_empty(&hub_event_list)); 59 52 60 - (from drivers/usb/core/hub.c::hub_thread()). 53 + while (true) { 54 + struct task_struct *tsk = NULL; 61 55 62 - If a freezable kernel thread fails to call try_to_freeze() after the freezer has 63 - initiated a freezing operation, the freezing of tasks will fail and the entire 64 - hibernation operation will be cancelled. For this reason, freezable kernel 65 - threads must call try_to_freeze() somewhere or use one of the 56 + wait_event_freezable(oom_reaper_wait, oom_reaper_list != NULL); 57 + spin_lock_irq(&oom_reaper_lock); 58 + if (oom_reaper_list != NULL) { 59 + tsk = oom_reaper_list; 60 + oom_reaper_list = tsk->oom_reaper_list; 61 + } 62 + spin_unlock_irq(&oom_reaper_lock); 63 + 64 + if (tsk) 65 + oom_reap_task(tsk); 66 + } 67 + 68 + (from mm/oom_kill.c::oom_reaper()). 69 + 70 + If a freezable kernel thread is not put to the frozen state after the freezer 71 + has initiated a freezing operation, the freezing of tasks will fail and the 72 + entire system-wide transition will be cancelled. For this reason, freezable 73 + kernel threads must call try_to_freeze() somewhere or use one of the 66 74 wait_event_freezable() and wait_event_freezable_timeout() macros. 67 75 68 76 After the system memory state has been restored from a hibernation image and 69 77 devices have been reinitialized, the function thaw_processes() is called in 70 - order to clear the PF_FROZEN flag for each frozen task. Then, the tasks that 71 - have been frozen leave __refrigerator() and continue running. 78 + order to wake up each frozen task. Then, the tasks that have been frozen leave 79 + __refrigerator() and continue running. 72 80 73 81 74 82 Rationale behind the functions dealing with freezing and thawing of tasks ··· 106 96 Kernel threads are not freezable by default. However, a kernel thread may clear 107 97 PF_NOFREEZE for itself by calling set_freezable() (the resetting of PF_NOFREEZE 108 98 directly is not allowed). From this point it is regarded as freezable 109 - and must call try_to_freeze() in a suitable place. 99 + and must call try_to_freeze() or variants of wait_event_freezable() in a 100 + suitable place. 110 101 111 102 IV. Why do we do that? 112 103 ======================