X-Git-Url: http://git.cascardo.info/?a=blobdiff_plain;f=kernel%2Fkthread.c;h=36fd751a769f4839100a54e2027ad57bb38ed117;hb=255451e45345bcd19e79f25e9afc0b9e14ccb104;hp=4ab4c3766a80ddf917cb988ac9c55d48957edbc4;hpb=b4f33f6ddd0c218e12454e1379de3aaa73f2e8dc;p=cascardo%2Flinux.git diff --git a/kernel/kthread.c b/kernel/kthread.c index 4ab4c3766a80..36fd751a769f 100644 --- a/kernel/kthread.c +++ b/kernel/kthread.c @@ -138,7 +138,7 @@ void *kthread_data(struct task_struct *task) } /** - * probe_kthread_data - speculative version of kthread_data() + * kthread_probe_data - speculative version of kthread_data() * @task: possible kthread task in question * * @task could be a kthread task. Return the data value specified when it @@ -146,7 +146,7 @@ void *kthread_data(struct task_struct *task) * inaccessible for any reason, %NULL is returned. This function requires * that @task itself is safe to dereference. */ -void *probe_kthread_data(struct task_struct *task) +void *kthread_probe_data(struct task_struct *task) { struct kthread *kthread = to_kthread(task); void *data = NULL; @@ -244,33 +244,10 @@ static void create_kthread(struct kthread_create_info *create) } } -/** - * kthread_create_on_node - create a kthread. - * @threadfn: the function to run until signal_pending(current). - * @data: data ptr for @threadfn. - * @node: task and thread structures for the thread are allocated on this node - * @namefmt: printf-style name for the thread. - * - * Description: This helper function creates and names a kernel - * thread. The thread will be stopped: use wake_up_process() to start - * it. See also kthread_run(). The new thread has SCHED_NORMAL policy and - * is affine to all CPUs. - * - * If thread is going to be bound on a particular cpu, give its node - * in @node, to get NUMA affinity for kthread stack, or else give NUMA_NO_NODE. - * When woken, the thread will run @threadfn() with @data as its - * argument. @threadfn() can either call do_exit() directly if it is a - * standalone thread for which no one will call kthread_stop(), or - * return when 'kthread_should_stop()' is true (which means - * kthread_stop() has been called). The return value should be zero - * or a negative error number; it will be passed to kthread_stop(). - * - * Returns a task_struct or ERR_PTR(-ENOMEM) or ERR_PTR(-EINTR). - */ -struct task_struct *kthread_create_on_node(int (*threadfn)(void *data), - void *data, int node, - const char namefmt[], - ...) +static struct task_struct *__kthread_create_on_node(int (*threadfn)(void *data), + void *data, int node, + const char namefmt[], + va_list args) { DECLARE_COMPLETION_ONSTACK(done); struct task_struct *task; @@ -311,11 +288,8 @@ struct task_struct *kthread_create_on_node(int (*threadfn)(void *data), task = create->result; if (!IS_ERR(task)) { static const struct sched_param param = { .sched_priority = 0 }; - va_list args; - va_start(args, namefmt); vsnprintf(task->comm, sizeof(task->comm), namefmt, args); - va_end(args); /* * root may have changed our (kthreadd's) priority or CPU mask. * The kernel thread should not inherit these properties. @@ -326,6 +300,44 @@ struct task_struct *kthread_create_on_node(int (*threadfn)(void *data), kfree(create); return task; } + +/** + * kthread_create_on_node - create a kthread. + * @threadfn: the function to run until signal_pending(current). + * @data: data ptr for @threadfn. + * @node: task and thread structures for the thread are allocated on this node + * @namefmt: printf-style name for the thread. + * + * Description: This helper function creates and names a kernel + * thread. The thread will be stopped: use wake_up_process() to start + * it. See also kthread_run(). The new thread has SCHED_NORMAL policy and + * is affine to all CPUs. + * + * If thread is going to be bound on a particular cpu, give its node + * in @node, to get NUMA affinity for kthread stack, or else give NUMA_NO_NODE. + * When woken, the thread will run @threadfn() with @data as its + * argument. @threadfn() can either call do_exit() directly if it is a + * standalone thread for which no one will call kthread_stop(), or + * return when 'kthread_should_stop()' is true (which means + * kthread_stop() has been called). The return value should be zero + * or a negative error number; it will be passed to kthread_stop(). + * + * Returns a task_struct or ERR_PTR(-ENOMEM) or ERR_PTR(-EINTR). + */ +struct task_struct *kthread_create_on_node(int (*threadfn)(void *data), + void *data, int node, + const char namefmt[], + ...) +{ + struct task_struct *task; + va_list args; + + va_start(args, namefmt); + task = __kthread_create_on_node(threadfn, data, node, namefmt, args); + va_end(args); + + return task; +} EXPORT_SYMBOL(kthread_create_on_node); static void __kthread_bind_mask(struct task_struct *p, const struct cpumask *mask, long state) @@ -390,10 +402,10 @@ struct task_struct *kthread_create_on_cpu(int (*threadfn)(void *data), cpu); if (IS_ERR(p)) return p; + kthread_bind(p, cpu); + /* CPU hotplug need to bind once again when unparking the thread. */ set_bit(KTHREAD_IS_PER_CPU, &to_kthread(p)->flags); to_kthread(p)->cpu = cpu; - /* Park the thread to get it out of TASK_UNINTERRUPTIBLE state */ - kthread_park(p); return p; } @@ -407,6 +419,10 @@ static void __kthread_unpark(struct task_struct *k, struct kthread *kthread) * which might be about to be cleared. */ if (test_and_clear_bit(KTHREAD_IS_PARKED, &kthread->flags)) { + /* + * Newly created kthread was parked when the CPU was offline. + * The binding was lost and we need to set it again. + */ if (test_bit(KTHREAD_IS_PER_CPU, &kthread->flags)) __kthread_bind(k, kthread->cpu, TASK_PARKED); wake_up_state(k, TASK_PARKED); @@ -540,7 +556,7 @@ int kthreadd(void *unused) return 0; } -void __init_kthread_worker(struct kthread_worker *worker, +void __kthread_init_worker(struct kthread_worker *worker, const char *name, struct lock_class_key *key) { @@ -549,7 +565,7 @@ void __init_kthread_worker(struct kthread_worker *worker, INIT_LIST_HEAD(&worker->work_list); worker->task = NULL; } -EXPORT_SYMBOL_GPL(__init_kthread_worker); +EXPORT_SYMBOL_GPL(__kthread_init_worker); /** * kthread_worker_fn - kthread function to process kthread_worker @@ -606,7 +622,7 @@ repeat: EXPORT_SYMBOL_GPL(kthread_worker_fn); /* insert @work before @pos in @worker */ -static void insert_kthread_work(struct kthread_worker *worker, +static void kthread_insert_work(struct kthread_worker *worker, struct kthread_work *work, struct list_head *pos) { @@ -619,7 +635,7 @@ static void insert_kthread_work(struct kthread_worker *worker, } /** - * queue_kthread_work - queue a kthread_work + * kthread_queue_work - queue a kthread_work * @worker: target kthread_worker * @work: kthread_work to queue * @@ -627,7 +643,7 @@ static void insert_kthread_work(struct kthread_worker *worker, * must have been created with kthread_worker_create(). Returns %true * if @work was successfully queued, %false if it was already pending. */ -bool queue_kthread_work(struct kthread_worker *worker, +bool kthread_queue_work(struct kthread_worker *worker, struct kthread_work *work) { bool ret = false; @@ -635,13 +651,13 @@ bool queue_kthread_work(struct kthread_worker *worker, spin_lock_irqsave(&worker->lock, flags); if (list_empty(&work->node)) { - insert_kthread_work(worker, work, &worker->work_list); + kthread_insert_work(worker, work, &worker->work_list); ret = true; } spin_unlock_irqrestore(&worker->lock, flags); return ret; } -EXPORT_SYMBOL_GPL(queue_kthread_work); +EXPORT_SYMBOL_GPL(kthread_queue_work); struct kthread_flush_work { struct kthread_work work; @@ -656,12 +672,12 @@ static void kthread_flush_work_fn(struct kthread_work *work) } /** - * flush_kthread_work - flush a kthread_work + * kthread_flush_work - flush a kthread_work * @work: work to flush * * If @work is queued or executing, wait for it to finish execution. */ -void flush_kthread_work(struct kthread_work *work) +void kthread_flush_work(struct kthread_work *work) { struct kthread_flush_work fwork = { KTHREAD_WORK_INIT(fwork.work, kthread_flush_work_fn), @@ -682,9 +698,10 @@ retry: } if (!list_empty(&work->node)) - insert_kthread_work(worker, &fwork.work, work->node.next); + kthread_insert_work(worker, &fwork.work, work->node.next); else if (worker->current_work == work) - insert_kthread_work(worker, &fwork.work, worker->work_list.next); + kthread_insert_work(worker, &fwork.work, + worker->work_list.next); else noop = true; @@ -693,23 +710,23 @@ retry: if (!noop) wait_for_completion(&fwork.done); } -EXPORT_SYMBOL_GPL(flush_kthread_work); +EXPORT_SYMBOL_GPL(kthread_flush_work); /** - * flush_kthread_worker - flush all current works on a kthread_worker + * kthread_flush_worker - flush all current works on a kthread_worker * @worker: worker to flush * * Wait until all currently executing or pending works on @worker are * finished. */ -void flush_kthread_worker(struct kthread_worker *worker) +void kthread_flush_worker(struct kthread_worker *worker) { struct kthread_flush_work fwork = { KTHREAD_WORK_INIT(fwork.work, kthread_flush_work_fn), COMPLETION_INITIALIZER_ONSTACK(fwork.done), }; - queue_kthread_work(worker, &fwork.work); + kthread_queue_work(worker, &fwork.work); wait_for_completion(&fwork.done); } -EXPORT_SYMBOL_GPL(flush_kthread_worker); +EXPORT_SYMBOL_GPL(kthread_flush_worker);