Skip to content

Commit d3a96bc

Browse files
committed
sched: Add documentation for HRTimer.
This commit added documentation for HRTimer. Signed-off-by: ouyangxiangzhen <ouyangxiangzhen@xiaomi.com>
1 parent 3646b80 commit d3a96bc

File tree

1 file changed

+226
-60
lines changed

1 file changed

+226
-60
lines changed

Documentation/reference/os/time_clock.rst

Lines changed: 226 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -665,87 +665,253 @@ require nanosecond-level task timing, which tick-based timers
665665
like wdog cannot provide. Reducing the tick interval to micro-
666666
or nanoseconds is impractical, as it would overload the CPU with interrupts.
667667
668-
To address this, NuttX provides a high-resolution timer (hrtimer),
669-
which delivers true nanosecond-level precision. Unlike wdog’s list-based timers,
670-
hrtimer uses a red-black tree for efficient management of large numbers of timers,
671-
an important advantage in hard real-time systems like vehicle control.
672-
673-
A user can register an hrtimer callback to execute after a specified delay.
674-
The callback runs in the timer interrupt context, so only limited NuttX interfaces
675-
are available, such as ``mq_send()``, ``sigqueue()``, ``nxevent_post()``, or ``kill()``,
676-
to communicate with tasks.
677-
678-
- :c:func:`hrtimer_init`
679-
- :c:func:`hrtimer_cancel`
680-
- :c:func:`hrtimer_cancel_sync`
681-
- :c:func:`hrtimer_start`
682-
- High-resolution Timer Callback
683-
684-
.. c:function:: void hrtimer_init(FAR hrtimer_t *hrtimer, hrtentry_t func, \
685-
FAR void *arg)
686-
687-
This function initializes a high-resolution timer instance.
688-
Sets the expiration callback and its argument. The timer is
689-
not started by this function.
690-
691-
:param hrtimer: Pointer to hrtimer instance
668+
High-resolution Timer (HRTimer) is a timer abstraction capable of achieving
669+
nanosecond-level timing resolution, primarily used in scenarios requiring
670+
high-resolution clock events. With the advancement of integrated circuit
671+
technology, modern high-resolution timer hardware, such as the typical x86
672+
HPET, can already meet sub-nanosecond timing requirements and offer
673+
femtosecond-level jitter control.
674+
675+
Although the current hardware timer abstraction (`up_alarm/up_timer`)
676+
in the NuttX kernel already supports nanosecond-level timing, its software
677+
timer abstraction, wdog, and the timer timeout interrupt handling process
678+
remain at microsecond-level (tick) resolution, which falls short of
679+
high-resolution timing demands. Therefore, it is necessary to implement a
680+
new timer abstraction, HRTimer, to address the resolution limitations of
681+
wdog. HRTimer primarily provides the following functional interfaces:
682+
683+
**Set a timer in nanoseconds**: Configure a software timer to trigger at
684+
a specified nanosecond time.
685+
686+
**Cancel a timer**: Cancel the software timer.
687+
688+
**Handle timer timeout**: Execute timeout processing after the timer event
689+
is triggered.
690+
691+
The new NuttX HRTimer is designed to address the issues of insufficient
692+
resolution in the current NuttX wdog. It draws on the strengths of the Linux
693+
HRTimer design while improving upon its weaknesses.
694+
The HRTimer design is divided into two parts: the `HRTimer Queue` and the
695+
`HRTimer`. The `HRTimer Queue` is a reusable component that allows users to
696+
freely customize their own `HRTimer` interface by pairing it with a private
697+
timer driver, without needing to modify the kernel code.
698+
699+
The HRTimer Queue is a zero-performance-overhead, composable, and
700+
customizable abstraction that provides only asynchronous-style interfaces:
701+
702+
**hrtimer_queue_start(queue, timer)**: Asynchronously sends an HRTimer to
703+
HRTimer queue.
704+
705+
**hrtimer_queue_async_cancel(queue, timer)**:
706+
Asynchronously cancels anHRTimer and returns the current reference count
707+
of the timer.
708+
709+
**hrtimer_queue_wait(queue, timer)**:
710+
Waits for the release of all references to the HRTimer to obtain ownership
711+
of the HRTimer data structure.
712+
713+
All other user interfaces can be composed based on these three interfaces.
714+
715+
On top of the `HRTimer Queue`, users only need to implement the following
716+
interfaces to customize their own HRTimer implementation:
717+
718+
**hrtimer_expiry(current)**: Handles timer expiration, typically called
719+
within the execution path of the corresponding timer hardware
720+
interrupt handler.
721+
722+
**hrtimer_reprogram(queue, next_expired)**: Sets the next timer event.
723+
724+
**hrtimer_wait_policy()**: Waits if the timer callback is still executing.
725+
726+
**hrtimer_current()**: Gets the current time to set relative timers.
727+
728+
After implementing the above three interfaces, users can include one of the
729+
`hrtimer_type_xxx.h` implementation to compose their own hrtimer
730+
implementation, which mainly includes the following interfaces:
731+
732+
**hrtimer_start(timer, func, arg, delay)**: Starts a timer.
733+
734+
**hrtimer_restart(timer, func, arg, delay)**: Restarts a timer that has
735+
been asynchronously canceled (its callback function might still be executing).
736+
This interface is designed to explicitly remind users to be aware of
737+
concurrency issues,as concurrency problems are prone to occur in actual
738+
programming and are very difficult to locate. Providing such an interface
739+
facilitates quick identification of concurrency issues.
740+
741+
**hrtimer_cancel(timer)**: Asynchronously cancels a timer. Note that
742+
the semantics of this interface are completely different from Linux's
743+
`try_to_cancel`. It ensures that the timer can definitely be canceled
744+
successfully, but may need to wait for its callback function to finish
745+
execution.
746+
747+
**hrtimer_cancel_sync(timer)**: Synchronously cancels a timer. If the timer's
748+
callback function is still executing, this function will spin-wait until
749+
the callback completes. It ensures that the user can always obtain
750+
ownership of the timer.
751+
752+
The state-machine diagram of the HRTimer is as follows:
753+
754+
.. code-block:: text
755+
756+
+------------------------------------------------------+
757+
| HRTIMER State Diagram |
758+
+------------------------------------------------------+
759+
| |
760+
| +----------------------+ |
761+
| | HRTIMER_COMPLETED | |
762+
| | (private) | |
763+
| +----------------------+ |
764+
| | |
765+
| | hrtimer_start |
766+
| | |
767+
| | |
768+
| v |
769+
| +----------------------+ |
770+
| | HRTIMER_PENDING |---------------------+ |
771+
| +-->| (shared) |<---+ | |
772+
| | +----------------------+ | | |
773+
| | | |timer callback | |
774+
| | |hrtimer_expiry |return non-zero | |
775+
| | | | | |
776+
| | v | | |
777+
| | +----------------------+ | | |
778+
| | | HRTIMER_RUNNING |----+ | |
779+
| | | (shared) | | |
780+
| | +----------------------+ | |
781+
| | | | |
782+
| | | | |
783+
| | |timer return zero | |
784+
| | |or | |
785+
| | |hrtimer_cancel | |
786+
| | | | |
787+
| | v | |
788+
| | +----------------------+ | |
789+
| | | HRTIMER_CANCELED |<--------+ |
790+
| +---------------| (half_shared) | |
791+
|hrtimer_restart +----------------------+ |
792+
| | |
793+
| hrtimer_cancel_sync| |
794+
| wait all cores | |
795+
| v |
796+
| +----------------------+ |
797+
| | HRTIMER_COMPLETED | |
798+
| | (private) | |
799+
| +----------------------+ |
800+
| ^ | |
801+
| | | |
802+
| +--+ |
803+
| hrtimer_cancel |
804+
+------------------------------------------------------+
805+
806+
The specific definitions of the states are as follows:
807+
808+
**HRTIMER_PENDING|shared**: `hrtimer->func != NULL`. That is, the hrtimer has
809+
been inserted into the hrtimer_queue and is waiting to be executed.
810+
811+
**HRTIMER_COMPLETED|private**: `hrtimer->func == NULL` ∧
812+
`∀c ∈ [0, CONFIG_SMP_NCPUS), (hrtimer_queue->running[c] & ~(1u)) != hrtimer`
813+
That is, the hrtimer is not in a pending state, and no core is currently
814+
executing the hrtimer's callback function.
815+
816+
**HRTIMER_RUNNING|shared**: `hrtimer->func == NULL` ∧
817+
`∃c ∈ [0, CONFIG_SMP_NCPUS), hrtimer_queue->running[c] == hrtimer`.
818+
That is, the hrtimer is not in a pending state, and there exists at least one
819+
core that is currently executing the hrtimer’s callback function.
820+
821+
**HRTIMER_CANCELED|half_shared**: `hrtimer->func == NULL` ∧
822+
`∀c ∈ [0, CONFIG_SMP_NCPUS), hrtimer_queue->running[c] != hrtimer`.
823+
That is, the hrtimer is not in a pending state, and all cores have lost
824+
ownership of the hrtimer—meaning they can no longer read from or write to the
825+
hrtimer—though its callback function may still be in the process of being
826+
executed.
827+
828+
.. c:function:: int hrtimer_restart(FAR hrtimer_t *timer, hrtimer_callback_t func, uint64_t time, uint32_t mode)
829+
830+
Restart a high-resolution timer with new parameters.
831+
832+
For relative mode timers, converts relative time to absolute expiration time.
833+
The expiration time is capped at HRTIMER_MAX_DELAY.
834+
835+
**Note:** This function is static inline and intended for internal use.
836+
837+
:param timer: Timer instance to start
692838
:param func: Expiration callback function
693-
:param arg: Callback argument
839+
:param time: Expiration time in nanoseconds (relative or absolute)
840+
:param mode: ``HRTIMER_MODE_ABS`` for absolute time,
841+
``!HRTIMER_MODE_ABS`` for relative time
694842
695-
:return: None.
843+
:return: Zero on success; error code on failure.
696844
697-
**POSIX Compatibility:** This is a NON-POSIX interface.
845+
**Assumptions:**
846+
- The caller has ownership of the timer.
698847
699-
.. c:function:: int hrtimer_cancel(FAR hrtimer_t *hrtimer)
848+
.. c:function:: int hrtimer_start(FAR hrtimer_t *timer, hrtimer_callback_t func, uint64_t time, uint32_t mode)
700849
701-
If the timer is armed but has not yet expired, it will be removed from
702-
the timer queue and the callback will not be invoked.
850+
Start a high-resolution timer with relative or absolute time in nanoseconds.
703851
704-
If the timer callback is currently executing, this function will mark
705-
the timer as canceled and return immediately. The running callback is
706-
allowed to complete, but it will not be invoked again.
852+
The caller must have ownership of the timer. This function validates parameters
853+
and timer state before attempting to start the timer.
707854
708-
This function is non-blocking and does not wait for a running callback
709-
to finish.
855+
:param timer: Timer instance to start
856+
:param func: Expiration callback function
857+
:param time: Expiration time in nanoseconds (relative or absolute)
858+
:param mode: ``HRTIMER_MODE_ABS`` for absolute time,
859+
``!HRTIMER_MODE_ABS`` for relative time
860+
861+
:return: Zero on success; ``-EINVAL`` if parameters are invalid or timer is pending.
862+
863+
**Assumptions:**
864+
- Timer is not NULL and callback function is not NULL.
865+
- Timer is not in pending state.
866+
867+
.. c:function:: int hrtimer_cancel(FAR hrtimer_t *timer)
868+
869+
Cancel a high-resolution timer asynchronously.
870+
871+
Sets the timer to cancelled state and returns immediately. The caller acquires
872+
limited ownership, allowing timer restart but not freeing. Callback may still
873+
be executing on another CPU. Use with caution to avoid concurrency issues.
874+
875+
:param timer: Timer instance to cancel
710876
711-
:param hrtimer: Timer instance to cancel
877+
:return: ``OK`` on success; ``>0`` if the timer is running.
712878
713-
:return: ``OK`` on success; negated errno on failure.
879+
**Assumptions:**
880+
- Timer is not NULL.
714881
715-
**POSIX Compatibility:** This is a NON-POSIX interface.
882+
.. c:function:: int hrtimer_cancel_sync(FAR hrtimer_t *timer)
716883
717-
.. c:function:: int hrtimer_cancel_sync(FAR hrtimer_t *hrtimer)
884+
Cancel a high-resolution timer and synchronously wait for callback completion.
718885
719-
Cancel a high-resolution timer and wait synchronously until the timer
720-
becomes inactive.
886+
Sets timer to cancelled state and waits for all references to be released.
887+
Caller acquires full ownership and can safely deallocate the timer after
888+
this function returns.
721889
722-
This function first calls hrtimer_cancel() to request cancellation of
723-
the timer. If the timer callback is currently executing, this function
724-
will wait until the callback has completed and the timer state has
725-
transitioned to HRTIMER_STATE_INACTIVE.
890+
:param timer: Timer instance to cancel
726891
727-
This function may sleep and must not be called from interrupt context.
892+
:return: ``OK`` on success.
728893
729-
:param hrtimer: Timer instance to cancel
894+
**Assumptions:**
895+
- Timer is not NULL.
730896
731-
:return: ``OK`` on success; negated errno on failure.
897+
.. c:function:: uint64_t hrtimer_gettime(FAR hrtimer_t *timer)
732898
733-
**POSIX Compatibility:** This is a NON-POSIX interface.
899+
Get the remaining time until timer expiration.
734900
735-
.. c:function:: int hrtimer_start(FAR hrtimer_t *hrtimer, uint64_t ns, \
736-
enum hrtimer_mode_e mode)
901+
:param timer: Timer instance to query
737902
738-
This function starts a high-resolution timer in absolute or relative mode.
903+
:return: Remaining time in nanoseconds until next expiration.
739904
740-
:param hrtimer: Timer instance to cancel
741-
:param ns: Timer expiration in nanoseconds (absolute or relative)
742-
:param mode: HRTIMER_MODE_ABS or HRTIMER_MODE_REL
905+
**Assumptions:**
906+
- Timer is not NULL.
743907
744-
:return: ``OK`` on success; negated errno on failure.
908+
.. c:type:: uint64_t (*hrtimer_callback_t)(FAR const struct hrtimer_s *timer, uint64_t expired)
745909
746-
**POSIX Compatibility:** This is a NON-POSIX interface.
910+
**High-resolution Timer Callback Type**: Function pointer type for timer
911+
expiration callbacks. When a hrtimer expires, a function of this type is called.
747912
748-
.. c:type:: void (*hrtentry_t)(FAR struct hrtimer_s *)
913+
:param timer: The hrtimer pointer passed to callback function,
914+
do not modify the hrtimer when executing callback function.
915+
:param expired: Time in nanoseconds when timer expired
749916
750-
**High-resolution Timer Callback**: when a hrtimer expires,
751-
the callback function with this type is called.
917+
:return: Next delay in nanoseconds until next expiration.

0 commit comments

Comments
 (0)