diff options
-rw-r--r-- | include/linux/kthread.h | 12 | ||||
-rw-r--r-- | kernel/kthread.c | 21 |
2 files changed, 24 insertions, 9 deletions
diff --git a/include/linux/kthread.h b/include/linux/kthread.h index 5c2ec2c4eb22..4f5235cb13bb 100644 --- a/include/linux/kthread.h +++ b/include/linux/kthread.h | |||
@@ -65,7 +65,12 @@ struct kthread_work; | |||
65 | typedef void (*kthread_work_func_t)(struct kthread_work *work); | 65 | typedef void (*kthread_work_func_t)(struct kthread_work *work); |
66 | void kthread_delayed_work_timer_fn(unsigned long __data); | 66 | void kthread_delayed_work_timer_fn(unsigned long __data); |
67 | 67 | ||
68 | enum { | ||
69 | KTW_FREEZABLE = 1 << 0, /* freeze during suspend */ | ||
70 | }; | ||
71 | |||
68 | struct kthread_worker { | 72 | struct kthread_worker { |
73 | unsigned int flags; | ||
69 | spinlock_t lock; | 74 | spinlock_t lock; |
70 | struct list_head work_list; | 75 | struct list_head work_list; |
71 | struct list_head delayed_work_list; | 76 | struct list_head delayed_work_list; |
@@ -154,12 +159,13 @@ extern void __kthread_init_worker(struct kthread_worker *worker, | |||
154 | 159 | ||
155 | int kthread_worker_fn(void *worker_ptr); | 160 | int kthread_worker_fn(void *worker_ptr); |
156 | 161 | ||
157 | __printf(1, 2) | 162 | __printf(2, 3) |
158 | struct kthread_worker * | 163 | struct kthread_worker * |
159 | kthread_create_worker(const char namefmt[], ...); | 164 | kthread_create_worker(unsigned int flags, const char namefmt[], ...); |
160 | 165 | ||
161 | struct kthread_worker * | 166 | struct kthread_worker * |
162 | kthread_create_worker_on_cpu(int cpu, const char namefmt[], ...); | 167 | kthread_create_worker_on_cpu(int cpu, unsigned int flags, |
168 | const char namefmt[], ...); | ||
163 | 169 | ||
164 | bool kthread_queue_work(struct kthread_worker *worker, | 170 | bool kthread_queue_work(struct kthread_worker *worker, |
165 | struct kthread_work *work); | 171 | struct kthread_work *work); |
diff --git a/kernel/kthread.c b/kernel/kthread.c index c1fcc63fa605..be2cc1f9dd57 100644 --- a/kernel/kthread.c +++ b/kernel/kthread.c | |||
@@ -560,11 +560,11 @@ void __kthread_init_worker(struct kthread_worker *worker, | |||
560 | const char *name, | 560 | const char *name, |
561 | struct lock_class_key *key) | 561 | struct lock_class_key *key) |
562 | { | 562 | { |
563 | memset(worker, 0, sizeof(struct kthread_worker)); | ||
563 | spin_lock_init(&worker->lock); | 564 | spin_lock_init(&worker->lock); |
564 | lockdep_set_class_and_name(&worker->lock, key, name); | 565 | lockdep_set_class_and_name(&worker->lock, key, name); |
565 | INIT_LIST_HEAD(&worker->work_list); | 566 | INIT_LIST_HEAD(&worker->work_list); |
566 | INIT_LIST_HEAD(&worker->delayed_work_list); | 567 | INIT_LIST_HEAD(&worker->delayed_work_list); |
567 | worker->task = NULL; | ||
568 | } | 568 | } |
569 | EXPORT_SYMBOL_GPL(__kthread_init_worker); | 569 | EXPORT_SYMBOL_GPL(__kthread_init_worker); |
570 | 570 | ||
@@ -594,6 +594,10 @@ int kthread_worker_fn(void *worker_ptr) | |||
594 | */ | 594 | */ |
595 | WARN_ON(worker->task && worker->task != current); | 595 | WARN_ON(worker->task && worker->task != current); |
596 | worker->task = current; | 596 | worker->task = current; |
597 | |||
598 | if (worker->flags & KTW_FREEZABLE) | ||
599 | set_freezable(); | ||
600 | |||
597 | repeat: | 601 | repeat: |
598 | set_current_state(TASK_INTERRUPTIBLE); /* mb paired w/ kthread_stop */ | 602 | set_current_state(TASK_INTERRUPTIBLE); /* mb paired w/ kthread_stop */ |
599 | 603 | ||
@@ -627,7 +631,8 @@ repeat: | |||
627 | EXPORT_SYMBOL_GPL(kthread_worker_fn); | 631 | EXPORT_SYMBOL_GPL(kthread_worker_fn); |
628 | 632 | ||
629 | static struct kthread_worker * | 633 | static struct kthread_worker * |
630 | __kthread_create_worker(int cpu, const char namefmt[], va_list args) | 634 | __kthread_create_worker(int cpu, unsigned int flags, |
635 | const char namefmt[], va_list args) | ||
631 | { | 636 | { |
632 | struct kthread_worker *worker; | 637 | struct kthread_worker *worker; |
633 | struct task_struct *task; | 638 | struct task_struct *task; |
@@ -657,6 +662,7 @@ __kthread_create_worker(int cpu, const char namefmt[], va_list args) | |||
657 | if (IS_ERR(task)) | 662 | if (IS_ERR(task)) |
658 | goto fail_task; | 663 | goto fail_task; |
659 | 664 | ||
665 | worker->flags = flags; | ||
660 | worker->task = task; | 666 | worker->task = task; |
661 | wake_up_process(task); | 667 | wake_up_process(task); |
662 | return worker; | 668 | return worker; |
@@ -668,6 +674,7 @@ fail_task: | |||
668 | 674 | ||
669 | /** | 675 | /** |
670 | * kthread_create_worker - create a kthread worker | 676 | * kthread_create_worker - create a kthread worker |
677 | * @flags: flags modifying the default behavior of the worker | ||
671 | * @namefmt: printf-style name for the kthread worker (task). | 678 | * @namefmt: printf-style name for the kthread worker (task). |
672 | * | 679 | * |
673 | * Returns a pointer to the allocated worker on success, ERR_PTR(-ENOMEM) | 680 | * Returns a pointer to the allocated worker on success, ERR_PTR(-ENOMEM) |
@@ -675,13 +682,13 @@ fail_task: | |||
675 | * when the worker was SIGKILLed. | 682 | * when the worker was SIGKILLed. |
676 | */ | 683 | */ |
677 | struct kthread_worker * | 684 | struct kthread_worker * |
678 | kthread_create_worker(const char namefmt[], ...) | 685 | kthread_create_worker(unsigned int flags, const char namefmt[], ...) |
679 | { | 686 | { |
680 | struct kthread_worker *worker; | 687 | struct kthread_worker *worker; |
681 | va_list args; | 688 | va_list args; |
682 | 689 | ||
683 | va_start(args, namefmt); | 690 | va_start(args, namefmt); |
684 | worker = __kthread_create_worker(-1, namefmt, args); | 691 | worker = __kthread_create_worker(-1, flags, namefmt, args); |
685 | va_end(args); | 692 | va_end(args); |
686 | 693 | ||
687 | return worker; | 694 | return worker; |
@@ -692,6 +699,7 @@ EXPORT_SYMBOL(kthread_create_worker); | |||
692 | * kthread_create_worker_on_cpu - create a kthread worker and bind it | 699 | * kthread_create_worker_on_cpu - create a kthread worker and bind it |
693 | * it to a given CPU and the associated NUMA node. | 700 | * it to a given CPU and the associated NUMA node. |
694 | * @cpu: CPU number | 701 | * @cpu: CPU number |
702 | * @flags: flags modifying the default behavior of the worker | ||
695 | * @namefmt: printf-style name for the kthread worker (task). | 703 | * @namefmt: printf-style name for the kthread worker (task). |
696 | * | 704 | * |
697 | * Use a valid CPU number if you want to bind the kthread worker | 705 | * Use a valid CPU number if you want to bind the kthread worker |
@@ -705,13 +713,14 @@ EXPORT_SYMBOL(kthread_create_worker); | |||
705 | * when the worker was SIGKILLed. | 713 | * when the worker was SIGKILLed. |
706 | */ | 714 | */ |
707 | struct kthread_worker * | 715 | struct kthread_worker * |
708 | kthread_create_worker_on_cpu(int cpu, const char namefmt[], ...) | 716 | kthread_create_worker_on_cpu(int cpu, unsigned int flags, |
717 | const char namefmt[], ...) | ||
709 | { | 718 | { |
710 | struct kthread_worker *worker; | 719 | struct kthread_worker *worker; |
711 | va_list args; | 720 | va_list args; |
712 | 721 | ||
713 | va_start(args, namefmt); | 722 | va_start(args, namefmt); |
714 | worker = __kthread_create_worker(cpu, namefmt, args); | 723 | worker = __kthread_create_worker(cpu, flags, namefmt, args); |
715 | va_end(args); | 724 | va_end(args); |
716 | 725 | ||
717 | return worker; | 726 | return worker; |