77c9fd5004
Replace busy-wait spin_loop() in FenceTimeline::wait() with Condvar::wait_timeout(). signal() now calls notify_all() to wake blocked threads. This turns syncobj_wait from CPU-burning poll to proper blocking sleep/wake. Add two new tests: - test_wait_wakes_on_signal: spawns a thread that signals after 10ms, verifies the blocked wait wakes within 1s - test_wait_timeout_expires: verifies 1ms timeout on an unsignaled fence returns an error