sched/hrtimer: add option for list-based hrtimer management

Add support for managing hrtimers using a simple list. This approach
  is more memory-efficient, as list nodes use less memory, and it is
  preferable to an RB-tree when the number of hrtimers is relatively small.

Signed-off-by: Chengdong Wang <wangchengdong@lixiang.com>
This commit is contained in:
wangchengdong
2026-01-19 18:34:03 +08:00
committed by Xiang Xiao
parent 3c1712c66d
commit 291938150f
4 changed files with 77 additions and 0 deletions
+5
View File
@@ -31,6 +31,7 @@
#include <nuttx/clock.h>
#include <nuttx/compiler.h>
#include <nuttx/spinlock.h>
#include <nuttx/list.h>
#include <stdint.h>
#include <sys/tree.h>
@@ -68,7 +69,11 @@ typedef CODE uint64_t (*hrtimer_entry_t)(FAR const struct hrtimer_s *hrtimer,
typedef struct hrtimer_node_s
{
#ifdef CONFIG_HRTIMER_TREE
RB_ENTRY(hrtimer_node_s) entry; /* RB-tree linkage */
#else
struct list_node entry; /* List linkage */
#endif
} hrtimer_node_t;
/* High-resolution timer object
+25
View File
@@ -2067,3 +2067,28 @@ config HRTIMER
default n
---help---
Enable to support high resolution timer
if HRTIMER
choice
prompt "HRTimer management data structure type"
default HRTIMER_TREE
config HRTIMER_LIST
bool "List-based timer management"
help
Use a simple list to manage timers. This method is
suitable for systems with a small number of timers.
It is more memory-efficient but may become slower
as the number of timers increases.
config HRTIMER_TREE
bool "RB-tree-based timer management"
help
Use a red-black tree to manage timers. This method
provides better performance for systems with many
timers, at the cost of slightly higher memory usage.
endchoice
endif # HRTIMER
+41
View File
@@ -44,7 +44,9 @@
* being the left-most (minimum) node in the tree.
*/
#ifdef CONFIG_HRTIMER_TREE
RB_HEAD(hrtimer_tree_s, hrtimer_node_s);
#endif
/****************************************************************************
* Public Data
@@ -54,9 +56,15 @@ RB_HEAD(hrtimer_tree_s, hrtimer_node_s);
extern spinlock_t g_hrtimer_spinlock;
#ifdef CONFIG_HRTIMER_TREE
/* Red-Black tree containing all active high-resolution timers */
extern struct hrtimer_tree_s g_hrtimer_tree;
#else
/* List containing all active high-resolution timers */
extern struct list_node g_hrtimer_list;
#endif
/* Array of pointers to currently running high-resolution timers
* for each CPU in SMP configurations. Index corresponds to CPU ID.
@@ -165,6 +173,7 @@ int hrtimer_starttimer(uint64_t ns)
* >=0 if a expires after b
****************************************************************************/
#ifdef CONFIG_HRTIMER_TREE
static inline_function
int hrtimer_compare(FAR const hrtimer_node_t *a,
FAR const hrtimer_node_t *b)
@@ -174,6 +183,7 @@ int hrtimer_compare(FAR const hrtimer_node_t *a,
return clock_compare(atimer->expired, btimer->expired) ? -1 : 1;
}
#endif
/****************************************************************************
* Red-Black Tree Prototype for high-resolution timers
@@ -184,7 +194,9 @@ int hrtimer_compare(FAR const hrtimer_node_t *a,
* operations based on timer expiration time.
****************************************************************************/
#ifdef CONFIG_HRTIMER_TREE
RB_PROTOTYPE(hrtimer_tree_s, hrtimer_node_s, entry, hrtimer_compare);
#endif
/****************************************************************************
* Name: hrtimer_is_armed
@@ -210,7 +222,11 @@ static inline_function bool hrtimer_is_armed(FAR hrtimer_t *hrtimer)
static inline_function void hrtimer_remove(FAR hrtimer_t *hrtimer)
{
#ifdef CONFIG_HRTIMER_TREE
RB_REMOVE(hrtimer_tree_s, &g_hrtimer_tree, &hrtimer->node);
#else
list_delete_fast(&hrtimer->node.entry);
#endif
/* Explicitly clear parent to mark the timer as unarmed */
@@ -226,7 +242,24 @@ static inline_function void hrtimer_remove(FAR hrtimer_t *hrtimer)
static inline_function void hrtimer_insert(FAR hrtimer_t *hrtimer)
{
#ifdef CONFIG_HRTIMER_TREE
RB_INSERT(hrtimer_tree_s, &g_hrtimer_tree, &hrtimer->node);
#else
FAR hrtimer_t *curr;
uint64_t expired = hrtimer->expired;
list_for_every_entry(&g_hrtimer_list, curr, hrtimer_t, node.entry)
{
/* Until curr->expired has not timed out relative to expired */
if (!clock_compare(curr->expired, expired))
{
break;
}
}
list_add_before(&curr->node.entry, &hrtimer->node.entry);
#endif
}
/****************************************************************************
@@ -241,7 +274,11 @@ static inline_function void hrtimer_insert(FAR hrtimer_t *hrtimer)
static inline_function FAR hrtimer_t *hrtimer_get_first(void)
{
#ifdef CONFIG_HRTIMER_TREE
return (FAR hrtimer_t *)RB_MIN(hrtimer_tree_s, &g_hrtimer_tree);
#else
return list_first_entry(&g_hrtimer_list, FAR hrtimer_t, node.entry);
#endif
}
/****************************************************************************
@@ -265,7 +302,11 @@ static inline_function FAR hrtimer_t *hrtimer_get_first(void)
static inline_function bool hrtimer_is_first(FAR hrtimer_t *hrtimer)
{
#ifdef CONFIG_HRTIMER_TREE
return RB_LEFT(&hrtimer->node, entry) == NULL;
#else
return hrtimer == list_first_entry(&g_hrtimer_list, hrtimer_t, node.entry);
#endif
}
#endif /* CONFIG_HRTIMER */
+6
View File
@@ -57,7 +57,11 @@ spinlock_t g_hrtimer_spinlock = SP_UNLOCKED;
* The tree is ordered by absolute expiration time.
*/
#ifdef CONFIG_HRTIMER_TREE
struct hrtimer_tree_s g_hrtimer_tree = RB_INITIALIZER(g_hrtimer_tree);
#else
struct list_node g_hrtimer_list = LIST_INITIAL_VALUE(g_hrtimer_list);
#endif
/****************************************************************************
* Public Functions
@@ -83,4 +87,6 @@ struct hrtimer_tree_s g_hrtimer_tree = RB_INITIALIZER(g_hrtimer_tree);
* core (e.g., hrtimer_start(), hrtimer_cancel(), and expire paths).
****************************************************************************/
#ifdef CONFIG_HRTIMER_TREE
RB_GENERATE(hrtimer_tree_s, hrtimer_node_s, entry, hrtimer_compare);
#endif