Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2be49b6f authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "kthread/smpboot: Serialize kthread parking against wakeup"

parents a2d277f6 e3ec2821
Loading
Loading
Loading
Loading
+38 −0
Original line number Original line Diff line number Diff line
@@ -121,7 +121,45 @@ static int smpboot_thread_fn(void *data)
		}
		}


		if (kthread_should_park()) {
		if (kthread_should_park()) {
			/*
			 * Serialize against wakeup. If we take the lock first,
			 * wakeup is skipped. If we run later, we observe,
			 * TASK_RUNNING update from wakeup path, before moving
			 * forward. This helps avoid the race, where wakeup
			 * observes TASK_INTERRUPTIBLE, and also observes
			 * the TASK_PARKED in kthread_parkme() before updating
			 * task state to TASK_RUNNING. In this case, kthread
			 * gets parked in TASK_RUNNING state. This results
			 * in panic later on in kthread_unpark(), as it sees
			 * KTHREAD_IS_PARKED flag set but fails to rebind the
			 * kthread, due to it being not in TASK_PARKED state.
			 *
			 * Control thread                      Hotplug Thread
			 *
			 * kthread_park()
			 *   set KTHREAD_SHOULD_PARK
			 *                                smpboot_thread_fn()
			 *                                  set_current_state(
			 *                                  TASK_INTERRUPTIBLE);
			 *                                  kthread_parkme()
			 *
			 *   wake_up_process()
			 *
			 * raw_spin_lock_irqsave(&p->pi_lock, flags);
			 * if (!(p->state & state))
			 *            goto out;
			 *
			 *                                  __set_current_state(
			 *                                  TASK_PARKED);
			 *
			 * if (p->on_rq && ttwu_remote(p, wake_flags))
			 *   ttwu_remote()
			 *     p->state = TASK_RUNNING;
			 *                                   schedule();
			 */
			raw_spin_lock(&current->pi_lock);
			__set_current_state(TASK_RUNNING);
			__set_current_state(TASK_RUNNING);
			raw_spin_unlock(&current->pi_lock);
			preempt_enable();
			preempt_enable();
			if (ht->park && td->status == HP_THREAD_ACTIVE) {
			if (ht->park && td->status == HP_THREAD_ACTIVE) {
				BUG_ON(td->cpu != smp_processor_id());
				BUG_ON(td->cpu != smp_processor_id());