• Oleg Nesterov's avatar
    workqueues: implement flush_work() · db700897
    Oleg Nesterov authored
    Most of users of flush_workqueue() can be changed to use cancel_work_sync(),
    but sometimes we really need to wait for the completion and cancelling is not
    an option. schedule_on_each_cpu() is good example.
    
    Add the new helper, flush_work(work), which waits for the completion of the
    specific work_struct. More precisely, it "flushes" the result of of the last
    queue_work() which is visible to the caller.
    
    For example, this code
    
    	queue_work(wq, work);
    	/* WINDOW */
    	queue_work(wq, work);
    
    	flush_work(work);
    
    doesn't necessary work "as expected". What can happen in the WINDOW above is
    
    	- wq starts the execution of work->func()
    
    	- the caller migrates to another CPU
    
    now, after the 2nd queue_work() this work is active on the previous CPU, and
    at the same time it is queued on another. In this case flush_work(work) may
    return before the first work->func() completes.
    
    It is trivial to add another helper
    
    	int flush_work_sync(struct work_struct *work)
    	{
    		return flush_work(work) || wait_on_work(work);
    	}
    
    which works "more correctly", but it has to iterate over all CPUs and thus
    it much slower than flush_work().
    Signed-off-by: default avatarOleg Nesterov <oleg@tv-sign.ru>
    Acked-by: default avatarMax Krasnyansky <maxk@qualcomm.com>
    Acked-by: default avatarJarek Poplawski <jarkao2@gmail.com>
    Cc: Peter Zijlstra <peterz@infradead.org>
    Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    db700897
workqueue.c 23.5 KB