Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/wq
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/wq: workqueue: change cancel_work_sync() to clear work->data workqueue: warn about flush_scheduled_work()
This commit is contained in:
commit
fa5312d9e8
|
@ -229,6 +229,16 @@ static inline void set_wq_data(struct work_struct *work,
|
|||
atomic_long_set(&work->data, new);
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear WORK_STRUCT_PENDING and the workqueue on which it was queued.
|
||||
*/
|
||||
static inline void clear_wq_data(struct work_struct *work)
|
||||
{
|
||||
unsigned long flags = *work_data_bits(work) &
|
||||
(1UL << WORK_STRUCT_STATIC);
|
||||
atomic_long_set(&work->data, flags);
|
||||
}
|
||||
|
||||
static inline
|
||||
struct cpu_workqueue_struct *get_wq_data(struct work_struct *work)
|
||||
{
|
||||
|
@ -671,7 +681,7 @@ static int __cancel_work_timer(struct work_struct *work,
|
|||
wait_on_work(work);
|
||||
} while (unlikely(ret < 0));
|
||||
|
||||
work_clear_pending(work);
|
||||
clear_wq_data(work);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -845,6 +855,30 @@ int schedule_on_each_cpu(work_func_t func)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* flush_scheduled_work - ensure that any scheduled work has run to completion.
|
||||
*
|
||||
* Forces execution of the kernel-global workqueue and blocks until its
|
||||
* completion.
|
||||
*
|
||||
* Think twice before calling this function! It's very easy to get into
|
||||
* trouble if you don't take great care. Either of the following situations
|
||||
* will lead to deadlock:
|
||||
*
|
||||
* One of the work items currently on the workqueue needs to acquire
|
||||
* a lock held by your code or its caller.
|
||||
*
|
||||
* Your code is running in the context of a work routine.
|
||||
*
|
||||
* They will be detected by lockdep when they occur, but the first might not
|
||||
* occur very often. It depends on what work items are on the workqueue and
|
||||
* what locks they need, which you have no control over.
|
||||
*
|
||||
* In most situations flushing the entire workqueue is overkill; you merely
|
||||
* need to know that a particular work item isn't queued and isn't running.
|
||||
* In such cases you should use cancel_delayed_work_sync() or
|
||||
* cancel_work_sync() instead.
|
||||
*/
|
||||
void flush_scheduled_work(void)
|
||||
{
|
||||
flush_workqueue(keventd_wq);
|
||||
|
|
Loading…
Reference in New Issue