|
@@ -1396,12 +1396,15 @@ retry:
|
|
|
/* set REBIND and kick idle ones, we'll wait for these later */
|
|
|
for_each_worker_pool(pool, gcwq) {
|
|
|
list_for_each_entry(worker, &pool->idle_list, entry) {
|
|
|
+ unsigned long worker_flags = worker->flags;
|
|
|
+
|
|
|
if (worker->flags & WORKER_REBIND)
|
|
|
continue;
|
|
|
|
|
|
- /* morph UNBOUND to REBIND */
|
|
|
- worker->flags &= ~WORKER_UNBOUND;
|
|
|
- worker->flags |= WORKER_REBIND;
|
|
|
+ /* morph UNBOUND to REBIND atomically */
|
|
|
+ worker_flags &= ~WORKER_UNBOUND;
|
|
|
+ worker_flags |= WORKER_REBIND;
|
|
|
+ ACCESS_ONCE(worker->flags) = worker_flags;
|
|
|
|
|
|
idle_rebind.cnt++;
|
|
|
worker->idle_rebind = &idle_rebind;
|
|
@@ -1434,10 +1437,12 @@ retry:
|
|
|
/* rebind busy workers */
|
|
|
for_each_busy_worker(worker, i, pos, gcwq) {
|
|
|
struct work_struct *rebind_work = &worker->rebind_work;
|
|
|
+ unsigned long worker_flags = worker->flags;
|
|
|
|
|
|
- /* morph UNBOUND to REBIND */
|
|
|
- worker->flags &= ~WORKER_UNBOUND;
|
|
|
- worker->flags |= WORKER_REBIND;
|
|
|
+ /* morph UNBOUND to REBIND atomically */
|
|
|
+ worker_flags &= ~WORKER_UNBOUND;
|
|
|
+ worker_flags |= WORKER_REBIND;
|
|
|
+ ACCESS_ONCE(worker->flags) = worker_flags;
|
|
|
|
|
|
if (test_and_set_bit(WORK_STRUCT_PENDING_BIT,
|
|
|
work_data_bits(rebind_work)))
|