Thread Initialization

pdflush is used as a work procedure for kernel threads. Once generated, pdflush threads go to sleep and wait until other parts of the kernel assign them tasks that are described in pdflush_work. Consequently, the number of pdflush threads need not match the number of tasks to be performed. The generated threads are on call and simply wait until the kernel decides to give them work to do.

The code flow diagram in Figure 17-3 shows how pdflush works.

Figure 17-3: Code flow diagram for pdflush.

The start routine for generating a new pdflush thread is pdflush, but control flow is passed immediately to_pdflush.1

In_pdflush, the worker function of the pdflush_work instance is set to null because the thread has not been given a particular job to do. The global counter (nr_pdflush_threads) must also be incremented by 1 because a new pdflush thread has now been added to the system.

The thread then goes into an endless loop in which the following actions are performed:

□ The pdflush_work instance of the thread is added to the global list pdflush_list (reminder: the kernel is able to identify the thread by means of the who element).

□ when_i_went_to_sleep is set to the current system time in jiffies to remember when the thread started sleeping.

□ schedule is invoked — this is the most important action. Because the status of the thread was previously set to task_interruptible, the thread now goes to sleep until woken by an external event.

If the kernel requires a worker thread, it sets the worker function of a pdflush_work instance in the global list and wakes the corresponding thread, which resumes work immediately after schedule — but now with the fn worker function.

1 All that happens in pdflush is that an instance of pdflush_work is generated; a pointer to it is passed to_pdflush_work as a parameter. This is to stop the compiler from performing unfortunate optimizations on this variable. Additionally, the process priority is set to 0, and the allowed CPUs are limited to the ones granted for the parent kthreadd.

□ The worker function is invoked with the stored argument so that it can set about its task.

□ Upon termination of the worker function, the kernel checks whether there are too many or too few worker threads. If no idle worker thread was available for longer than 1 second,2 start_one_pdflush_thread generates a new thread. If the sleepiest thread (which is at the end of the pdflush_list list) has been asleep for more than 1 second, the current thread is removed from the system by exiting the endless loop. In this case, the only clean-up action required besides handling locking is to decrement nr_pdflush_threads — one pdflush thread less is available.

Continue reading here: Mmpdflushc

Was this article helpful?

0 0