@@ -50,21 +50,31 @@ struct MachTimeBaseLocal {
5050 numer_ = timebase.numer ;
5151 denom_ = timebase.denom ;
5252 calibration_interval_mach_ = CALIBRATION_INTERVAL_NS * denom_ / numer_;
53- calibrate ();
53+ // Do NOT call calibrate() here. Instead, set next_calibrate_mach_ = 0
54+ // to force calibration on first use via calibrate_if_needed().
55+ // This avoids a uint64_t underflow bug: the constructor is invoked lazily
56+ // on first thread_local access, AFTER the caller has already captured
57+ // current_mach = mach_absolute_time(). If calibrate() independently reads
58+ // mach_absolute_time(), base_mach_time_ becomes newer than the caller's
59+ // current_mach, causing (current_mach - base_mach_time_) to underflow.
60+ base_wall_time_us_ = 0 ;
61+ base_mach_time_ = 0 ;
62+ next_calibrate_mach_ = 0 ;
5463 }
5564
56- void calibrate () {
65+ // Calibrate using the caller's mach time to guarantee
66+ // base_mach_time_ <= current_mach (no underflow possible).
67+ void calibrate (uint64_t current_mach) {
5768 struct timeval tv;
5869 gettimeofday (&tv, nullptr );
59- uint64_t mach_now = mach_absolute_time ();
6070 base_wall_time_us_ = tv.tv_sec * 1000000LL + tv.tv_usec ;
61- base_mach_time_ = mach_now ;
62- next_calibrate_mach_ = mach_now + calibration_interval_mach_;
71+ base_mach_time_ = current_mach ;
72+ next_calibrate_mach_ = current_mach + calibration_interval_mach_;
6373 }
6474
6575 void calibrate_if_needed (uint64_t current_mach) {
6676 if (OB_UNLIKELY (current_mach >= next_calibrate_mach_)) {
67- calibrate ();
77+ calibrate (current_mach );
6878 }
6979 }
7080};
0 commit comments