diff options
| -rw-r--r-- | include/linux/workqueue.h | 25 | ||||
| -rw-r--r-- | kernel/workqueue.c | 17 |
2 files changed, 22 insertions, 20 deletions
diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h index e724dafc9e6d..d89cfc143b1a 100644 --- a/include/linux/workqueue.h +++ b/include/linux/workqueue.h | |||
| @@ -184,13 +184,17 @@ static inline unsigned int work_static(struct work_struct *work) { return 0; } | |||
| 184 | #define work_clear_pending(work) \ | 184 | #define work_clear_pending(work) \ |
| 185 | clear_bit(WORK_STRUCT_PENDING, work_data_bits(work)) | 185 | clear_bit(WORK_STRUCT_PENDING, work_data_bits(work)) |
| 186 | 186 | ||
| 187 | enum { | ||
| 188 | WQ_FREEZEABLE = 1 << 0, /* freeze during suspend */ | ||
| 189 | WQ_SINGLE_THREAD = 1 << 1, /* no per-cpu worker */ | ||
| 190 | }; | ||
| 187 | 191 | ||
| 188 | extern struct workqueue_struct * | 192 | extern struct workqueue_struct * |
| 189 | __create_workqueue_key(const char *name, int singlethread, int freezeable, | 193 | __create_workqueue_key(const char *name, unsigned int flags, |
| 190 | struct lock_class_key *key, const char *lock_name); | 194 | struct lock_class_key *key, const char *lock_name); |
| 191 | 195 | ||
| 192 | #ifdef CONFIG_LOCKDEP | 196 | #ifdef CONFIG_LOCKDEP |
| 193 | #define __create_workqueue(name, singlethread, freezeable) \ | 197 | #define __create_workqueue(name, flags) \ |
| 194 | ({ \ | 198 | ({ \ |
| 195 | static struct lock_class_key __key; \ | 199 | static struct lock_class_key __key; \ |
| 196 | const char *__lock_name; \ | 200 | const char *__lock_name; \ |
| @@ -200,19 +204,20 @@ __create_workqueue_key(const char *name, int singlethread, int freezeable, | |||
| 200 | else \ | 204 | else \ |
| 201 | __lock_name = #name; \ | 205 | __lock_name = #name; \ |
| 202 | \ | 206 | \ |
| 203 | __create_workqueue_key((name), (singlethread), \ | 207 | __create_workqueue_key((name), (flags), &__key, \ |
| 204 | (freezeable), &__key, \ | ||
| 205 | __lock_name); \ | 208 | __lock_name); \ |
| 206 | }) | 209 | }) |
| 207 | #else | 210 | #else |
| 208 | #define __create_workqueue(name, singlethread, freezeable) \ | 211 | #define __create_workqueue(name, flags) \ |
| 209 | __create_workqueue_key((name), (singlethread), (freezeable), \ | 212 | __create_workqueue_key((name), (flags), NULL, NULL) |
| 210 | NULL, NULL) | ||
| 211 | #endif | 213 | #endif |
| 212 | 214 | ||
| 213 | #define create_workqueue(name) __create_workqueue((name), 0, 0) | 215 | #define create_workqueue(name) \ |
| 214 | #define create_freezeable_workqueue(name) __create_workqueue((name), 1, 1) | 216 | __create_workqueue((name), 0) |
| 215 | #define create_singlethread_workqueue(name) __create_workqueue((name), 1, 0) | 217 | #define create_freezeable_workqueue(name) \ |
| 218 | __create_workqueue((name), WQ_FREEZEABLE | WQ_SINGLE_THREAD) | ||
| 219 | #define create_singlethread_workqueue(name) \ | ||
| 220 | __create_workqueue((name), WQ_SINGLE_THREAD) | ||
| 216 | 221 | ||
| 217 | extern void destroy_workqueue(struct workqueue_struct *wq); | 222 | extern void destroy_workqueue(struct workqueue_struct *wq); |
| 218 | 223 | ||
diff --git a/kernel/workqueue.c b/kernel/workqueue.c index c56146a755e5..68e4dd808ec0 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c | |||
| @@ -67,11 +67,10 @@ struct cpu_workqueue_struct { | |||
| 67 | * per-CPU workqueues: | 67 | * per-CPU workqueues: |
| 68 | */ | 68 | */ |
| 69 | struct workqueue_struct { | 69 | struct workqueue_struct { |
| 70 | unsigned int flags; /* I: WQ_* flags */ | ||
| 70 | struct cpu_workqueue_struct *cpu_wq; /* I: cwq's */ | 71 | struct cpu_workqueue_struct *cpu_wq; /* I: cwq's */ |
| 71 | struct list_head list; /* W: list of all workqueues */ | 72 | struct list_head list; /* W: list of all workqueues */ |
| 72 | const char *name; /* I: workqueue name */ | 73 | const char *name; /* I: workqueue name */ |
| 73 | int singlethread; | ||
| 74 | int freezeable; /* Freeze threads during suspend */ | ||
| 75 | #ifdef CONFIG_LOCKDEP | 74 | #ifdef CONFIG_LOCKDEP |
| 76 | struct lockdep_map lockdep_map; | 75 | struct lockdep_map lockdep_map; |
| 77 | #endif | 76 | #endif |
| @@ -203,9 +202,9 @@ static const struct cpumask *cpu_singlethread_map __read_mostly; | |||
| 203 | static cpumask_var_t cpu_populated_map __read_mostly; | 202 | static cpumask_var_t cpu_populated_map __read_mostly; |
| 204 | 203 | ||
| 205 | /* If it's single threaded, it isn't in the list of workqueues. */ | 204 | /* If it's single threaded, it isn't in the list of workqueues. */ |
| 206 | static inline int is_wq_single_threaded(struct workqueue_struct *wq) | 205 | static inline bool is_wq_single_threaded(struct workqueue_struct *wq) |
| 207 | { | 206 | { |
| 208 | return wq->singlethread; | 207 | return wq->flags & WQ_SINGLE_THREAD; |
| 209 | } | 208 | } |
| 210 | 209 | ||
| 211 | static const struct cpumask *wq_cpu_map(struct workqueue_struct *wq) | 210 | static const struct cpumask *wq_cpu_map(struct workqueue_struct *wq) |
| @@ -463,7 +462,7 @@ static int worker_thread(void *__cwq) | |||
| 463 | struct cpu_workqueue_struct *cwq = __cwq; | 462 | struct cpu_workqueue_struct *cwq = __cwq; |
| 464 | DEFINE_WAIT(wait); | 463 | DEFINE_WAIT(wait); |
| 465 | 464 | ||
| 466 | if (cwq->wq->freezeable) | 465 | if (cwq->wq->flags & WQ_FREEZEABLE) |
| 467 | set_freezable(); | 466 | set_freezable(); |
| 468 | 467 | ||
| 469 | for (;;) { | 468 | for (;;) { |
| @@ -1013,8 +1012,7 @@ static void start_workqueue_thread(struct cpu_workqueue_struct *cwq, int cpu) | |||
| 1013 | } | 1012 | } |
| 1014 | 1013 | ||
| 1015 | struct workqueue_struct *__create_workqueue_key(const char *name, | 1014 | struct workqueue_struct *__create_workqueue_key(const char *name, |
| 1016 | int singlethread, | 1015 | unsigned int flags, |
| 1017 | int freezeable, | ||
| 1018 | struct lock_class_key *key, | 1016 | struct lock_class_key *key, |
| 1019 | const char *lock_name) | 1017 | const char *lock_name) |
| 1020 | { | 1018 | { |
| @@ -1030,13 +1028,12 @@ struct workqueue_struct *__create_workqueue_key(const char *name, | |||
| 1030 | if (!wq->cpu_wq) | 1028 | if (!wq->cpu_wq) |
| 1031 | goto err; | 1029 | goto err; |
| 1032 | 1030 | ||
| 1031 | wq->flags = flags; | ||
| 1033 | wq->name = name; | 1032 | wq->name = name; |
| 1034 | lockdep_init_map(&wq->lockdep_map, lock_name, key, 0); | 1033 | lockdep_init_map(&wq->lockdep_map, lock_name, key, 0); |
| 1035 | wq->singlethread = singlethread; | ||
| 1036 | wq->freezeable = freezeable; | ||
| 1037 | INIT_LIST_HEAD(&wq->list); | 1034 | INIT_LIST_HEAD(&wq->list); |
| 1038 | 1035 | ||
| 1039 | if (singlethread) { | 1036 | if (flags & WQ_SINGLE_THREAD) { |
| 1040 | cwq = init_cpu_workqueue(wq, singlethread_cpu); | 1037 | cwq = init_cpu_workqueue(wq, singlethread_cpu); |
| 1041 | err = create_workqueue_thread(cwq, singlethread_cpu); | 1038 | err = create_workqueue_thread(cwq, singlethread_cpu); |
| 1042 | start_workqueue_thread(cwq, -1); | 1039 | start_workqueue_thread(cwq, -1); |
