Skip to content
Snippets Groups Projects
Commit aa112ef1 authored by Nat Goodspeed's avatar Nat Goodspeed
Browse files

DRTVWR-575: Fix bug in macOS micro_sleep().

The compiler was deducing an unsigned type for the difference (U64 desired
microseconds - half KERNEL_SLEEP_INTERVAL_US). When the desired sleep was less
than that constant, the difference went hugely positive, resulting in a very
long snooze.

Amusingly, forcing that U64 result into an S32 num_sleep_intervals worked only
*because* of integer truncation: the high-order bits were discarded, resulting
in a negative result as intended.

Ensuring that both integer operands are signed at the outset, though, produces
a more formally correct result.
parent bb718155
No related branches found
No related tags found
2 merge requests!3Update to main branch,!2Rebase onto current main branch
...@@ -121,9 +121,14 @@ U32 micro_sleep(U64 us, U32 max_yields) ...@@ -121,9 +121,14 @@ U32 micro_sleep(U64 us, U32 max_yields)
U64 start = get_clock_count(); U64 start = get_clock_count();
// This is kernel dependent. Currently, our kernel generates software clock // This is kernel dependent. Currently, our kernel generates software clock
// interrupts at 250 Hz (every 4,000 microseconds). // interrupts at 250 Hz (every 4,000 microseconds).
const U64 KERNEL_SLEEP_INTERVAL_US = 4000; const S64 KERNEL_SLEEP_INTERVAL_US = 4000;
auto num_sleep_intervals = (us - (KERNEL_SLEEP_INTERVAL_US >> 1)) / KERNEL_SLEEP_INTERVAL_US; // Use signed arithmetic to discover whether a sleep is even necessary. If
// either 'us' or KERNEL_SLEEP_INTERVAL_US is unsigned, the compiler
// promotes the difference to unsigned. If 'us' is less than half
// KERNEL_SLEEP_INTERVAL_US, the unsigned difference will be hugely
// positive, resulting in a crazy long wait.
auto num_sleep_intervals = (S64(us) - (KERNEL_SLEEP_INTERVAL_US >> 1)) / KERNEL_SLEEP_INTERVAL_US;
if (num_sleep_intervals > 0) if (num_sleep_intervals > 0)
{ {
U64 sleep_time = (num_sleep_intervals * KERNEL_SLEEP_INTERVAL_US) - (KERNEL_SLEEP_INTERVAL_US >> 1); U64 sleep_time = (num_sleep_intervals * KERNEL_SLEEP_INTERVAL_US) - (KERNEL_SLEEP_INTERVAL_US >> 1);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment