Loading kernel/sched/core.c +17 −0 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ #include <linux/security.h> #include <linux/syscalls.h> #include <linux/irq.h> #include <linux/delay.h> #include <linux/kthread.h> Loading Loading @@ -5985,6 +5986,22 @@ int sched_isolate_cpu(int cpu) if (++cpu_isolation_vote[cpu] > 1) goto out; /* * There is a race between watchdog being enabled by hotplug and * core isolation disabling the watchdog. When a CPU is hotplugged in * and the hotplug lock has been released the watchdog thread might * not have run yet to enable the watchdog. * We have to wait for the watchdog to be enabled before proceeding. */ if (!watchdog_configured(cpu)) { msleep(20); if (!watchdog_configured(cpu)) { --cpu_isolation_vote[cpu]; ret_code = -EBUSY; goto out; } } set_cpu_isolated(cpu, true); cpumask_clear_cpu(cpu, &avail_cpus); Loading kernel/watchdog.c +20 −8 Original line number Diff line number Diff line Loading @@ -456,17 +456,13 @@ static void watchdog_set_prio(unsigned int policy, unsigned int prio) sched_setscheduler(current, policy, ¶m); } /* Must be called with hotplug lock (lock_device_hotplug()) held. */ void watchdog_enable(unsigned int cpu) { struct hrtimer *hrtimer = this_cpu_ptr(&watchdog_hrtimer); unsigned int *enabled = this_cpu_ptr(&watchdog_en); lock_device_hotplug_assert(); if (*enabled) return; *enabled = 1; /* * Start the timer first to prevent the NMI watchdog triggering Loading @@ -484,19 +480,24 @@ void watchdog_enable(unsigned int cpu) watchdog_nmi_enable(cpu); watchdog_set_prio(SCHED_FIFO, MAX_RT_PRIO - 1); /* * Need to ensure above operations are observed by other CPUs before * indicating that timer is enabled. This is to synchronize core * isolation and hotplug. Core isolation will wait for this flag to be * set. */ mb(); *enabled = 1; } /* Must be called with hotplug lock (lock_device_hotplug()) held. */ void watchdog_disable(unsigned int cpu) { struct hrtimer *hrtimer = this_cpu_ptr(&watchdog_hrtimer); unsigned int *enabled = this_cpu_ptr(&watchdog_en); lock_device_hotplug_assert(); if (!*enabled) return; *enabled = 0; watchdog_set_prio(SCHED_NORMAL, 0); /* Loading @@ -506,6 +507,17 @@ void watchdog_disable(unsigned int cpu) */ watchdog_nmi_disable(cpu); hrtimer_cancel(hrtimer); /* * No need for barrier here since disabling the watchdog is * synchronized with hotplug lock */ *enabled = 0; } bool watchdog_configured(unsigned int cpu) { return *per_cpu_ptr(&watchdog_en, cpu); } static void watchdog_cleanup(unsigned int cpu, bool online) Loading Loading
kernel/sched/core.c +17 −0 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ #include <linux/security.h> #include <linux/syscalls.h> #include <linux/irq.h> #include <linux/delay.h> #include <linux/kthread.h> Loading Loading @@ -5985,6 +5986,22 @@ int sched_isolate_cpu(int cpu) if (++cpu_isolation_vote[cpu] > 1) goto out; /* * There is a race between watchdog being enabled by hotplug and * core isolation disabling the watchdog. When a CPU is hotplugged in * and the hotplug lock has been released the watchdog thread might * not have run yet to enable the watchdog. * We have to wait for the watchdog to be enabled before proceeding. */ if (!watchdog_configured(cpu)) { msleep(20); if (!watchdog_configured(cpu)) { --cpu_isolation_vote[cpu]; ret_code = -EBUSY; goto out; } } set_cpu_isolated(cpu, true); cpumask_clear_cpu(cpu, &avail_cpus); Loading
kernel/watchdog.c +20 −8 Original line number Diff line number Diff line Loading @@ -456,17 +456,13 @@ static void watchdog_set_prio(unsigned int policy, unsigned int prio) sched_setscheduler(current, policy, ¶m); } /* Must be called with hotplug lock (lock_device_hotplug()) held. */ void watchdog_enable(unsigned int cpu) { struct hrtimer *hrtimer = this_cpu_ptr(&watchdog_hrtimer); unsigned int *enabled = this_cpu_ptr(&watchdog_en); lock_device_hotplug_assert(); if (*enabled) return; *enabled = 1; /* * Start the timer first to prevent the NMI watchdog triggering Loading @@ -484,19 +480,24 @@ void watchdog_enable(unsigned int cpu) watchdog_nmi_enable(cpu); watchdog_set_prio(SCHED_FIFO, MAX_RT_PRIO - 1); /* * Need to ensure above operations are observed by other CPUs before * indicating that timer is enabled. This is to synchronize core * isolation and hotplug. Core isolation will wait for this flag to be * set. */ mb(); *enabled = 1; } /* Must be called with hotplug lock (lock_device_hotplug()) held. */ void watchdog_disable(unsigned int cpu) { struct hrtimer *hrtimer = this_cpu_ptr(&watchdog_hrtimer); unsigned int *enabled = this_cpu_ptr(&watchdog_en); lock_device_hotplug_assert(); if (!*enabled) return; *enabled = 0; watchdog_set_prio(SCHED_NORMAL, 0); /* Loading @@ -506,6 +507,17 @@ void watchdog_disable(unsigned int cpu) */ watchdog_nmi_disable(cpu); hrtimer_cancel(hrtimer); /* * No need for barrier here since disabling the watchdog is * synchronized with hotplug lock */ *enabled = 0; } bool watchdog_configured(unsigned int cpu) { return *per_cpu_ptr(&watchdog_en, cpu); } static void watchdog_cleanup(unsigned int cpu, bool online) Loading