On Sunday, 22 April 2007 23:14, Paul Jackson wrote: > Rafael wrote: > > Move all of the freezer-related flags to a separate field in task_struct and > > introduce functions to operate them using set_bit() etc. > > It's getting time I learned what this freezer thing is. > > What would you suggest I read? > > I looked in include/linux/freezer.h and didn't see any explanations. > I found one Documenation file, power/kernel_threads.txt, that explained > the interaction of freezing and kernel threads. I looked in the > comments for various 2.6.21-rc6-mm1 freezer* patches, and saw various > interesting details. > > But I couldn't find any documentation telling me what a freezer was, > or what a refrigerator is. > > Did I miss something?
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 - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/