mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-04-22 14:23:58 +00:00
task_work: add helper for more targeted task_work canceling
The only exported helper we have right now is task_work_cancel(), which cancels any task_work from a given task where func matches the queued work item. This is a bit too coarse for some use cases. Add a task_work_cancel_match() that allows to more specifically target individual work items outside of purely the callback function used. task_work_cancel() can be trivially implemented on top of that, hence do so. Reviewed-by: Oleg Nesterov <oleg@redhat.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
parent
b2e720ace2
commit
c7aab1a7c5
2 changed files with 30 additions and 7 deletions
|
@ -22,6 +22,8 @@ enum task_work_notify_mode {
|
||||||
int task_work_add(struct task_struct *task, struct callback_head *twork,
|
int task_work_add(struct task_struct *task, struct callback_head *twork,
|
||||||
enum task_work_notify_mode mode);
|
enum task_work_notify_mode mode);
|
||||||
|
|
||||||
|
struct callback_head *task_work_cancel_match(struct task_struct *task,
|
||||||
|
bool (*match)(struct callback_head *, void *data), void *data);
|
||||||
struct callback_head *task_work_cancel(struct task_struct *, task_work_func_t);
|
struct callback_head *task_work_cancel(struct task_struct *, task_work_func_t);
|
||||||
void task_work_run(void);
|
void task_work_run(void);
|
||||||
|
|
||||||
|
|
|
@ -59,18 +59,17 @@ int task_work_add(struct task_struct *task, struct callback_head *work,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* task_work_cancel - cancel a pending work added by task_work_add()
|
* task_work_cancel_match - cancel a pending work added by task_work_add()
|
||||||
* @task: the task which should execute the work
|
* @task: the task which should execute the work
|
||||||
* @func: identifies the work to remove
|
* @match: match function to call
|
||||||
*
|
|
||||||
* Find the last queued pending work with ->func == @func and remove
|
|
||||||
* it from queue.
|
|
||||||
*
|
*
|
||||||
* RETURNS:
|
* RETURNS:
|
||||||
* The found work or NULL if not found.
|
* The found work or NULL if not found.
|
||||||
*/
|
*/
|
||||||
struct callback_head *
|
struct callback_head *
|
||||||
task_work_cancel(struct task_struct *task, task_work_func_t func)
|
task_work_cancel_match(struct task_struct *task,
|
||||||
|
bool (*match)(struct callback_head *, void *data),
|
||||||
|
void *data)
|
||||||
{
|
{
|
||||||
struct callback_head **pprev = &task->task_works;
|
struct callback_head **pprev = &task->task_works;
|
||||||
struct callback_head *work;
|
struct callback_head *work;
|
||||||
|
@ -86,7 +85,7 @@ task_work_cancel(struct task_struct *task, task_work_func_t func)
|
||||||
*/
|
*/
|
||||||
raw_spin_lock_irqsave(&task->pi_lock, flags);
|
raw_spin_lock_irqsave(&task->pi_lock, flags);
|
||||||
while ((work = READ_ONCE(*pprev))) {
|
while ((work = READ_ONCE(*pprev))) {
|
||||||
if (work->func != func)
|
if (!match(work, data))
|
||||||
pprev = &work->next;
|
pprev = &work->next;
|
||||||
else if (cmpxchg(pprev, work, work->next) == work)
|
else if (cmpxchg(pprev, work, work->next) == work)
|
||||||
break;
|
break;
|
||||||
|
@ -96,6 +95,28 @@ task_work_cancel(struct task_struct *task, task_work_func_t func)
|
||||||
return work;
|
return work;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool task_work_func_match(struct callback_head *cb, void *data)
|
||||||
|
{
|
||||||
|
return cb->func == data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* task_work_cancel - cancel a pending work added by task_work_add()
|
||||||
|
* @task: the task which should execute the work
|
||||||
|
* @func: identifies the work to remove
|
||||||
|
*
|
||||||
|
* Find the last queued pending work with ->func == @func and remove
|
||||||
|
* it from queue.
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* The found work or NULL if not found.
|
||||||
|
*/
|
||||||
|
struct callback_head *
|
||||||
|
task_work_cancel(struct task_struct *task, task_work_func_t func)
|
||||||
|
{
|
||||||
|
return task_work_cancel_match(task, task_work_func_match, func);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* task_work_run - execute the works added by task_work_add()
|
* task_work_run - execute the works added by task_work_add()
|
||||||
*
|
*
|
||||||
|
|
Loading…
Add table
Reference in a new issue