]>
git.ipfire.org Git - thirdparty/linux.git/blob - kernel/vhost_task.c
1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2021 Oracle Corporation
5 #include <linux/slab.h>
6 #include <linux/completion.h>
7 #include <linux/sched/task.h>
8 #include <linux/sched/vhost_task.h>
9 #include <linux/sched/signal.h>
11 enum vhost_task_flags
{
12 VHOST_TASK_FLAGS_STOP
,
16 bool (*fn
)(void *data
);
18 struct completion exited
;
20 struct task_struct
*task
;
23 static int vhost_task_fn(void *data
)
25 struct vhost_task
*vtsk
= data
;
31 if (!dead
&& signal_pending(current
)) {
34 * Calling get_signal will block in SIGSTOP,
35 * or clear fatal_signal_pending, but remember
38 * This thread won't actually exit until all
39 * of the file descriptors are closed, and
40 * the release function is called.
42 dead
= get_signal(&ksig
);
44 clear_thread_flag(TIF_SIGPENDING
);
47 /* mb paired w/ vhost_task_stop */
48 set_current_state(TASK_INTERRUPTIBLE
);
50 if (test_bit(VHOST_TASK_FLAGS_STOP
, &vtsk
->flags
)) {
51 __set_current_state(TASK_RUNNING
);
55 did_work
= vtsk
->fn(vtsk
->data
);
60 complete(&vtsk
->exited
);
65 * vhost_task_wake - wakeup the vhost_task
66 * @vtsk: vhost_task to wake
68 * wake up the vhost_task worker thread
70 void vhost_task_wake(struct vhost_task
*vtsk
)
72 wake_up_process(vtsk
->task
);
74 EXPORT_SYMBOL_GPL(vhost_task_wake
);
77 * vhost_task_stop - stop a vhost_task
78 * @vtsk: vhost_task to stop
80 * vhost_task_fn ensures the worker thread exits after
81 * VHOST_TASK_FLAGS_SOP becomes true.
83 void vhost_task_stop(struct vhost_task
*vtsk
)
85 set_bit(VHOST_TASK_FLAGS_STOP
, &vtsk
->flags
);
86 vhost_task_wake(vtsk
);
88 * Make sure vhost_task_fn is no longer accessing the vhost_task before
91 wait_for_completion(&vtsk
->exited
);
94 EXPORT_SYMBOL_GPL(vhost_task_stop
);
97 * vhost_task_create - create a copy of a task to be used by the kernel
98 * @fn: vhost worker function
99 * @arg: data to be passed to fn
100 * @name: the thread's name
102 * This returns a specialized task for use by the vhost layer or NULL on
103 * failure. The returned task is inactive, and the caller must fire it up
104 * through vhost_task_start().
106 struct vhost_task
*vhost_task_create(bool (*fn
)(void *), void *arg
,
109 struct kernel_clone_args args
= {
110 .flags
= CLONE_FS
| CLONE_UNTRACED
| CLONE_VM
|
111 CLONE_THREAD
| CLONE_SIGHAND
,
118 struct vhost_task
*vtsk
;
119 struct task_struct
*tsk
;
121 vtsk
= kzalloc(sizeof(*vtsk
), GFP_KERNEL
);
124 init_completion(&vtsk
->exited
);
130 tsk
= copy_process(NULL
, 0, NUMA_NO_NODE
, &args
);
139 EXPORT_SYMBOL_GPL(vhost_task_create
);
142 * vhost_task_start - start a vhost_task created with vhost_task_create
143 * @vtsk: vhost_task to wake up
145 void vhost_task_start(struct vhost_task
*vtsk
)
147 wake_up_new_task(vtsk
->task
);
149 EXPORT_SYMBOL_GPL(vhost_task_start
);