>  static bool ha_mon_initializing;
> +static bool ha_mon_destroying;
>  
>  static int ha_monitor_init(void)
>  {
>       int ret;
>  
> +     WRITE_ONCE(ha_mon_destroying, false);
>       ha_mon_initializing = true;
>       ret = da_monitor_init();
>       if (ret == 0)
> @@ -152,6 +155,7 @@ static int ha_monitor_init(void)
>  
>  static void ha_monitor_destroy(void)
>  {
> +     WRITE_ONCE(ha_mon_destroying, true);
>       ha_monitor_disable_hook();
>       da_monitor_destroy();
>  }
> @@ -302,12 +306,30 @@ static bool ha_monitor_handle_constraint(struct 
> da_monitor *da_mon,
>       return false;
>  }
>  
> +/*
> + * __ha_monitor_timer_callback - generic callback representation
> + *
> + * This callback runs in an RCU read-side critical section to allow the
> + * destruction sequence to easily synchronize_rcu() with all pending timers
> + * after asynchronously disabling them. The ha_mon_destroying check ensures
> + * any callback entering the RCU section after synchronize_rcu() completes
> + * will see the flag and bail out immediately.
> + */
>  static inline void __ha_monitor_timer_callback(struct ha_monitor *ha_mon)
>  {
> -     enum states curr_state = READ_ONCE(ha_mon->da_mon.curr_state);
>       DECLARE_SEQ_BUF(env_string, ENV_BUFFER_SIZE);
> -     u64 time_ns = ha_get_ns();
> -
> +     enum states curr_state;
> +     u64 time_ns;
> +
> +     guard(rcu)();
> +     if (unlikely(READ_ONCE(ha_mon_destroying)))

Instead of this global variable, can we instead use da_mon->monitoring?

> +             return;
> +     /* Ensure consistent curr_state if we race with da_monitor_reset */
> +     curr_state = smp_load_acquire(&ha_mon->da_mon.curr_state);
> +     if (unlikely(!da_monitor_handling_event(&ha_mon->da_mon)))
> +             return;
> +
> +     time_ns = ha_get_ns();
>       ha_get_env_string(&env_string, ha_mon, time_ns);
>       ha_react(curr_state, EVENT_NONE, env_string.buffer);
>       ha_trace_error_env(ha_mon, model_get_state_name(curr_state),
> -- 
> 2.54.0

Reply via email to