forked from Minki/linux
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);
|
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
|
static inline
|
||||||
struct cpu_workqueue_struct *get_wq_data(struct work_struct *work)
|
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);
|
wait_on_work(work);
|
||||||
} while (unlikely(ret < 0));
|
} while (unlikely(ret < 0));
|
||||||
|
|
||||||
work_clear_pending(work);
|
clear_wq_data(work);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -845,6 +855,30 @@ int schedule_on_each_cpu(work_func_t func)
|
|||||||
return 0;
|
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)
|
void flush_scheduled_work(void)
|
||||||
{
|
{
|
||||||
flush_workqueue(keventd_wq);
|
flush_workqueue(keventd_wq);
|
||||||
|
Loading…
Reference in New Issue
Block a user