diff options
Diffstat (limited to 'kernel/workqueue.c')
-rw-r--r-- | kernel/workqueue.c | 47 |
1 files changed, 28 insertions, 19 deletions
diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 6fa847c5c5e9..558733801ac0 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c | |||
@@ -601,7 +601,7 @@ struct task_struct *wq_worker_sleeping(struct task_struct *task, | |||
601 | 601 | ||
602 | /** | 602 | /** |
603 | * worker_set_flags - set worker flags and adjust nr_running accordingly | 603 | * worker_set_flags - set worker flags and adjust nr_running accordingly |
604 | * @worker: worker to set flags for | 604 | * @worker: self |
605 | * @flags: flags to set | 605 | * @flags: flags to set |
606 | * @wakeup: wakeup an idle worker if necessary | 606 | * @wakeup: wakeup an idle worker if necessary |
607 | * | 607 | * |
@@ -609,14 +609,16 @@ struct task_struct *wq_worker_sleeping(struct task_struct *task, | |||
609 | * nr_running becomes zero and @wakeup is %true, an idle worker is | 609 | * nr_running becomes zero and @wakeup is %true, an idle worker is |
610 | * woken up. | 610 | * woken up. |
611 | * | 611 | * |
612 | * LOCKING: | 612 | * CONTEXT: |
613 | * spin_lock_irq(gcwq->lock). | 613 | * spin_lock_irq(gcwq->lock) |
614 | */ | 614 | */ |
615 | static inline void worker_set_flags(struct worker *worker, unsigned int flags, | 615 | static inline void worker_set_flags(struct worker *worker, unsigned int flags, |
616 | bool wakeup) | 616 | bool wakeup) |
617 | { | 617 | { |
618 | struct global_cwq *gcwq = worker->gcwq; | 618 | struct global_cwq *gcwq = worker->gcwq; |
619 | 619 | ||
620 | WARN_ON_ONCE(worker->task != current); | ||
621 | |||
620 | /* | 622 | /* |
621 | * If transitioning into NOT_RUNNING, adjust nr_running and | 623 | * If transitioning into NOT_RUNNING, adjust nr_running and |
622 | * wake up an idle worker as necessary if requested by | 624 | * wake up an idle worker as necessary if requested by |
@@ -639,19 +641,21 @@ static inline void worker_set_flags(struct worker *worker, unsigned int flags, | |||
639 | 641 | ||
640 | /** | 642 | /** |
641 | * worker_clr_flags - clear worker flags and adjust nr_running accordingly | 643 | * worker_clr_flags - clear worker flags and adjust nr_running accordingly |
642 | * @worker: worker to set flags for | 644 | * @worker: self |
643 | * @flags: flags to clear | 645 | * @flags: flags to clear |
644 | * | 646 | * |
645 | * Clear @flags in @worker->flags and adjust nr_running accordingly. | 647 | * Clear @flags in @worker->flags and adjust nr_running accordingly. |
646 | * | 648 | * |
647 | * LOCKING: | 649 | * CONTEXT: |
648 | * spin_lock_irq(gcwq->lock). | 650 | * spin_lock_irq(gcwq->lock) |
649 | */ | 651 | */ |
650 | static inline void worker_clr_flags(struct worker *worker, unsigned int flags) | 652 | static inline void worker_clr_flags(struct worker *worker, unsigned int flags) |
651 | { | 653 | { |
652 | struct global_cwq *gcwq = worker->gcwq; | 654 | struct global_cwq *gcwq = worker->gcwq; |
653 | unsigned int oflags = worker->flags; | 655 | unsigned int oflags = worker->flags; |
654 | 656 | ||
657 | WARN_ON_ONCE(worker->task != current); | ||
658 | |||
655 | worker->flags &= ~flags; | 659 | worker->flags &= ~flags; |
656 | 660 | ||
657 | /* if transitioning out of NOT_RUNNING, increment nr_running */ | 661 | /* if transitioning out of NOT_RUNNING, increment nr_running */ |
@@ -1073,7 +1077,8 @@ static void worker_enter_idle(struct worker *worker) | |||
1073 | BUG_ON(!list_empty(&worker->entry) && | 1077 | BUG_ON(!list_empty(&worker->entry) && |
1074 | (worker->hentry.next || worker->hentry.pprev)); | 1078 | (worker->hentry.next || worker->hentry.pprev)); |
1075 | 1079 | ||
1076 | worker_set_flags(worker, WORKER_IDLE, false); | 1080 | /* can't use worker_set_flags(), also called from start_worker() */ |
1081 | worker->flags |= WORKER_IDLE; | ||
1077 | gcwq->nr_idle++; | 1082 | gcwq->nr_idle++; |
1078 | worker->last_active = jiffies; | 1083 | worker->last_active = jiffies; |
1079 | 1084 | ||
@@ -1086,6 +1091,10 @@ static void worker_enter_idle(struct worker *worker) | |||
1086 | jiffies + IDLE_WORKER_TIMEOUT); | 1091 | jiffies + IDLE_WORKER_TIMEOUT); |
1087 | } else | 1092 | } else |
1088 | wake_up_all(&gcwq->trustee_wait); | 1093 | wake_up_all(&gcwq->trustee_wait); |
1094 | |||
1095 | /* sanity check nr_running */ | ||
1096 | WARN_ON_ONCE(gcwq->nr_workers == gcwq->nr_idle && | ||
1097 | atomic_read(get_gcwq_nr_running(gcwq->cpu))); | ||
1089 | } | 1098 | } |
1090 | 1099 | ||
1091 | /** | 1100 | /** |
@@ -1270,7 +1279,7 @@ fail: | |||
1270 | */ | 1279 | */ |
1271 | static void start_worker(struct worker *worker) | 1280 | static void start_worker(struct worker *worker) |
1272 | { | 1281 | { |
1273 | worker_set_flags(worker, WORKER_STARTED, false); | 1282 | worker->flags |= WORKER_STARTED; |
1274 | worker->gcwq->nr_workers++; | 1283 | worker->gcwq->nr_workers++; |
1275 | worker_enter_idle(worker); | 1284 | worker_enter_idle(worker); |
1276 | wake_up_process(worker->task); | 1285 | wake_up_process(worker->task); |
@@ -1300,7 +1309,7 @@ static void destroy_worker(struct worker *worker) | |||
1300 | gcwq->nr_idle--; | 1309 | gcwq->nr_idle--; |
1301 | 1310 | ||
1302 | list_del_init(&worker->entry); | 1311 | list_del_init(&worker->entry); |
1303 | worker_set_flags(worker, WORKER_DIE, false); | 1312 | worker->flags |= WORKER_DIE; |
1304 | 1313 | ||
1305 | spin_unlock_irq(&gcwq->lock); | 1314 | spin_unlock_irq(&gcwq->lock); |
1306 | 1315 | ||
@@ -2979,10 +2988,10 @@ static int __cpuinit trustee_thread(void *__gcwq) | |||
2979 | gcwq->flags |= GCWQ_MANAGING_WORKERS; | 2988 | gcwq->flags |= GCWQ_MANAGING_WORKERS; |
2980 | 2989 | ||
2981 | list_for_each_entry(worker, &gcwq->idle_list, entry) | 2990 | list_for_each_entry(worker, &gcwq->idle_list, entry) |
2982 | worker_set_flags(worker, WORKER_ROGUE, false); | 2991 | worker->flags |= WORKER_ROGUE; |
2983 | 2992 | ||
2984 | for_each_busy_worker(worker, i, pos, gcwq) | 2993 | for_each_busy_worker(worker, i, pos, gcwq) |
2985 | worker_set_flags(worker, WORKER_ROGUE, false); | 2994 | worker->flags |= WORKER_ROGUE; |
2986 | 2995 | ||
2987 | /* | 2996 | /* |
2988 | * Call schedule() so that we cross rq->lock and thus can | 2997 | * Call schedule() so that we cross rq->lock and thus can |
@@ -2995,12 +3004,12 @@ static int __cpuinit trustee_thread(void *__gcwq) | |||
2995 | spin_lock_irq(&gcwq->lock); | 3004 | spin_lock_irq(&gcwq->lock); |
2996 | 3005 | ||
2997 | /* | 3006 | /* |
2998 | * Sched callbacks are disabled now. gcwq->nr_running should | 3007 | * Sched callbacks are disabled now. Zap nr_running. After |
2999 | * be zero and will stay that way, making need_more_worker() | 3008 | * this, nr_running stays zero and need_more_worker() and |
3000 | * and keep_working() always return true as long as the | 3009 | * keep_working() are always true as long as the worklist is |
3001 | * worklist is not empty. | 3010 | * not empty. |
3002 | */ | 3011 | */ |
3003 | WARN_ON_ONCE(atomic_read(get_gcwq_nr_running(gcwq->cpu)) != 0); | 3012 | atomic_set(get_gcwq_nr_running(gcwq->cpu), 0); |
3004 | 3013 | ||
3005 | spin_unlock_irq(&gcwq->lock); | 3014 | spin_unlock_irq(&gcwq->lock); |
3006 | del_timer_sync(&gcwq->idle_timer); | 3015 | del_timer_sync(&gcwq->idle_timer); |
@@ -3046,7 +3055,7 @@ static int __cpuinit trustee_thread(void *__gcwq) | |||
3046 | worker = create_worker(gcwq, false); | 3055 | worker = create_worker(gcwq, false); |
3047 | spin_lock_irq(&gcwq->lock); | 3056 | spin_lock_irq(&gcwq->lock); |
3048 | if (worker) { | 3057 | if (worker) { |
3049 | worker_set_flags(worker, WORKER_ROGUE, false); | 3058 | worker->flags |= WORKER_ROGUE; |
3050 | start_worker(worker); | 3059 | start_worker(worker); |
3051 | } | 3060 | } |
3052 | } | 3061 | } |
@@ -3085,8 +3094,8 @@ static int __cpuinit trustee_thread(void *__gcwq) | |||
3085 | * operations. Use a separate flag to mark that | 3094 | * operations. Use a separate flag to mark that |
3086 | * rebinding is scheduled. | 3095 | * rebinding is scheduled. |
3087 | */ | 3096 | */ |
3088 | worker_set_flags(worker, WORKER_REBIND, false); | 3097 | worker->flags |= WORKER_REBIND; |
3089 | worker_clr_flags(worker, WORKER_ROGUE); | 3098 | worker->flags &= ~WORKER_ROGUE; |
3090 | 3099 | ||
3091 | /* queue rebind_work, wq doesn't matter, use the default one */ | 3100 | /* queue rebind_work, wq doesn't matter, use the default one */ |
3092 | if (test_and_set_bit(WORK_STRUCT_PENDING_BIT, | 3101 | if (test_and_set_bit(WORK_STRUCT_PENDING_BIT, |