|
@@ -571,23 +571,24 @@ EXPORT_SYMBOL_GPL(__kthread_init_worker);
|
|
* kthread_worker_fn - kthread function to process kthread_worker
|
|
* kthread_worker_fn - kthread function to process kthread_worker
|
|
* @worker_ptr: pointer to initialized kthread_worker
|
|
* @worker_ptr: pointer to initialized kthread_worker
|
|
*
|
|
*
|
|
- * This function can be used as @threadfn to kthread_create() or
|
|
|
|
- * kthread_run() with @worker_ptr argument pointing to an initialized
|
|
|
|
- * kthread_worker. The started kthread will process work_list until
|
|
|
|
- * the it is stopped with kthread_stop(). A kthread can also call
|
|
|
|
- * this function directly after extra initialization.
|
|
|
|
|
|
+ * This function implements the main cycle of kthread worker. It processes
|
|
|
|
+ * work_list until it is stopped with kthread_stop(). It sleeps when the queue
|
|
|
|
+ * is empty.
|
|
*
|
|
*
|
|
- * Different kthreads can be used for the same kthread_worker as long
|
|
|
|
- * as there's only one kthread attached to it at any given time. A
|
|
|
|
- * kthread_worker without an attached kthread simply collects queued
|
|
|
|
- * kthread_works.
|
|
|
|
|
|
+ * The works are not allowed to keep any locks, disable preemption or interrupts
|
|
|
|
+ * when they finish. There is defined a safe point for freezing when one work
|
|
|
|
+ * finishes and before a new one is started.
|
|
*/
|
|
*/
|
|
int kthread_worker_fn(void *worker_ptr)
|
|
int kthread_worker_fn(void *worker_ptr)
|
|
{
|
|
{
|
|
struct kthread_worker *worker = worker_ptr;
|
|
struct kthread_worker *worker = worker_ptr;
|
|
struct kthread_work *work;
|
|
struct kthread_work *work;
|
|
|
|
|
|
- WARN_ON(worker->task);
|
|
|
|
|
|
+ /*
|
|
|
|
+ * FIXME: Update the check and remove the assignment when all kthread
|
|
|
|
+ * worker users are created using kthread_create_worker*() functions.
|
|
|
|
+ */
|
|
|
|
+ WARN_ON(worker->task && worker->task != current);
|
|
worker->task = current;
|
|
worker->task = current;
|
|
repeat:
|
|
repeat:
|
|
set_current_state(TASK_INTERRUPTIBLE); /* mb paired w/ kthread_stop */
|
|
set_current_state(TASK_INTERRUPTIBLE); /* mb paired w/ kthread_stop */
|
|
@@ -621,6 +622,98 @@ repeat:
|
|
}
|
|
}
|
|
EXPORT_SYMBOL_GPL(kthread_worker_fn);
|
|
EXPORT_SYMBOL_GPL(kthread_worker_fn);
|
|
|
|
|
|
|
|
+static struct kthread_worker *
|
|
|
|
+__kthread_create_worker(int cpu, const char namefmt[], va_list args)
|
|
|
|
+{
|
|
|
|
+ struct kthread_worker *worker;
|
|
|
|
+ struct task_struct *task;
|
|
|
|
+
|
|
|
|
+ worker = kzalloc(sizeof(*worker), GFP_KERNEL);
|
|
|
|
+ if (!worker)
|
|
|
|
+ return ERR_PTR(-ENOMEM);
|
|
|
|
+
|
|
|
|
+ kthread_init_worker(worker);
|
|
|
|
+
|
|
|
|
+ if (cpu >= 0) {
|
|
|
|
+ char name[TASK_COMM_LEN];
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * kthread_create_worker_on_cpu() allows to pass a generic
|
|
|
|
+ * namefmt in compare with kthread_create_on_cpu. We need
|
|
|
|
+ * to format it here.
|
|
|
|
+ */
|
|
|
|
+ vsnprintf(name, sizeof(name), namefmt, args);
|
|
|
|
+ task = kthread_create_on_cpu(kthread_worker_fn, worker,
|
|
|
|
+ cpu, name);
|
|
|
|
+ } else {
|
|
|
|
+ task = __kthread_create_on_node(kthread_worker_fn, worker,
|
|
|
|
+ -1, namefmt, args);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (IS_ERR(task))
|
|
|
|
+ goto fail_task;
|
|
|
|
+
|
|
|
|
+ worker->task = task;
|
|
|
|
+ wake_up_process(task);
|
|
|
|
+ return worker;
|
|
|
|
+
|
|
|
|
+fail_task:
|
|
|
|
+ kfree(worker);
|
|
|
|
+ return ERR_CAST(task);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * kthread_create_worker - create a kthread worker
|
|
|
|
+ * @namefmt: printf-style name for the kthread worker (task).
|
|
|
|
+ *
|
|
|
|
+ * Returns a pointer to the allocated worker on success, ERR_PTR(-ENOMEM)
|
|
|
|
+ * when the needed structures could not get allocated, and ERR_PTR(-EINTR)
|
|
|
|
+ * when the worker was SIGKILLed.
|
|
|
|
+ */
|
|
|
|
+struct kthread_worker *
|
|
|
|
+kthread_create_worker(const char namefmt[], ...)
|
|
|
|
+{
|
|
|
|
+ struct kthread_worker *worker;
|
|
|
|
+ va_list args;
|
|
|
|
+
|
|
|
|
+ va_start(args, namefmt);
|
|
|
|
+ worker = __kthread_create_worker(-1, namefmt, args);
|
|
|
|
+ va_end(args);
|
|
|
|
+
|
|
|
|
+ return worker;
|
|
|
|
+}
|
|
|
|
+EXPORT_SYMBOL(kthread_create_worker);
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * kthread_create_worker_on_cpu - create a kthread worker and bind it
|
|
|
|
+ * it to a given CPU and the associated NUMA node.
|
|
|
|
+ * @cpu: CPU number
|
|
|
|
+ * @namefmt: printf-style name for the kthread worker (task).
|
|
|
|
+ *
|
|
|
|
+ * Use a valid CPU number if you want to bind the kthread worker
|
|
|
|
+ * to the given CPU and the associated NUMA node.
|
|
|
|
+ *
|
|
|
|
+ * A good practice is to add the cpu number also into the worker name.
|
|
|
|
+ * For example, use kthread_create_worker_on_cpu(cpu, "helper/%d", cpu).
|
|
|
|
+ *
|
|
|
|
+ * Returns a pointer to the allocated worker on success, ERR_PTR(-ENOMEM)
|
|
|
|
+ * when the needed structures could not get allocated, and ERR_PTR(-EINTR)
|
|
|
|
+ * when the worker was SIGKILLed.
|
|
|
|
+ */
|
|
|
|
+struct kthread_worker *
|
|
|
|
+kthread_create_worker_on_cpu(int cpu, const char namefmt[], ...)
|
|
|
|
+{
|
|
|
|
+ struct kthread_worker *worker;
|
|
|
|
+ va_list args;
|
|
|
|
+
|
|
|
|
+ va_start(args, namefmt);
|
|
|
|
+ worker = __kthread_create_worker(cpu, namefmt, args);
|
|
|
|
+ va_end(args);
|
|
|
|
+
|
|
|
|
+ return worker;
|
|
|
|
+}
|
|
|
|
+EXPORT_SYMBOL(kthread_create_worker_on_cpu);
|
|
|
|
+
|
|
/* insert @work before @pos in @worker */
|
|
/* insert @work before @pos in @worker */
|
|
static void kthread_insert_work(struct kthread_worker *worker,
|
|
static void kthread_insert_work(struct kthread_worker *worker,
|
|
struct kthread_work *work,
|
|
struct kthread_work *work,
|