diff options
author | Oleg Nesterov <oleg@redhat.com> | 2013-04-29 18:05:12 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-04-29 18:54:25 -0400 |
commit | b5c5442bb6bce0c67701d55124be561043a51faf (patch) | |
tree | f00a0fdcdb157fa4b8f54c6a31d3935b7c927aa6 /kernel/kthread.c | |
parent | 4ecdafc8084fe1d95bb59ed7753b345abcd586fb (diff) |
kthread: kill task_get_live_kthread()
task_get_live_kthread() looks confusing and unneeded. It does
get_task_struct() but only kthread_stop() needs this, it can be called
even if the calller doesn't have a reference when we know that this
kthread can't exit until we do kthread_stop().
kthread_park() and kthread_unpark() do not need get_task_struct(), the
callers already have the reference. And it can not help if we can race
with the exiting kthread anyway, kthread_park() can hang forever in this
case.
Change kthread_park() and kthread_unpark() to use to_live_kthread(),
change kthread_stop() to do get_task_struct() by hand and remove
task_get_live_kthread().
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Rusty Russell <rusty@rustcorp.com.au>
Cc: "Srivatsa S. Bhat" <srivatsa.bhat@linux.vnet.ibm.com>
Cc: Tejun Heo <tj@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel/kthread.c')
-rw-r--r-- | kernel/kthread.c | 20 |
1 files changed, 7 insertions, 13 deletions
diff --git a/kernel/kthread.c b/kernel/kthread.c index a84dee265f94..9b12d65186f7 100644 --- a/kernel/kthread.c +++ b/kernel/kthread.c | |||
@@ -324,12 +324,6 @@ struct task_struct *kthread_create_on_cpu(int (*threadfn)(void *data), | |||
324 | return p; | 324 | return p; |
325 | } | 325 | } |
326 | 326 | ||
327 | static struct kthread *task_get_live_kthread(struct task_struct *k) | ||
328 | { | ||
329 | get_task_struct(k); | ||
330 | return to_live_kthread(k); | ||
331 | } | ||
332 | |||
333 | static void __kthread_unpark(struct task_struct *k, struct kthread *kthread) | 327 | static void __kthread_unpark(struct task_struct *k, struct kthread *kthread) |
334 | { | 328 | { |
335 | clear_bit(KTHREAD_SHOULD_PARK, &kthread->flags); | 329 | clear_bit(KTHREAD_SHOULD_PARK, &kthread->flags); |
@@ -356,11 +350,10 @@ static void __kthread_unpark(struct task_struct *k, struct kthread *kthread) | |||
356 | */ | 350 | */ |
357 | void kthread_unpark(struct task_struct *k) | 351 | void kthread_unpark(struct task_struct *k) |
358 | { | 352 | { |
359 | struct kthread *kthread = task_get_live_kthread(k); | 353 | struct kthread *kthread = to_live_kthread(k); |
360 | 354 | ||
361 | if (kthread) | 355 | if (kthread) |
362 | __kthread_unpark(k, kthread); | 356 | __kthread_unpark(k, kthread); |
363 | put_task_struct(k); | ||
364 | } | 357 | } |
365 | 358 | ||
366 | /** | 359 | /** |
@@ -377,7 +370,7 @@ void kthread_unpark(struct task_struct *k) | |||
377 | */ | 370 | */ |
378 | int kthread_park(struct task_struct *k) | 371 | int kthread_park(struct task_struct *k) |
379 | { | 372 | { |
380 | struct kthread *kthread = task_get_live_kthread(k); | 373 | struct kthread *kthread = to_live_kthread(k); |
381 | int ret = -ENOSYS; | 374 | int ret = -ENOSYS; |
382 | 375 | ||
383 | if (kthread) { | 376 | if (kthread) { |
@@ -390,7 +383,6 @@ int kthread_park(struct task_struct *k) | |||
390 | } | 383 | } |
391 | ret = 0; | 384 | ret = 0; |
392 | } | 385 | } |
393 | put_task_struct(k); | ||
394 | return ret; | 386 | return ret; |
395 | } | 387 | } |
396 | 388 | ||
@@ -411,10 +403,13 @@ int kthread_park(struct task_struct *k) | |||
411 | */ | 403 | */ |
412 | int kthread_stop(struct task_struct *k) | 404 | int kthread_stop(struct task_struct *k) |
413 | { | 405 | { |
414 | struct kthread *kthread = task_get_live_kthread(k); | 406 | struct kthread *kthread; |
415 | int ret; | 407 | int ret; |
416 | 408 | ||
417 | trace_sched_kthread_stop(k); | 409 | trace_sched_kthread_stop(k); |
410 | |||
411 | get_task_struct(k); | ||
412 | kthread = to_live_kthread(k); | ||
418 | if (kthread) { | 413 | if (kthread) { |
419 | set_bit(KTHREAD_SHOULD_STOP, &kthread->flags); | 414 | set_bit(KTHREAD_SHOULD_STOP, &kthread->flags); |
420 | __kthread_unpark(k, kthread); | 415 | __kthread_unpark(k, kthread); |
@@ -422,10 +417,9 @@ int kthread_stop(struct task_struct *k) | |||
422 | wait_for_completion(&kthread->exited); | 417 | wait_for_completion(&kthread->exited); |
423 | } | 418 | } |
424 | ret = k->exit_code; | 419 | ret = k->exit_code; |
425 | |||
426 | put_task_struct(k); | 420 | put_task_struct(k); |
427 | trace_sched_kthread_stop_ret(ret); | ||
428 | 421 | ||
422 | trace_sched_kthread_stop_ret(ret); | ||
429 | return ret; | 423 | return ret; |
430 | } | 424 | } |
431 | EXPORT_SYMBOL(kthread_stop); | 425 | EXPORT_SYMBOL(kthread_stop); |