mirror of
https://github.com/apache/nuttx.git
synced 2026-05-26 10:46:28 +08:00
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:
committed by
Xiang Xiao
parent
3c1712c66d
commit
291938150f
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user