-
Notifications
You must be signed in to change notification settings - Fork 60
Manage ticks to suppress RCU CPU stall warning #75
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||
---|---|---|---|---|---|---|---|---|
|
@@ -132,6 +132,16 @@ DTC ?= dtc | |||||||
E := | ||||||||
S := $E $E | ||||||||
|
||||||||
# During boot process, he emulator manually manages the growth of ticks to | ||||||||
# suppress RCU CPU stall warnings. Thus, we need an target time to set the | ||||||||
# increment of ticks. According to Using RCU’s CPU Stall Detector[1], the | ||||||||
# grace period for RCU CPU stalls is typically set to 21 seconds. | ||||||||
# By dividing this value by two as the expected completion time, we can | ||||||||
# provide a sufficient buffer to reduce the impact of errors and avoid | ||||||||
# RCU CPU stall warnings. | ||||||||
# [1] docs.kernel.org/RCU/stallwarn.html#config-rcu-cpu-stall-timeout | ||||||||
CFLAGS += -D SEMU_BOOT_TARGET_TIME=10 | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider making boot time configurable
Consider making the boot target time configurable via environment variable instead of hardcoding it in the Makefile. This would allow users to override the value without modifying the Makefile. Could use something like: Code suggestionCheck the AI-generated fix before applying
Suggested change
Code Review Run #9f603b Is this a valid issue, or was it incorrectly flagged by the Agent?
|
||||||||
|
||||||||
SMP ?= 1 | ||||||||
.PHONY: riscv-harts.dtsi | ||||||||
riscv-harts.dtsi: | ||||||||
|
Original file line number | Diff line number | Diff line change | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -1,3 +1,4 @@ | ||||||||||||||
#include <stdbool.h> | ||||||||||||||
#include <time.h> | ||||||||||||||
|
||||||||||||||
#include "utils.h" | ||||||||||||||
|
@@ -19,6 +20,10 @@ | |||||||||||||
#endif | ||||||||||||||
#endif | ||||||||||||||
|
||||||||||||||
bool boot_complete = false; | ||||||||||||||
static double ticks_increment; | ||||||||||||||
static double boot_ticks; | ||||||||||||||
Comment on lines
+24
to
+25
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider initializing static timing variables
Consider initializing Code suggestionCheck the AI-generated fix before applying
Suggested change
Code Review Run #9f603b Is this a valid issue, or was it incorrectly flagged by the Agent?
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider consistent integer type usage
The Code suggestionCheck the AI-generated fix before applying
Suggested change
Code Review Run #9f603b Is this a valid issue, or was it incorrectly flagged by the Agent?
|
||||||||||||||
|
||||||||||||||
/* Calculate "x * n / d" without unnecessary overflow or loss of precision. | ||||||||||||||
* | ||||||||||||||
* Reference: | ||||||||||||||
|
@@ -32,35 +37,93 @@ static inline uint64_t mult_frac(uint64_t x, uint64_t n, uint64_t d) | |||||||||||||
return q * n + r * n / d; | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
void semu_timer_init(semu_timer_t *timer, uint64_t freq) | ||||||||||||||
{ | ||||||||||||||
timer->freq = freq; | ||||||||||||||
semu_timer_rebase(timer, 0); | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
static uint64_t semu_timer_clocksource(uint64_t freq) | ||||||||||||||
/* High-precision time measurement: | ||||||||||||||
* - POSIX systems: clock_gettime() for nanosecond precision | ||||||||||||||
* - macOS: mach_absolute_time() with timebase conversion | ||||||||||||||
* - Other platforms: time(0) with conversion to nanoseconds as fallback | ||||||||||||||
* | ||||||||||||||
* The platform-specific timing logic is now clearly separated: POSIX and macOS | ||||||||||||||
* implementations provide high-precision measurements, while the fallback path | ||||||||||||||
* uses time(0) for a coarser but portable approach. | ||||||||||||||
*/ | ||||||||||||||
static inline uint64_t host_time_ns() | ||||||||||||||
{ | ||||||||||||||
#if defined(HAVE_POSIX_TIMER) | ||||||||||||||
struct timespec t; | ||||||||||||||
clock_gettime(CLOCKID, &t); | ||||||||||||||
return t.tv_sec * freq + mult_frac(t.tv_nsec, freq, 1e9); | ||||||||||||||
struct timespec ts; | ||||||||||||||
clock_gettime(CLOCKID, &ts); | ||||||||||||||
return (uint64_t) ts.tv_sec * 1e9 + (uint64_t) ts.tv_nsec; | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider using integer constant for nanoseconds
Consider using Code suggestionCheck the AI-generated fix before applying
Suggested change
Code Review Run #9f603b Is this a valid issue, or was it incorrectly flagged by the Agent?
|
||||||||||||||
|
||||||||||||||
#elif defined(HAVE_MACH_TIMER) | ||||||||||||||
static mach_timebase_info_data_t t; | ||||||||||||||
if (t.denom == 0) | ||||||||||||||
(void) mach_timebase_info(&t); | ||||||||||||||
return mult_frac(mult_frac(mach_absolute_time(), t.numer, t.denom), freq, | ||||||||||||||
1e9); | ||||||||||||||
static mach_timebase_info_data_t ts = {0}; | ||||||||||||||
if (ts.denom == 0) | ||||||||||||||
(void) mach_timebase_info(&ts); | ||||||||||||||
|
||||||||||||||
uint64_t now = mach_absolute_time(); | ||||||||||||||
/* convert to nanoseconds: (now * t.numer / t.denom) */ | ||||||||||||||
return mult_frac(now, ts.numer, (uint64_t) ts.denom); | ||||||||||||||
|
||||||||||||||
#else | ||||||||||||||
return time(0) * freq; | ||||||||||||||
/* Fallback to non-HRT calls time(0) in seconds => convert to ns. */ | ||||||||||||||
time_t now_sec = time(0); | ||||||||||||||
return (uint64_t) now_sec * 1e9; | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use consistent integer constant in fallback
Similar to above, consider using Code suggestionCheck the AI-generated fix before applying
Suggested change
Code Review Run #9f603b Is this a valid issue, or was it incorrectly flagged by the Agent?
|
||||||||||||||
#endif | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
/* The function that returns the "emulator time" in ticks. | ||||||||||||||
* | ||||||||||||||
* Before the boot process is completed, the emulator manually manages the | ||||||||||||||
* growth of ticks to suppress RCU CPU stall warnings. After the boot process is | ||||||||||||||
* completed, the emulator switches back to the real-time timer, using an offset | ||||||||||||||
* bridging to ensure that the ticks of both timers remain consistent. | ||||||||||||||
*/ | ||||||||||||||
static uint64_t semu_timer_clocksource(semu_timer_t *timer) | ||||||||||||||
{ | ||||||||||||||
/* After boot process complete, the timer will switch to real time. Thus, | ||||||||||||||
* there is an offset between the real time and the emulator time. | ||||||||||||||
* | ||||||||||||||
* After switching to real time, the correct way to update time is to | ||||||||||||||
* calculate the increment of time. Then add it to the emulator time. | ||||||||||||||
*/ | ||||||||||||||
static int64_t offset = 0; | ||||||||||||||
static bool first_switch = true; | ||||||||||||||
Comment on lines
+87
to
+88
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider making static variables thread-safe
Consider making Code suggestionCheck the AI-generated fix before applying
Suggested change
Code Review Run #9f603b Is this a valid issue, or was it incorrectly flagged by the Agent?
|
||||||||||||||
|
||||||||||||||
if (!boot_complete) { | ||||||||||||||
boot_ticks += ticks_increment; | ||||||||||||||
return (uint64_t) boot_ticks; | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
uint64_t real_ticks = mult_frac(host_time_ns(), timer->freq, 1e9); | ||||||||||||||
if (first_switch) { | ||||||||||||||
first_switch = false; | ||||||||||||||
|
||||||||||||||
/* Calculate the offset between the real time and the emulator time */ | ||||||||||||||
offset = (int64_t) (real_ticks - boot_ticks); | ||||||||||||||
} | ||||||||||||||
return (uint64_t) ((int64_t) real_ticks - offset); | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
void semu_timer_init(semu_timer_t *timer, uint64_t freq, int n_harts) | ||||||||||||||
jserv marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||
{ | ||||||||||||||
timer->freq = freq; | ||||||||||||||
timer->begin = mult_frac(host_time_ns(), timer->freq, 1e9); | ||||||||||||||
boot_ticks = timer->begin; /* Initialize the fake ticks for boot process */ | ||||||||||||||
|
||||||||||||||
/* According to statistics, the number of times 'semu_timer_clocksource' | ||||||||||||||
* called is approximately 'SMP count * 2.15 * 1e8'. By the time the boot | ||||||||||||||
* process is completed, the emulator will have a total of 'boot seconds * | ||||||||||||||
* frequency' ticks. Therefore, each time, '(boot seconds * frequency) / | ||||||||||||||
* (2.15 * 1e8 * SMP count)' ticks need to be added. | ||||||||||||||
*/ | ||||||||||||||
ticks_increment = | ||||||||||||||
(SEMU_BOOT_TARGET_TIME * CLOCK_FREQ) / (2.15 * 1e8 * n_harts); | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
uint64_t semu_timer_get(semu_timer_t *timer) | ||||||||||||||
{ | ||||||||||||||
return semu_timer_clocksource(timer->freq) - timer->begin; | ||||||||||||||
return semu_timer_clocksource(timer) - timer->begin; | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
void semu_timer_rebase(semu_timer_t *timer, uint64_t time) | ||||||||||||||
{ | ||||||||||||||
timer->begin = semu_timer_clocksource(timer->freq) - time; | ||||||||||||||
timer->begin = semu_timer_clocksource(timer) - time; | ||||||||||||||
} |
Uh oh!
There was an error while loading. Please reload this page.