On Sunday, 22 April 2007 23:14, Paul Jackson wrote:Well, unfortunately not. The freezer is not separately documented, mainly because (1) for a long time it's been a part of the suspend code and no one else used it, and (2) because it's been changing a lot recently and it's been a 'moving target' from the documentation point of view. I'll try to explain how it works. In short, we use the freezer to make tasks enter a specific function, called the refrigerator, and stay there until they are let out. This is done by calling freeze_processes() (in 2.6.21-rc7 it is located in kernel/power/process.c) that executes try_to_freeze_tasks() separately for userland processes and kernel threads (the sync() in between is needed by the suspend code). try_to_freeze_tasks() sets the FREEZE flag (TIF_FREEZE in 2.6.21-rc7) for each freezable (I'll explain what that means in a while) task and sends a fake signal to it. Userland processes then go to get_signal_to_deliver(), where they execute try_to_freeze() (defined in include/linux/freezer.h) and call refrigerator() (in kernel/power/process.c), since the FREEZE flag is set. In refrigerator() they reset the FREEZE flag and set the FROZEN flag (in 2.6.21-rc7 it is a process flag defined in sched.h). Next, they loop in refrigerator() until someone resets the FROZEN flag for them. Then we say that they are 'frozen'. Kernel threads don't call get_signal_to_deliver(), so they have to execute try_to_freeze() directly to go to the refrigerator. Moreover, kernel threads may not want to go there at all, in which case they should set the NOFREEZE flag (in 2.6.21-rc7 it is a process flag defined in sched.h), that makes try_to_freeze_tasks() ignore them. Apart from the kernel threads that have the NOFREEZE flag set, try_to_freeze_tasks() ignores the task that's running it (its current task) and the tasks that have exit_state different from 0. They all are regarded as 'not freezable'. Of course, kernel threads that declare themselves as not freezable, by setting the NOFREEZE flag, should be careful enough not to interfere with the subsystem that is using the freezer (ie. has called freeze_processes()), which may be quite difficult in practice, so only a few kernel threads do it (and even some of them really shouldn't). The subsystem that has called freeze_processes() is responsible for the 'thawing' of tasks, which is done by calling thaw_processes() (defined in kernel/power/process.c). It runs thaw_tasks() (in the same file) for kernel threads and userland processes. This function loops over all tasks and resets the FROZEN flag for them, so that they can leave the refrigerator. The suspend code uses the freezer to make sure that processes won't get in the way when some suspend-related low-level operations are carried out (like suspending devices, the creation of a suspend image by swsusp etc.). Other subsystems may use it for similar purposes. Greetings, Rafael -
| Eric W. Biederman | [PATCH 02/10] sysfs: Support for preventing unmounts. |
| Greg KH | [GIT PATCH] driver core patches against 2.6.24 |
| Bart Van Assche | Integration of SCST in the mainstream Linux kernel |
| david | Re: Dual-Licensing Linux Kernel with GPL V2 and GPL V3 |
git: | |
| Antonio Almeida | HTB accuracy for high speed |
| Jarek Poplawski | [PATCH] pkt_sched: Destroy gen estimators under rtnl_lock(). |
| Gerrit Renker | [PATCH 26/37] dccp: Integration of dynamic feature activation - part 1 (socket set... |
| David Miller | [GIT]: Networking |
