return alarm_try_to_cancel(&timr->it.alarm.alarmtimer);
 }
 
+/**
+ * alarm_timer_wait_running - Posix timer callback to wait for a timer
+ * @timr:      Pointer to the posixtimer data struct
+ *
+ * Called from the core code when timer cancel detected that the callback
+ * is running. @timr is unlocked and rcu read lock is held to prevent it
+ * from being freed.
+ */
+static void alarm_timer_wait_running(struct k_itimer *timr)
+{
+       hrtimer_cancel_wait_running(&timr->it.alarm.alarmtimer.timer);
+}
+
 /**
  * alarm_timer_arm - Posix timer callback to arm a timer
  * @timr:      Pointer to the posixtimer data struct
        .timer_forward          = alarm_timer_forward,
        .timer_remaining        = alarm_timer_remaining,
        .timer_try_to_cancel    = alarm_timer_try_to_cancel,
+       .timer_wait_running     = alarm_timer_wait_running,
        .nsleep                 = alarm_timer_nsleep,
 };
 #endif /* CONFIG_POSIX_TIMERS */
 
        return hrtimer_try_to_cancel(&timr->it.real.timer);
 }
 
+static void common_timer_wait_running(struct k_itimer *timer)
+{
+       hrtimer_cancel_wait_running(&timer->it.real.timer);
+}
+
 static struct k_itimer *timer_wait_running(struct k_itimer *timer,
                                           unsigned long *flags)
 {
+       const struct k_clock *kc = READ_ONCE(timer->kclock);
        timer_t timer_id = READ_ONCE(timer->it_id);
 
+       /* Prevent kfree(timer) after dropping the lock */
+       rcu_read_lock();
        unlock_timer(timer, *flags);
-       cpu_relax();
+
+       if (!WARN_ON_ONCE(!kc->timer_wait_running))
+               kc->timer_wait_running(timer);
+
+       rcu_read_unlock();
        /* Relock the timer. It might be not longer hashed. */
        return lock_timer(timer_id, flags);
 }
        .timer_forward          = common_hrtimer_forward,
        .timer_remaining        = common_hrtimer_remaining,
        .timer_try_to_cancel    = common_hrtimer_try_to_cancel,
+       .timer_wait_running     = common_timer_wait_running,
        .timer_arm              = common_hrtimer_arm,
 };
 
        .timer_forward          = common_hrtimer_forward,
        .timer_remaining        = common_hrtimer_remaining,
        .timer_try_to_cancel    = common_hrtimer_try_to_cancel,
+       .timer_wait_running     = common_timer_wait_running,
        .timer_arm              = common_hrtimer_arm,
 };
 
        .timer_forward          = common_hrtimer_forward,
        .timer_remaining        = common_hrtimer_remaining,
        .timer_try_to_cancel    = common_hrtimer_try_to_cancel,
+       .timer_wait_running     = common_timer_wait_running,
        .timer_arm              = common_hrtimer_arm,
 };
 
        .timer_forward          = common_hrtimer_forward,
        .timer_remaining        = common_hrtimer_remaining,
        .timer_try_to_cancel    = common_hrtimer_try_to_cancel,
+       .timer_wait_running     = common_timer_wait_running,
        .timer_arm              = common_hrtimer_arm,
 };