src/os/solaris/vm/os_solaris.cpp

Print this page
rev 6280 : 8040140: System.nanoTime() is slow and non-monotonic on OS X
Reviewed-by: sspitsyn, shade


1378   for (;;) {
1379 // grab lock for max_hrtime
1380     int curlock = max_hrtime_lock;
1381     if (curlock & LOCK_BUSY)  continue;
1382     if (gotlock = Atomic::cmpxchg(LOCK_BUSY, &max_hrtime_lock, LOCK_FREE) != LOCK_FREE) continue;
1383     if (newtime > max_hrtime) {
1384       max_hrtime = newtime;
1385     } else {
1386       newtime = max_hrtime;
1387     }
1388     // release lock
1389     max_hrtime_lock = LOCK_FREE;
1390     return newtime;
1391   }
1392 }
1393 // gethrtime can move backwards if read from one cpu and then a different cpu
1394 // getTimeNanos is guaranteed to not move backward on Solaris
1395 inline hrtime_t getTimeNanos() {
1396   if (VM_Version::supports_cx8()) {
1397     const hrtime_t now = gethrtime();
1398     // Use atomic long load since 32-bit x86 uses 2 registers to keep long.
1399     const hrtime_t prev = Atomic::load((volatile jlong*)&max_hrtime);
1400     if (now <= prev)  return prev;   // same or retrograde time;





1401     const hrtime_t obsv = Atomic::cmpxchg(now, (volatile jlong*)&max_hrtime, prev);
1402     assert(obsv >= prev, "invariant");   // Monotonicity
1403     // If the CAS succeeded then we're done and return "now".
1404     // If the CAS failed and the observed value "obs" is >= now then
1405     // we should return "obs".  If the CAS failed and now > obs > prv then
1406     // some other thread raced this thread and installed a new value, in which case
1407     // we could either (a) retry the entire operation, (b) retry trying to install now
1408     // or (c) just return obs.  We use (c).   No loop is required although in some cases
1409     // we might discard a higher "now" value in deference to a slightly lower but freshly
1410     // installed obs value.   That's entirely benign -- it admits no new orderings compared
1411     // to (a) or (b) -- and greatly reduces coherence traffic.
1412     // We might also condition (c) on the magnitude of the delta between obs and now.
1413     // Avoiding excessive CAS operations to hot RW locations is critical.
1414     // See http://blogs.sun.com/dave/entry/cas_and_cache_trivia_invalidate
1415     return (prev == obsv) ? now : obsv ;
1416   } else {
1417     return oldgetTimeNanos();
1418   }
1419 }
1420 
1421 // Time since start-up in seconds to a fine granularity.
1422 // Used by VMSelfDestructTimer and the MemProfiler.
1423 double os::elapsedTime() {
1424   return (double)(getTimeNanos() - first_hrtime) / (double)hrtime_hz;
1425 }
1426 
1427 jlong os::elapsed_counter() {
1428   return (jlong)(getTimeNanos() - first_hrtime);
1429 }
1430 
1431 jlong os::elapsed_frequency() {
1432    return hrtime_hz;
1433 }
1434 




1378   for (;;) {
1379 // grab lock for max_hrtime
1380     int curlock = max_hrtime_lock;
1381     if (curlock & LOCK_BUSY)  continue;
1382     if (gotlock = Atomic::cmpxchg(LOCK_BUSY, &max_hrtime_lock, LOCK_FREE) != LOCK_FREE) continue;
1383     if (newtime > max_hrtime) {
1384       max_hrtime = newtime;
1385     } else {
1386       newtime = max_hrtime;
1387     }
1388     // release lock
1389     max_hrtime_lock = LOCK_FREE;
1390     return newtime;
1391   }
1392 }
1393 // gethrtime can move backwards if read from one cpu and then a different cpu
1394 // getTimeNanos is guaranteed to not move backward on Solaris
1395 inline hrtime_t getTimeNanos() {
1396   if (VM_Version::supports_cx8()) {
1397     const hrtime_t now = gethrtime();
1398     if (AssumeMonotonicOSTimers) {
1399       return now;
1400     }
1401 
1402     const hrtime_t prev = max_hrtime;
1403     if (now <= prev) {
1404       return prev;   // same or retrograde time;
1405     }
1406     const hrtime_t obsv = Atomic::cmpxchg(now, (volatile jlong*)&max_hrtime, prev);
1407     assert(obsv >= prev, "invariant");   // Monotonicity
1408     // If the CAS succeeded then we're done and return "now".
1409     // If the CAS failed and the observed value "obsv" is >= now then
1410     // we should return "obsv".  If the CAS failed and now > obsv > prv then
1411     // some other thread raced this thread and installed a new value, in which case
1412     // we could either (a) retry the entire operation, (b) retry trying to install now
1413     // or (c) just return obsv.  We use (c).   No loop is required although in some cases
1414     // we might discard a higher "now" value in deference to a slightly lower but freshly
1415     // installed obsv value.   That's entirely benign -- it admits no new orderings compared
1416     // to (a) or (b) -- and greatly reduces coherence traffic.
1417     // We might also condition (c) on the magnitude of the delta between obsv and now.
1418     // Avoiding excessive CAS operations to hot RW locations is critical.
1419     // See https://blogs.oracle.com/dave/entry/cas_and_cache_trivia_invalidate
1420     return (prev == obsv) ? now : obsv ;
1421   } else {
1422     return oldgetTimeNanos();
1423   }
1424 }
1425 
1426 // Time since start-up in seconds to a fine granularity.
1427 // Used by VMSelfDestructTimer and the MemProfiler.
1428 double os::elapsedTime() {
1429   return (double)(getTimeNanos() - first_hrtime) / (double)hrtime_hz;
1430 }
1431 
1432 jlong os::elapsed_counter() {
1433   return (jlong)(getTimeNanos() - first_hrtime);
1434 }
1435 
1436 jlong os::elapsed_frequency() {
1437    return hrtime_hz;
1438 }
1439