drivers/base/power/wakeup.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-)
From: Jaidev Shastri <jaidevshastri@vt.edu>
pm_save_wakeup_count() stores saved_count and then events_check_enabled
under events_lock. wakeup_source_report_event() reads
events_check_enabled without the lock and counts the event.
Store the flag with smp_store_release() and read it with
smp_load_acquire(), so that the stores a reader may rely on after
observing the flag are stated by the code.
Found with MBCheck, a static herd7-based memory consistency checker.
Signed-off-by: Jaidev Shastri <jaidevshastri@vt.edu>
---
drivers/base/power/wakeup.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c
index 80b497de2..afc9fafaf 100644
--- a/drivers/base/power/wakeup.c
+++ b/drivers/base/power/wakeup.c
@@ -578,8 +578,11 @@ static void wakeup_source_activate(struct wakeup_source *ws)
static void wakeup_source_report_event(struct wakeup_source *ws, bool hard)
{
ws->event_count++;
- /* This is racy, but the counter is approximate anyway. */
- if (events_check_enabled)
+ /*
+ * This is racy, but the counter is approximate anyway. The acquire
+ * pairs with the release in pm_save_wakeup_count().
+ */
+ if (smp_load_acquire(&events_check_enabled))
ws->wakeup_count++;
if (!ws->active)
@@ -1003,7 +1006,8 @@ bool pm_save_wakeup_count(unsigned int count)
split_counters(&cnt, &inpr);
if (cnt == count && inpr == 0) {
saved_count = count;
- events_check_enabled = true;
+ /* Pairs with the smp_load_acquire() in wakeup_source_report_event(). */
+ smp_store_release(&events_check_enabled, true);
}
raw_spin_unlock_irqrestore(&events_lock, flags);
return events_check_enabled;
---
base-commit: 93f51579e7df248780214094418f205253383cc5
change-id: 20260921-mb-pm-wakeup-6bc4f1592414
Best regards,
--
Jaidev Shastri <jaidevshastri@vt.edu>
On Tue, Sep 22, 2026 at 3:25 AM Jaidev Shastri via B4 Relay
<devnull+jaidevshastri.vt.edu@kernel.org> wrote:
>
> From: Jaidev Shastri <jaidevshastri@vt.edu>
>
> pm_save_wakeup_count() stores saved_count and then events_check_enabled
> under events_lock. wakeup_source_report_event() reads
> events_check_enabled without the lock and counts the event.
>
> Store the flag with smp_store_release() and read it with
> smp_load_acquire(), so that the stores a reader may rely on after
> observing the flag are stated by the code.
And how exactly does this help?
> Found with MBCheck, a static herd7-based memory consistency checker.
>
> Signed-off-by: Jaidev Shastri <jaidevshastri@vt.edu>
> ---
> drivers/base/power/wakeup.c | 10 +++++++---
> 1 file changed, 7 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c
> index 80b497de2..afc9fafaf 100644
> --- a/drivers/base/power/wakeup.c
> +++ b/drivers/base/power/wakeup.c
> @@ -578,8 +578,11 @@ static void wakeup_source_activate(struct wakeup_source *ws)
> static void wakeup_source_report_event(struct wakeup_source *ws, bool hard)
> {
> ws->event_count++;
> - /* This is racy, but the counter is approximate anyway. */
> - if (events_check_enabled)
> + /*
> + * This is racy, but the counter is approximate anyway. The acquire
> + * pairs with the release in pm_save_wakeup_count().
> + */
> + if (smp_load_acquire(&events_check_enabled))
> ws->wakeup_count++;
>
> if (!ws->active)
> @@ -1003,7 +1006,8 @@ bool pm_save_wakeup_count(unsigned int count)
> split_counters(&cnt, &inpr);
> if (cnt == count && inpr == 0) {
> saved_count = count;
> - events_check_enabled = true;
> + /* Pairs with the smp_load_acquire() in wakeup_source_report_event(). */
> + smp_store_release(&events_check_enabled, true);
> }
> raw_spin_unlock_irqrestore(&events_lock, flags);
> return events_check_enabled;
>
> ---
> base-commit: 93f51579e7df248780214094418f205253383cc5
> change-id: 20260921-mb-pm-wakeup-6bc4f1592414
>
> Best regards,
> --
> Jaidev Shastri <jaidevshastri@vt.edu>
>
>
© 2016 - 2026 Red Hat, Inc.