-
Notifications
You must be signed in to change notification settings - Fork 1.4k
sched: Refactor the functional incorrect HRTimer implementation. #17675
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
170572b to
5a0104b
Compare
| * Private Functions | ||
| ****************************************************************************/ | ||
|
|
||
| static inline_function clock_t adjust_next_interval(clock_t interval) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
move to separated pr
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved to #17680.
| ****************************************************************************/ | ||
|
|
||
| #ifdef CONFIG_SCHED_TICKLESS | ||
| int weak_function up_alarm_cancel(FAR struct timespec *ts) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
move to the separated pr too
| up_alarm_tick_start(div_const_roundup(next_expired, NSEC_PER_TICK)); | ||
| # else | ||
| struct timespec ts; | ||
| # ifdef CONFIG_SCHED_TICKLESS_ALARM |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
merge to e72a975
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Merged.
|
@Fix-Point @xiaoxiang781216 @GUIDINGLI I believe this hritmer feature is genuinely useful for Apache NuttX, which is why I decided to introduce it about three months ago. Since then, I have continued to refine and improve it whenever shortcomings were identified, with the goal of making it more robust and mature. I really don’t want to get into a dispute again. If you want to merge this refactoring, I am not able to stop you However, I would appreciate it if my implementation were not described as incorrect or even completely unusable, or described as having functional issues or being inferior in terms of performance, readability, or effectiveness. I acknowledge that the first version did not fully account for SMP, but I have submitted a fix (#17642 Finally, before merging this, I would suggest performing a performance comparison with my PR (#17573 Thank you! Best Regards |
anchao
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Setting aside the implementation details, there are far too many critical section issues that I haven’t pointed out them exhaustively. You are advised to fully resolve them before submitting the code.
Also, please watch your wording. What is "incorrect"? I’m genuinely curious about your professionalism and respectfulness — you are essentially belittling the work of individual developers.
include/nuttx/hrtimer.h
Outdated
| } | ||
|
|
||
| static inline_function | ||
| int hrtimer_start(FAR hrtimer_t *timer, hrtimer_callback_t func, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why was the parameter prototype changed? If func/arg are determined in hrtimer_init or hrtimer_setup, it will yield better performance for the start process.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Compared to previous implementation,
- when restarting the timer, writing the three fields—
func,arg, andexpired—does indeed involve two additional writes compared to writing onlyexpired. - However, within the critical section, this implementation does not require modifying the
funcof the hrtimer, which saves one write operation compared to the need to write thestatefield, resulting in an overall increase of onewriteoutside the critical section but onewritereduced inside the critical section.
The advantage of this interface design is that it reuses func to encode the state of the hrtimer, saving 4 bytes of space per hrtimer. Furthermore, it maintains consistency with other OS APIs (such as workqueue and wdog), improving user-friendliness.
I believe the slight overhead outside the critical section will be hidden by the pipeline and should not have a significant impact on overall performance. I will attempt to write test cases to compare the performance of the two implementations.
include/nuttx/hrtimer_queue.h
Outdated
| static inline_function | ||
| void hrtimer_queue_init(FAR hrtimer_queue_internal_t *queue) | ||
| { | ||
| FAR hrtimer_internal_t *guard_timer = &queue->guard_timer; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add null pointer check or remove debug assert on line 102
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you, null pointer check is added and debug assertion is removed.
| hrtimer_callback_t func; | ||
| uint64_t next_expired; | ||
| uint64_t expired; | ||
| int cpu = this_cpu(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cpu may changed without lock
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can ensure the invariant that the core id will not change in the interrupt handling.
- NuttX currently does not support kernel preemption, thus interrupts cannot be nested within interrupt context. Even if kernel preemption and interrupt nesting are supported in the future, we can avoid nested calls to
hrtimer_expiryby using an interrupt nesting counter. - During interrupt handling, we use per-core
ARCH_INTERRUPTSTACK, ensuring that the core ID remains unchanged while in interrupt context.
5a0104b to
fe7aa38
Compare
I am sorry for my mistake. The |
fe7aa38 to
da45306
Compare
A minor fix can resolve the issue you mentioned, check #17642, you don't need to do such a big refactoring |
This commit removed functional incorrect hrtimer implementation. This implementation can not work correctly for SMP systems. Signed-off-by: ouyangxiangzhen <[email protected]>
da45306 to
e846886
Compare
| int hrtimer_compare(FAR const hrtimer_rb_t *a, FAR const hrtimer_rb_t *b) | ||
| { | ||
| /* This branchless compare is equivalent to: | ||
| * (int64_t)(a->expired - b->expired) > 0 ? 1 : -1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should be equivalent to (int64_t)(a->expired - b->expired) >= 0 ? 1 : -1;
This ensures that when a new timer has the same expiration time as an existing one, it will be placed after the older timer.
| */ | ||
|
|
||
| static inline_function | ||
| void hrtimer_reprogram(FAR hrtimer_queue_internal_t *queue, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you think this is an external API?
include/nuttx/hrtimer_queue.h
Outdated
| ****************************************************************************/ | ||
|
|
||
| static inline_function | ||
| int hrtimer_queue_init(FAR hrtimer_queue_internal_t *queue) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Internal API should not be exposed to users
include/nuttx/hrtimer.h
Outdated
| } | ||
|
|
||
| static inline_function | ||
| int hrtimer_start(FAR hrtimer_t *timer, hrtimer_callback_t func, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This API requires users to provide too many parameters, which I don’t think is ideal.
Users really only need to specify arg, mode, and func during hrtimer_init.
Therefore, my suggestion is to adopt my implementation, offering two separate APIs:
hrtimer_init()
hrtimer_start()
| #define HRTIMER_TIME_AFTER(t1, t2) ((int64_t)((t2) - (t1)) < 0) | ||
| #define HRTIMER_TIME_AFTER_EQ(t1, t2) ((int64_t)((t2) - (t1)) <= 0) | ||
|
|
||
| #define HRTIMER_MODE_ABS (0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is not safe to use a macro to represent the mode. We should use an enum instead, which allows the compiler to perform type checking for us.
| (timer)->expired = (time); \ | ||
| } while(0) | ||
|
|
||
| #define hrtimer_init(timer) memset(timer, 0, sizeof(timer)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should allow users to specify arg, mode, and func when initializing the hrtimer via hrtimer_init.
include/nuttx/hrtimer_queue.h
Outdated
| * jumping to NULL. | ||
| */ | ||
|
|
||
| hrtimer_fill(guard_timer, NULL, NULL, INT64_MAX); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In an RTOS system, a guard_timer is generally not needed, as the hrtimer module should be robust.
If the system misbehaves due to application issues rather than kernel faults, the proper approach would be to handle it at the system level, such as performing a restart.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- FMEA analysis requires us to design a safety mechanism to ensure fault tolerance.
- This guard timer help us avoid checking if the queue is empty during expiration processing, which would also save a branch on the critical path.
|
|
||
| /* Wait until all references have been released. */ | ||
|
|
||
| for (cpu = 0; cpu < CONFIG_SMP_NCPUS; cpu++) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are two loops in this section, which may impact efficiency. It might be worth considering a way to optimize or combine them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Both of these loops have definite upper bounds and can be expanded using macro.
| - The caller has ownership of the timer. | ||
| - Mode parameter is valid (0 or 1). | ||
| .. c:function:: int hrtimer_start(FAR hrtimer_t *timer, hrtimer_callback_t func, FAR void *arg, uint64_t time, uint32_t mode) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mode should be enum type, so compiler can do type checking for you.
include/nuttx/hrtimer.h
Outdated
| hrtimer_cb func, | ||
| FAR void *arg) | ||
| int hrtimer_restart(hrtimer_t *timer, hrtimer_callback_t func, | ||
| FAR void *arg, uint64_t time, uint32_t mode) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mode should be enum type, so compiler can do type checking for you.
include/nuttx/hrtimer.h
Outdated
| expired += clock_systime_nsec(); | ||
| } | ||
|
|
||
| DEBUGASSERT(mode <= 1u); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let the compiler to do type checking for you.
include/nuttx/hrtimer.h
Outdated
| { | ||
| int ret = -EINVAL; | ||
|
|
||
| DEBUGASSERT(mode <= 1u); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto
include/nuttx/hrtimer.h
Outdated
|
|
||
| static inline_function | ||
| int hrtimer_start(FAR hrtimer_t *timer, hrtimer_callback_t func, | ||
| FAR void *arg, uint64_t time, uint32_t mode) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto
| **hrtimer_start(timer, func, arg, time, mode)**: Starts a timer. | ||
| The mode parameter indicates whether it is a relative or absolute timer. | ||
| **hrtimer_restart(timer, func, arg, time, mode)**: Restarts a timer that has |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don’t need a separate hrtimer_restart, which would require users to input arg, time, and mode again.
Restarting essentially starts the hrtimer with a new expiry. If users want to refresh the hrtimer, they can simply call hrtimer_init() first.
So, in practice, the following functions are sufficient for users to manage hrtimers:
hrtimer_init(), hrtimer_start(), hrtimer_cancel(), and hrtimer_cancel_sync().
|
Let me make a conclusion of all my comments for your implementation into four categories:
|
This commit introduced hrtimer_queue, a resuable component to generate user-defined hrtimer implementation. Signed-off-by: ouyangxiangzhen <[email protected]>
This commit introduced the high-resolution timer abstraction. The hrtimer design features including: Use a strict state machine: an active timer can not be directly restarted, simplifying the implementation. Abstract the sorted queue for flexibility, allowing different data structures for various use cases. Execute callbacks with interrupts enabled, using hazard pointers to manage references. Clear ownership transfer: callbacks return the next expiration time for periodic timers, and the thread executing the callback is responsible for restarting or releasing the timer. Non-blocking restart: allow restarting a timer even if its callback is still running, requiring proper synchronization in the callback function. Starvation-free cancellation: use hazard pointers to avoid starvation and ensure safe memory reclamation. Signed-off-by: ouyangxiangzhen <[email protected]>
This commit supported wdog/scheduler hrtimer with tickless enabled. Signed-off-by: ouyangxiangzhen <[email protected]>
This commit added documentation for HRTimer. Signed-off-by: ouyangxiangzhen <[email protected]>
e846886 to
114a9f5
Compare
Thank you for your suggestions. Your comments are very insightful. Below are the modifications made based on your advice:
Regarding some other points that have not been changed yet, clarifications are as follows: 1. Determinism Issues Caused by WaitingWe need to discuss this case by case:
2. Interface Design IssuesAs mentioned, the reasons for adopting an interface in the form of
From a performance perspective, compared to the previous implementation, this PR’s implementation does incur two additional writes outside the critical section when restarting a timer, but it saves one write inside the critical section (because
Since these are consecutive writes to the same cache line and CPU pipelining can hide some of the latency, the extra write outside the critical section should not cause significant performance issues in practice. Overall, I believe the 3. Lock Performance IssuesAccording to our test results (#17569):
However, these results are from x86 platforms and may vary across different architectures. 4. Why Forward‑declare the Dependent Function
|
I suggest you to test performance and function on both SMP and non-SMP platform with my latest PR. Especially Checking the implementation of hrtimer_process and hrtimer_cancel_sync One more reminder is that hrtimer will mainly be used on non-SMP platform, your implementation also need to consider non-SMP performance. Anyway I will not spend time on your implementation anymore. And I don't care whose version got acquired by NuttX, I am just telling the truth on technical aspects. Regards. |
Summary
This PR is the part IV of #17556. The main changes in this PR are:
CONFIG_SCHED_TICKLESS_TICK_ARGUMENTto simplify kernel configuration and expiration handling.hrtimer_queuecomponent, allowing users to freely compose it with any hardware timer to implement their own hrtimer instance.Background
High-resolution Timer (HRTimer) is a timer abstraction capable of achieving nanosecond-level timing precision, primarily used in scenarios requiring high-precision clock events. With the advancement of integrated circuit technology, modern high-precision timer hardware (such as the typical x86 HPET) can already meet sub-nanosecond timing requirements and offer femtosecond-level jitter control.
Although the current hardware timer abstraction (
up_alarm/up_timer) in the NuttX kernel already supports nanosecond-level timing, its software timer abstraction, wdog, and the timer expiration interrupt handling process remain at microsecond-level (tick) precision, which falls short of high-precision timing demands. Therefore, it is necessary to implement a new timer abstraction—HRTimer, to address the precision limitations of wdog. HRTimer primarily provides the following functional interfaces:Design
The new NuttX HRTimer is designed to address the issues of insufficient precision in the current NuttX wdog. It draws on the strengths of the Linux HRTimer design while improving upon its weaknesses. As Figure 1 shows, the HRTimer design is divided into two parts: the
HRTimer Queueand theHRTimer. TheHRTimer Queueis a reusable component that allows users to freely customize their ownHRTimerinterface by pairing it with a private timer driver, without needing to modify the kernel code.graph TD subgraph "Public Headers" A[hrtimer_queue_type.h<br/> Public Type Definition] end subgraph "Internal Implementation Headers" B1[hrtimer_type_list.h<br/>List Implementation] B2[hrtimer_type_rb.h<br/>RB-Tree Implementation] B3[...Others] C[hrtimer_queue.h<br/>Reusable Component<br/>HRTimer Queue Internal] end subgraph "Instances" D[hrtimer.h<br/>OS HRTimer API ] E[hrtimer.c<br/>OS HRTimer Implementation] F[myhrtimer.h<br/>Customed HRTimer API ] G[myhrtimer.c<br/>Customed HRTimer Implementation] end %% Dependent A --> B1 A --> B2 A --> B3 B1 --> C B2 --> C B3 --> C A --> D C --> E D --> E A --> F C --> G F --> G %% Style style A fill:#e1f5fe style B1 fill:#f3e5f5 style B2 fill:#f3e5f5 style B3 fill:#f3e5f5 style C fill:#fff3e0 style D fill:#e8f5e8 style E fill:#e8f5e8 style F fill:#e8f5e8 style G fill:#e8f5e8Figure 1. The architecture of the HRTimer implementation
API Design
The HRTimer Queue is a zero-performance-overhead, composable, and customizable abstraction that provides only asynchronous-style interfaces:
All other user interfaces can be composed based on these three interfaces.
On top of the
HRTimer Queue, users only need to implement the following interfaces to customize their own HRTimer implementation:After implementing the above three interfaces, users can include one of the
hrtimer_type_xxx.himplementation to compose their own hrtimer implementation, which mainly includes the following interfaces:try_to_cancel. It ensures that the timer can definitely be canceled successfully, but may need to wait for its callback function to finish execution.The design characteristics of HRTimer are as follows:
Strict and Simplified HRTimer State Machine: In the old wdog design, wdog could be reset in any state, which introduced unnecessary complexity to certain function implementations. For example,
wd_starthad to account for the possibility of restarting. In the new HRTimer design, an HRTimer that has already been started and not canceled cannot be started again.Abstracted Sorting Queue: Since no single design can be optimal for all application scenarios, HRTimer abstracts interfaces for inserting and deleting nodes in the sorting queue. This allows for different data structure implementations to be configured for different application scenarios, as shown in Table 1.
Table 1: Comparison of Several Sorting Queue Implementations
Callback Execution Without Lock Held: HRTimer implements callback execution without lock held, ensuring that the system's blocking time is not limited by the user's callback function. However, this introduces additional states and waits, where waiting for reference release is primarily implemented using hazard pointers. This will be explained in detail in the subsequent state transition diagram.
Clear HRTimer Object Ownership Transfer Path: In the wdog implementation, the wdog callback function could restart the current timer directly without regard to ownership, potentially causing concurrency issues. In the new implementation, the HRTimer callback function cannot restart itself. Instead, inspired by Linux's design, the callback function returns whether a restart is needed. If a restart is required, the thread executing the callback function re-enqueues it; otherwise, the thread releases ownership. This change ensures a clear ownership transfer path for the HRTimer object.
Non-blocking Timer Restart: To address the issue in Linux where restarting a timer must wait for an already-started callback function to finish, which reduces the real-time performance, the new HRTimer implements a non-blocking timer restart mechanism. This mechanism reuses the last bit of the hazard pointer to mark whether the thread executing the callback has lost write ownership of the HRTimer object. After
hrtimer_async_cancelis called, other threads executing callbacks will lose write ownership of the HRTimer (though their callback functions may still be executing). This means the HRTimer can be restarted and repurposed for other callbacks without waiting for the callback function to complete. However, note that the callback function might still be executing, requiring users to consider this concurrency and implement proper synchronization mechanisms within their callback functions. To explicitly remind users of this concurrency, an HRTimer whose callback function has not yet completed execution must be restarted usinghrtimer_restart. This function relaxes the state checks on the HRTimer, allowing a timer with the callback running to be started.Deterministic Timer Cancellation: To address the starvation issue present in Linux's timer cancellation, the new HRTimer implementation sets a cancellation state via
hrtimer_async_cancel. This cancellation state has a unique and deterministic state transition, eliminating starvation. Memory reclamation is performed through hazard pointer checking loops. Hazard pointer checking ensures that all threads finish executing the callback function and release read ownership (reference release) of the specified HRTimer object.The valid state transitions of an HRTimer object are shown in Figure 2. States are represented using a simplified notation of
State|Ownership, such asHRTIMER_PENDING|shared. The meanings of the simplified ownership markers are as follows:Ownership Markers
|privateindicates that the resource is exclusively owned by a specific threadt. Only the owning threadtcan read from or write to this resource.|sharedindicates that the resource is globally shared and can be read by any thread. However, only the threadtthat holds the global lockl(t = Owned(l)) can obtain write ownership of this resource.|half_sharedindicates that the resource may be accessed by multiple threads, but only the thread that calledasync_cancelholds write ownership of this resource. Modifications to it by threads executing callback functions are prevented.The resource ownership here uses a simplified notation. In actual static analysis or formal verification processes, more complex abstractions such as resource algebra might be employed.
All state transitions not described in the diagram must return failure. For example, a timer in the
HRTIMER_PENDINGstate cannot be started (start) again. Note that there is one exception: a thread that is already in theHRTIMER_CANCELEDstate can legally callhrtimer_async_cancelagain, and the state remains unchanged.To avoid the overhead caused by threads waiting for callback functions to finish executing, HRTimer adds a
restartinterface. Under normal circumstances, thestartinterface cannot start a timer that is already in thecanceledstate. Only when the user uses thisrestartinterface can a timer whose callback function has not yet completed be started normally. Using this interface serves to explicitly remind users to pay attention to concurrency within their callback functions. Furthermore, when concurrency issues arise with HRTimer, it helps in pinpointing the source of the problem—issues can only originate from callback functions whererestartwas used to restart the timer.%%{ init: { 'theme': 'base', 'themeVariables': { 'primaryColor': '#FFFFFF', 'primaryTextColor' : '#000000', 'mermiad-container': "#FFFFFF", 'primaryBorderColor': '#000000', 'lineColor': '#000000', 'secondaryColor': '#FFFFFF', 'tertiaryColor': '#000000' }, 'sequence': { 'mirrorActors': false } } }%% stateDiagram-v2 HRTIMER_COMPLETED|private --> HRTIMER_PENDING|shared : hrtimer_start HRTIMER_PENDING|shared --> HRTIMER_COMPLETED|private : hrtimer callback return 0 in hrtimer_expiry HRTIMER_PENDING|shared --> HRTIMER_PENDING|shared : hrtimer callback return non-zero in hrtimer_expiry HRTIMER_PENDING|shared --> HRTIMER_CANCELED|half_shared : hrtimer_async_cancel HRTIMER_CANCELED|half_shared --> HRTIMER_CANCELED|private : hrtimer_cancel wait all cores release the references to the timer. HRTIMER_CANCELED|half_shared --> HRTIMER_PENDING|shared : hrtimer_restart HRTIMER_CANCELED|private --> HRTIMER_COMPLETED|private : Complete the cancelFigure 2. HRTimer State Transition Diagram
Performance Evaluation
We conducted 1 million interface calls on the
intel64:nsh(Intel Core i7 12700) platform and measured their average execution CPU cycles, as shown in the Figure 3 below. It can be observed that the overhead for starting and asynchronously canceling timers is significantly reduced compared to wdog.hrtimer_startcompared towd_startis 2.10x.hrtimer_start & cancelcompared towd_start & cancelis 1.57x.Additionally, after enabling hrtimer, wdog processing is treated as an hrtimer timer, which lowers the overhead of the wdog interface.
wd_startachieved a speedup of 1.73x when hrtimer is enabled.Figure 3. HRtimer API Latency Test
Plan
The merge plan for this PR is as follows:
Impact
HRTimer currently is disabled by default, so it has no effect on system.
Testing
Tested on
intel64:nsh,rv-virt:smp,qemu-armv8a:smp,ostestpassed. The hrtimer SMP stress test ran for over 72 hours without errors. The parallel stress test cases is showed in Appendix.Explanation
Here we need to provide some explanations to avoid misunderstandings with others' work:
Is this hrtimer an improvement based on @wangchdo work #17517?
ClockDeviceabstraction (driver/timers: ClockDevice, a new timer driver abstraction for NuttX. #17276). The core concurrent state machine was completed as early as August this year. My plan was to support HRTimer after finishing theClockDevice. During this period, I had no communication with @wangchdo .Why are we removing the existing hrtimer implementation and replacing it with this one? Is this disrespectful to @wangchdo 's work?
Simple modifications cannot fix @wangchdo implementation. Therefore, I believe the most effective approach is to remove the existing hrtimer implementation and replace it with this one.
For example, two key implementations severely violate the ownership invariant:
test_callbackis triggered before the firsttest_callbackfinishes executing, it may causeBto be updated twice.More similar concurrency issues could be cited here. As I have emphasized again and again, the fundamental problem is the violation of the ownership invariant of hrtimer: only one owner can modify the hrtimer object at a time.
Designing functionally correct concurrent algorithms is not easy at all. Relying solely on engineering experience is insufficient; theoretical methods are necessary to avoid errors, such as adapting resource invariants and using structured diagrams to clarify every possible concurrent state transition. @wangchdo's design failed to consider how to handle concurrency correctly, making it nearly impossible to improve upon his code base.
From an efficiency perspective, replacing @wangchdo 's implementation with this PR's implementation—which is functionally correct, offers better code reusability, and is more user-friendly—can save both of us time and allow us to focus on more meaningful optimizations.
Appendix
The hrtimer parallel stress test cases is showed as following, and they will be pushed to
nuttx-appsafter this PR is merged: