int __read_mostly nmi_watchdog_available;
struct cpumask watchdog_allowed_mask __read_mostly;
-static bool softlockup_threads_initialized __read_mostly;
struct cpumask watchdog_cpumask __read_mostly;
unsigned long *watchdog_cpumask_bits = cpumask_bits(&watchdog_cpumask);
}
/**
- * watchdog_nmi_reconfigure - Optional function to reconfigure NMI watchdogs
- * @run: If false stop the watchdogs on all enabled CPUs
- * If true start the watchdogs on all enabled CPUs
+ * watchdog_nmi_stop - Stop the watchdog for reconfiguration
*
- * The core call order is:
- * watchdog_nmi_reconfigure(false);
+ * The reconfiguration steps are:
+ * watchdog_nmi_stop();
* update_variables();
- * watchdog_nmi_reconfigure(true);
+ * watchdog_nmi_start();
+ */
+void __weak watchdog_nmi_stop(void) { }
+
+/**
+ * watchdog_nmi_start - Start the watchdog after reconfiguration
*
- * The second call which starts the watchdogs again guarantees that the
- * following variables are stable across the call.
+ * Counterpart to watchdog_nmi_stop().
+ *
+ * The following variables have been updated in update_variables() and
+ * contain the currently valid configuration:
* - watchdog_enabled
* - watchdog_thresh
* - watchdog_cpumask
- *
- * After the call the variables can be changed again.
*/
-void __weak watchdog_nmi_reconfigure(bool run) { }
+void __weak watchdog_nmi_start(void) { }
/**
* lockup_detector_update_enable - Update the sysctl enable bit
unsigned int __read_mostly softlockup_panic =
CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE;
+static bool softlockup_threads_initialized __read_mostly;
static u64 __read_mostly sample_period;
static DEFINE_PER_CPU(unsigned long, watchdog_touch_ts);
smpboot_update_cpumask_percpu_thread(&watchdog_threads,
&watchdog_allowed_mask);
- __lockup_detector_cleanup();
}
/* Temporarily park all watchdog threads */
softlockup_update_smpboot_threads();
}
-static void softlockup_reconfigure_threads(void)
+static void lockup_detector_reconfigure(void)
{
- watchdog_nmi_reconfigure(false);
+ cpus_read_lock();
+ watchdog_nmi_stop();
softlockup_park_all_threads();
set_sample_period();
lockup_detector_update_enable();
if (watchdog_enabled && watchdog_thresh)
softlockup_unpark_threads();
- watchdog_nmi_reconfigure(true);
+ watchdog_nmi_start();
+ cpus_read_unlock();
+ /*
+ * Must be called outside the cpus locked section to prevent
+ * recursive locking in the perf code.
+ */
+ __lockup_detector_cleanup();
}
/*
- * Create the watchdog thread infrastructure.
+ * Create the watchdog thread infrastructure and configure the detector(s).
*
* The threads are not unparked as watchdog_allowed_mask is empty. When
* the threads are sucessfully initialized, take the proper locks and
* unpark the threads in the watchdog_cpumask if the watchdog is enabled.
*/
-static __init void softlockup_init_threads(void)
+static __init void lockup_detector_setup(void)
{
int ret;
mutex_lock(&watchdog_mutex);
softlockup_threads_initialized = true;
- softlockup_reconfigure_threads();
+ lockup_detector_reconfigure();
mutex_unlock(&watchdog_mutex);
}
static inline void watchdog_unpark_threads(void) { }
static inline int watchdog_enable_all_cpus(void) { return 0; }
static inline void watchdog_disable_all_cpus(void) { }
-static inline void softlockup_init_threads(void) { }
-static void softlockup_reconfigure_threads(void)
+static void lockup_detector_reconfigure(void)
{
- watchdog_nmi_reconfigure(false);
+ cpus_read_lock();
+ watchdog_nmi_stop();
lockup_detector_update_enable();
- watchdog_nmi_reconfigure(true);
+ watchdog_nmi_start();
+ cpus_read_unlock();
+}
+static inline void lockup_detector_setup(void)
+{
+ lockup_detector_reconfigure();
}
#endif /* !CONFIG_SOFTLOCKUP_DETECTOR */
{
/* Remove impossible cpus to keep sysctl output clean. */
cpumask_and(&watchdog_cpumask, &watchdog_cpumask, cpu_possible_mask);
- softlockup_reconfigure_threads();
+ lockup_detector_reconfigure();
}
/*
if (!watchdog_nmi_probe())
nmi_watchdog_available = true;
- softlockup_init_threads();
+ lockup_detector_setup();
}