[LINUX] Freezing of tasks (2/2)

Originally, it is a part of the Linux Kernel source code, so it will be treated as GPLv2 (recognition that it should be).

https://www.kernel.org/doc/html/latest/index.html

Licensing documentation

The following describes the license of the Linux kernel source code (GPLv2), how to properly mark the license of individual files in the source tree, as well as links to the full license text.

https://www.kernel.org/doc/html/latest/process/license-rules.html#kernel-licensing

https://www.kernel.org/doc/html/latest/power/freezing-of-tasks.html


Docs » Power Management » Freezing of tasks

V. Are there any problems related to the freezing of tasks? (Are there any problems related to the freezing of tasks?)

Yes, there are. (Yes, there are)

.

First of all, the freezing of kernel threads may be tricky if they depend one on another.

First of all, freezing kernel threads can be tricky if you're requesting something else.

For example, if kernel thread A waits for a completion (in the TASK_UNINTERRUPTIBLE state) that needs to be done by freezable kernel thread B and B is frozen in the meantime, then A will be blocked until B is thawed, which may be undesirable. For example, if kernel thread A waits for completion by freezable kernel thread B (in TASK_UNINTERRUPTIBLE state), and B freezes in the meantime, A will be blocked until B is thawed, which would be undesirable.

That’s why kernel threads are not freezable by default.

That's why kernel threads don't make it freezable by default.

.

Second, there are the following two problems related to the freezing of user space processes:

Next, there are two reasons related to the freeze of user space processes:

.

Putting processes into an uninterruptible sleep distorts the load average.

Putting the process into an uninterrupted sleep will distort the average load.

Now that we have FUSE, plus the framework for doing device drivers in userspace, it gets even more complicated because some userspace processes are now doing the sorts of things that kernel threads do (https://lists.linux-foundation.org/pipermail/linux-pm/2007-May/012309.html).

Currently, we have FUSE and, in addition, a framework for running device drivers in user space. This is further complicated by the fact that some userspace processes are doing the kind of processing that kernel threads do. (https://lists.linux-foundation.org/pipermail/linux-pm/2007-May/012309.html)

The problem 1. seems to be fixable, although it hasn’t been fixed so far.

Problem 1 seems to be solvable, but it is not.

The other one is more serious, but it seems that we can work around it by using hibernation (and suspend) notifiers

The other is a more serious problem, but this can be avoided by using the workaround used in hibernation (and suspend) notifiers.

(in that case, though, we won’t be able to avoid the realization by the user space processes that the hibernation is taking place).

(However, in that case, realization cannot be avoided by the user-space process in which hibernation takes place).

.

There are also problems that the freezing of tasks tends to expose, although they are not directly related to it.

There is also a problem that is not directly related to task freezes, but is more likely to become apparent due to task freezes.

For example, if request_firmware() is called from a device driver’s .resume() routine, it will timeout and eventually fail, because the user land process that should respond to the request is frozen at this point.

For example, if request_firmware () is called from the device driver resume () routine, it will time out and eventually fail. This is because the user space process that has to respond to this request is frozen at this point.

So, seemingly, the failure is due to the freezing of tasks.

So, at first glance, the cause of the failure is the freeze of the task.

Suppose, however, that the firmware file is located on a filesystem accessible only through another device that hasn’t been resumed yet.

However, the firmware file is in the filesystem. The file system can only be accessed through another device that has not completed resume.

In that case, request_firmware() will fail regardless of whether or not the freezing of tasks is used.

In this case, request_firmware () will fail regardless of whether task freeze is used.

Consequently, the problem is not really related to the freezing of tasks, since it generally exists anyway.

As a result, problems usually occur and are not related to task freezes.

.

A driver must have all firmwares it may need in RAM before suspend() is called.

The driver must have all the firmware in RAM before suspend () is called.

If keeping them is not practical, for example due to their size, they must be requested early enough using the suspend notifier API described in Documentation/driver-api/pm/notifiers.rst.

If it is not practical to retain, for example its size, you should make an early request using the suspend notifier API (see Documentation / driver-api / pm / notifiers.rst).

VI. Are there any precautions to be taken to prevent freezing failures? (Are there any precautions to prevent freezing failures?)

Yes, there are. (Yes, there are)

.

First of all, grabbing the ‘system_transition_mutex’ lock to mutually exclude a piece of code from system-wide sleep such as suspend/hibernation is not encouraged.

It is not recommended to get the ‘system_transition_mutex’ lock first and exclude the code from each other from system-wide sleep like suspend / hibernation.

If possible, that piece of code must instead hook onto the suspend/hibernation notifiers to achieve mutual exclusion.

If possible, instead, hooks should be made through suspend / hibernation notifiers to achieve mutual exclusion.

Look at the CPU-Hotplug code (kernel/cpu.c) for an example.

See CPU-Hotplug code (kernel / cpu.c) for an example.

.

However, if that is not feasible, and grabbing ‘system_transition_mutex’ is deemed necessary, it is strongly discouraged to directly call mutex_[un]lock(&system_transition_mutex) since that could lead to freezing failures,

However, if that is not possible and you think you need to get the ‘system_transition_mutex’, do not call the mutex_ [un] lock (& system_transition_mutex) directly. Freezing failures can occur.

because if the suspend/hibernate code successfully acquired the ‘system_transition_mutex’ lock, and hence that other entity failed to acquire the lock, then that task would get blocked in TASK_UNINTERRUPTIBLE state.

This is because if suspend / hibernate code gets the ‘system_transition_mutex’ lock successfully, no other entity can get the lock and the task will be blocked in TASK_UNINTERRUPTIBLE state.

As a consequence, the freezer would not be able to freeze that task, leading to freezing failure.

As a result, the freezer will not be able to freeze the task, resulting in a freeze failure.

.

However, the [un]lock_system_sleep() APIs are safe to use in this scenario, since they ask the freezer to skip freezing this task, since it is anyway “frozen enough” as it is blocked on ‘system_transition_mutex’, which will be released only after the entire suspend/hibernation sequence is complete.

However, for this scenario, the [un] lock_system_sleep () API is safe to use. Asks freezer to skip freezing for this task. The system_transition_mutex is blocked and frozen enough (frozon enogh) anyway, so it will be released after the suspend / hibernation sequence is complete.

So, to summarize, use [un]lock_system_sleep() instead of directly using mutex_[un]lock(&system_transition_mutex). That would prevent freezing failures.

So, in summary, instead of using mutex_ [un] lock (& system_transition_mutex) directly, use [un] lock_system_sleep (). This prevents freezing failures.

V. Miscellaneous (Other)

/sys/power/pm_freeze_timeout controls how long it will cost at most to freeze all user space processes or all freezable kernel threads, in unit of millisecond.

/ sys / power / pm_freeze_timeout contains information on the maximum cost required to freeze all userspace processes and all freezable kernel threads. The unit is millisecond.

The default value is 20000, with range of unsigned integer.

The default value is 20000 and the range is an unsgined integer.

Recommended Posts

Freezing of tasks (1/2)
Freezing of tasks (2/2)
Administrative tasks