1.1 --- a/src/os/bsd/vm/os_bsd.cpp Mon May 05 15:10:43 2014 +0200 1.2 +++ b/src/os/bsd/vm/os_bsd.cpp Fri Apr 25 07:40:33 2014 +0200 1.3 @@ -127,8 +127,12 @@ 1.4 // global variables 1.5 julong os::Bsd::_physical_memory = 0; 1.6 1.7 - 1.8 +#ifdef __APPLE__ 1.9 +mach_timebase_info_data_t os::Bsd::_timebase_info = {0, 0}; 1.10 +volatile uint64_t os::Bsd::_max_abstime = 0; 1.11 +#else 1.12 int (*os::Bsd::_clock_gettime)(clockid_t, struct timespec *) = NULL; 1.13 +#endif 1.14 pthread_t os::Bsd::_main_thread; 1.15 int os::Bsd::_page_size = -1; 1.16 1.17 @@ -986,13 +990,15 @@ 1.18 return jlong(time.tv_sec) * 1000 + jlong(time.tv_usec / 1000); 1.19 } 1.20 1.21 +#ifndef __APPLE__ 1.22 #ifndef CLOCK_MONOTONIC 1.23 #define CLOCK_MONOTONIC (1) 1.24 #endif 1.25 +#endif 1.26 1.27 #ifdef __APPLE__ 1.28 void os::Bsd::clock_init() { 1.29 - // XXXDARWIN: Investigate replacement monotonic clock 1.30 + mach_timebase_info(&_timebase_info); 1.31 } 1.32 #else 1.33 void os::Bsd::clock_init() { 1.34 @@ -1007,10 +1013,38 @@ 1.35 #endif 1.36 1.37 1.38 +#ifdef __APPLE__ 1.39 + 1.40 +jlong os::javaTimeNanos() { 1.41 + const uint64_t tm = mach_absolute_time(); 1.42 + const uint64_t now = (tm * Bsd::_timebase_info.numer) / Bsd::_timebase_info.denom; 1.43 + const uint64_t prev = Bsd::_max_abstime; 1.44 + if (now <= prev) { 1.45 + return prev; // same or retrograde time; 1.46 + } 1.47 + const uint64_t obsv = Atomic::cmpxchg(now, (volatile jlong*)&Bsd::_max_abstime, prev); 1.48 + assert(obsv >= prev, "invariant"); // Monotonicity 1.49 + // If the CAS succeeded then we're done and return "now". 1.50 + // If the CAS failed and the observed value "obsv" is >= now then 1.51 + // we should return "obsv". If the CAS failed and now > obsv > prv then 1.52 + // some other thread raced this thread and installed a new value, in which case 1.53 + // we could either (a) retry the entire operation, (b) retry trying to install now 1.54 + // or (c) just return obsv. We use (c). No loop is required although in some cases 1.55 + // we might discard a higher "now" value in deference to a slightly lower but freshly 1.56 + // installed obsv value. That's entirely benign -- it admits no new orderings compared 1.57 + // to (a) or (b) -- and greatly reduces coherence traffic. 1.58 + // We might also condition (c) on the magnitude of the delta between obsv and now. 1.59 + // Avoiding excessive CAS operations to hot RW locations is critical. 1.60 + // See https://blogs.oracle.com/dave/entry/cas_and_cache_trivia_invalidate 1.61 + return (prev == obsv) ? now : obsv; 1.62 +} 1.63 + 1.64 +#else // __APPLE__ 1.65 + 1.66 jlong os::javaTimeNanos() { 1.67 if (Bsd::supports_monotonic_clock()) { 1.68 struct timespec tp; 1.69 - int status = Bsd::clock_gettime(CLOCK_MONOTONIC, &tp); 1.70 + int status = Bsd::_clock_gettime(CLOCK_MONOTONIC, &tp); 1.71 assert(status == 0, "gettime error"); 1.72 jlong result = jlong(tp.tv_sec) * (1000 * 1000 * 1000) + jlong(tp.tv_nsec); 1.73 return result; 1.74 @@ -1023,6 +1057,8 @@ 1.75 } 1.76 } 1.77 1.78 +#endif // __APPLE__ 1.79 + 1.80 void os::javaTimeNanos_info(jvmtiTimerInfo *info_ptr) { 1.81 if (Bsd::supports_monotonic_clock()) { 1.82 info_ptr->max_value = ALL_64_BITS;