da_mon->curr_state = model_get_initial_state_##name();                                  \
 }                                                                                              \
                                                                                                \
-/*                                                                                             \
- * da_monitor_curr_state_##name - return the current state                                     \
- */                                                                                            \
-static inline type da_monitor_curr_state_##name(struct da_monitor *da_mon)                     \
-{                                                                                              \
-       return da_mon->curr_state;                                                              \
-}                                                                                              \
-                                                                                               \
-/*                                                                                             \
- * da_monitor_set_state_##name - set the new current state                                     \
- */                                                                                            \
-static inline void                                                                             \
-da_monitor_set_state_##name(struct da_monitor *da_mon, enum states_##name state)               \
-{                                                                                              \
-       da_mon->curr_state = state;                                                             \
-}                                                                                              \
-                                                                                               \
 /*                                                                                             \
  * da_monitor_start_##name - start monitoring                                                  \
  *                                                                                             \
  * Event handler for implicit monitors. Implicit monitor is the one which the
  * handler does not need to specify which da_monitor to manipulate. Examples
  * of implicit monitor are the per_cpu or the global ones.
+ *
+ * Retry in case there is a race between getting and setting the next state,
+ * warn and reset the monitor if it runs out of retries. The monitor should be
+ * able to handle various orders.
  */
 #define DECLARE_DA_MON_MODEL_HANDLER_IMPLICIT(name, type)                                      \
                                                                                                \
 static inline bool                                                                             \
 da_event_##name(struct da_monitor *da_mon, enum events_##name event)                           \
 {                                                                                              \
-       type curr_state = da_monitor_curr_state_##name(da_mon);                                 \
-       type next_state = model_get_next_state_##name(curr_state, event);                       \
-                                                                                               \
-       if (next_state != INVALID_STATE) {                                                      \
-               da_monitor_set_state_##name(da_mon, next_state);                                \
-                                                                                               \
-               trace_event_##name(model_get_state_name_##name(curr_state),                     \
-                                  model_get_event_name_##name(event),                          \
-                                  model_get_state_name_##name(next_state),                     \
-                                  model_is_final_state_##name(next_state));                    \
-                                                                                               \
-               return true;                                                                    \
+       enum states_##name curr_state, next_state;                                              \
+                                                                                               \
+       curr_state = READ_ONCE(da_mon->curr_state);                                             \
+       for (int i = 0; i < MAX_DA_RETRY_RACING_EVENTS; i++) {                                  \
+               next_state = model_get_next_state_##name(curr_state, event);                    \
+               if (next_state == INVALID_STATE) {                                              \
+                       cond_react_##name(curr_state, event);                                   \
+                       trace_error_##name(model_get_state_name_##name(curr_state),             \
+                                          model_get_event_name_##name(event));                 \
+                       return false;                                                           \
+               }                                                                               \
+               if (likely(try_cmpxchg(&da_mon->curr_state, &curr_state, next_state))) {        \
+                       trace_event_##name(model_get_state_name_##name(curr_state),             \
+                                          model_get_event_name_##name(event),                  \
+                                          model_get_state_name_##name(next_state),             \
+                                          model_is_final_state_##name(next_state));            \
+                       return true;                                                            \
+               }                                                                               \
        }                                                                                       \
                                                                                                \
-       cond_react_##name(curr_state, event);                                                   \
-                                                                                               \
-       trace_error_##name(model_get_state_name_##name(curr_state),                             \
-                          model_get_event_name_##name(event));                                 \
-                                                                                               \
+       trace_rv_retries_error(#name, model_get_event_name_##name(event));                      \
+       pr_warn("rv: " __stringify(MAX_DA_RETRY_RACING_EVENTS)                                  \
+               " retries reached for event %s, resetting monitor %s",                          \
+               model_get_event_name_##name(event), #name);                                     \
        return false;                                                                           \
 }                                                                                              \
 
 /*
  * Event handler for per_task monitors.
+ *
+ * Retry in case there is a race between getting and setting the next state,
+ * warn and reset the monitor if it runs out of retries. The monitor should be
+ * able to handle various orders.
  */
 #define DECLARE_DA_MON_MODEL_HANDLER_PER_TASK(name, type)                                      \
                                                                                                \
 static inline bool da_event_##name(struct da_monitor *da_mon, struct task_struct *tsk,         \
                                   enum events_##name event)                                    \
 {                                                                                              \
-       type curr_state = da_monitor_curr_state_##name(da_mon);                                 \
-       type next_state = model_get_next_state_##name(curr_state, event);                       \
-                                                                                               \
-       if (next_state != INVALID_STATE) {                                                      \
-               da_monitor_set_state_##name(da_mon, next_state);                                \
-                                                                                               \
-               trace_event_##name(tsk->pid,                                                    \
-                                  model_get_state_name_##name(curr_state),                     \
-                                  model_get_event_name_##name(event),                          \
-                                  model_get_state_name_##name(next_state),                     \
-                                  model_is_final_state_##name(next_state));                    \
-                                                                                               \
-               return true;                                                                    \
+       enum states_##name curr_state, next_state;                                              \
+                                                                                               \
+       curr_state = READ_ONCE(da_mon->curr_state);                                             \
+       for (int i = 0; i < MAX_DA_RETRY_RACING_EVENTS; i++) {                                  \
+               next_state = model_get_next_state_##name(curr_state, event);                    \
+               if (next_state == INVALID_STATE) {                                              \
+                       cond_react_##name(curr_state, event);                                   \
+                       trace_error_##name(tsk->pid,                                            \
+                                          model_get_state_name_##name(curr_state),             \
+                                          model_get_event_name_##name(event));                 \
+                       return false;                                                           \
+               }                                                                               \
+               if (likely(try_cmpxchg(&da_mon->curr_state, &curr_state, next_state))) {        \
+                       trace_event_##name(tsk->pid,                                            \
+                                          model_get_state_name_##name(curr_state),             \
+                                          model_get_event_name_##name(event),                  \
+                                          model_get_state_name_##name(next_state),             \
+                                          model_is_final_state_##name(next_state));            \
+                       return true;                                                            \
+               }                                                                               \
        }                                                                                       \
                                                                                                \
-       cond_react_##name(curr_state, event);                                                   \
-                                                                                               \
-       trace_error_##name(tsk->pid,                                                            \
-                          model_get_state_name_##name(curr_state),                             \
-                          model_get_event_name_##name(event));                                 \
-                                                                                               \
+       trace_rv_retries_error(#name, model_get_event_name_##name(event));                      \
+       pr_warn("rv: " __stringify(MAX_DA_RETRY_RACING_EVENTS)                                  \
+               " retries reached for event %s, resetting monitor %s",                          \
+               model_get_event_name_##name(event), #name);                                     \
        return false;                                                                           \
 }