src/os/solaris/vm/os_solaris.cpp

Print this page
rev 2869 : 7117303: VM uses non-monotonic time source and complains that it is non-monotonic
Summary: Replaces calls to os::javaTimeMillis(), which does not guarantee montonicity, in GC code to os::javaTimeNanos() with a suitable conversion factor. os::javaTimeNanos() mostly guarantees montonicity depending on the underlying OS implementation and, as a result, a better alternative. Changes in OS files are to make use of the newly defined constants in globalDefinitions.hpp.
Reviewed-by:


1657        vm_exit_out_of_memory(SMALLINT, "thr_setspecific: out of swap space");
1658     } else {
1659       fatal(err_msg("os::thread_local_storage_at_put: thr_setspecific failed "
1660                     "(%s)", strerror(errno)));
1661     }
1662   } else {
1663       ThreadLocalStorage::set_thread_in_slot ((Thread *) value) ;
1664   }
1665 }
1666 
1667 // This function could be called before TLS is initialized, for example, when
1668 // VM receives an async signal or when VM causes a fatal error during
1669 // initialization. Return NULL if thr_getspecific() fails.
1670 void* os::thread_local_storage_at(int index) {
1671   // %%% this is used only in threadLocalStorage.cpp
1672   void* r = NULL;
1673   return thr_getspecific((thread_key_t)index, &r) != 0 ? NULL : r;
1674 }
1675 
1676 
1677 const int NANOSECS_PER_MILLISECS = 1000000;
1678 // gethrtime can move backwards if read from one cpu and then a different cpu
1679 // getTimeNanos is guaranteed to not move backward on Solaris
1680 // local spinloop created as faster for a CAS on an int than
1681 // a CAS on a 64bit jlong. Also Atomic::cmpxchg for jlong is not
1682 // supported on sparc v8 or pre supports_cx8 intel boxes.
1683 // oldgetTimeNanos for systems which do not support CAS on 64bit jlong
1684 // i.e. sparc v8 and pre supports_cx8 (i486) intel boxes
1685 inline hrtime_t oldgetTimeNanos() {
1686   int gotlock = LOCK_INVALID;
1687   hrtime_t newtime = gethrtime();
1688 
1689   for (;;) {
1690 // grab lock for max_hrtime
1691     int curlock = max_hrtime_lock;
1692     if (curlock & LOCK_BUSY)  continue;
1693     if (gotlock = Atomic::cmpxchg(LOCK_BUSY, &max_hrtime_lock, LOCK_FREE) != LOCK_FREE) continue;
1694     if (newtime > max_hrtime) {
1695       max_hrtime = newtime;
1696     } else {
1697       newtime = max_hrtime;


1786   if (fd == -1)
1787     return false;
1788 
1789   pstatus_t status;
1790   int res = os::read(fd, (void*) &status, sizeof(pstatus_t));
1791   ::close(fd);
1792   if (res != sizeof(pstatus_t))
1793     return false;
1794 
1795   return status.pr_flags & PR_MSACCT;
1796 }
1797 
1798 double os::elapsedVTime() {
1799   return (double)gethrvtime() / (double)hrtime_hz;
1800 }
1801 
1802 // Used internally for comparisons only
1803 // getTimeMillis guaranteed to not move backwards on Solaris
1804 jlong getTimeMillis() {
1805   jlong nanotime = getTimeNanos();
1806   return (jlong)(nanotime / NANOSECS_PER_MILLISECS);
1807 }
1808 
1809 // Must return millis since Jan 1 1970 for JVM_CurrentTimeMillis
1810 jlong os::javaTimeMillis() {
1811   timeval t;
1812   if (gettimeofday( &t, NULL) == -1)
1813     fatal(err_msg("os::javaTimeMillis: gettimeofday (%s)", strerror(errno)));
1814   return jlong(t.tv_sec) * 1000  +  jlong(t.tv_usec) / 1000;
1815 }
1816 
1817 jlong os::javaTimeNanos() {
1818   return (jlong)getTimeNanos();
1819 }
1820 
1821 void os::javaTimeNanos_info(jvmtiTimerInfo *info_ptr) {
1822   info_ptr->max_value = ALL_64_BITS;      // gethrtime() uses all 64 bits
1823   info_ptr->may_skip_backward = false;    // not subject to resetting or drifting
1824   info_ptr->may_skip_forward = false;     // not subject to resetting or drifting
1825   info_ptr->kind = JVMTI_TIMER_ELAPSED;   // elapsed not CPU time
1826 }


6047        status = os::Solaris::cond_signal(_cond);
6048        assert_status(status == 0, status, "cond_signal");
6049      }
6050   }
6051 }
6052 
6053 // JSR166
6054 // -------------------------------------------------------
6055 
6056 /*
6057  * The solaris and linux implementations of park/unpark are fairly
6058  * conservative for now, but can be improved. They currently use a
6059  * mutex/condvar pair, plus _counter.
6060  * Park decrements _counter if > 0, else does a condvar wait.  Unpark
6061  * sets count to 1 and signals condvar.  Only one thread ever waits
6062  * on the condvar. Contention seen when trying to park implies that someone
6063  * is unparking you, so don't wait. And spurious returns are fine, so there
6064  * is no need to track notifications.
6065  */
6066 
6067 #define NANOSECS_PER_SEC 1000000000
6068 #define NANOSECS_PER_MILLISEC 1000000
6069 #define MAX_SECS 100000000
6070 
6071 /*
6072  * This code is common to linux and solaris and will be moved to a
6073  * common place in dolphin.
6074  *
6075  * The passed in time value is either a relative time in nanoseconds
6076  * or an absolute time in milliseconds. Either way it has to be unpacked
6077  * into suitable seconds and nanoseconds components and stored in the
6078  * given timespec structure.
6079  * Given time is a 64-bit value and the time_t used in the timespec is only
6080  * a signed-32-bit value (except on 64-bit Linux) we have to watch for
6081  * overflow if times way in the future are given. Further on Solaris versions
6082  * prior to 10 there is a restriction (see cond_timedwait) that the specified
6083  * number of seconds, in abstime, is less than current_time  + 100,000,000.
6084  * As it will be 28 years before "now + 100000000" will overflow we can
6085  * ignore overflow and just impose a hard-limit on seconds using the value
6086  * of "now + 100,000,000". This places a limit on the timeout of about 3.17
6087  * years from "now".
6088  */
6089 static void unpackTime(timespec* absTime, bool isAbsolute, jlong time) {
6090   assert (time > 0, "convertTime");




1657        vm_exit_out_of_memory(SMALLINT, "thr_setspecific: out of swap space");
1658     } else {
1659       fatal(err_msg("os::thread_local_storage_at_put: thr_setspecific failed "
1660                     "(%s)", strerror(errno)));
1661     }
1662   } else {
1663       ThreadLocalStorage::set_thread_in_slot ((Thread *) value) ;
1664   }
1665 }
1666 
1667 // This function could be called before TLS is initialized, for example, when
1668 // VM receives an async signal or when VM causes a fatal error during
1669 // initialization. Return NULL if thr_getspecific() fails.
1670 void* os::thread_local_storage_at(int index) {
1671   // %%% this is used only in threadLocalStorage.cpp
1672   void* r = NULL;
1673   return thr_getspecific((thread_key_t)index, &r) != 0 ? NULL : r;
1674 }
1675 
1676 

1677 // gethrtime can move backwards if read from one cpu and then a different cpu
1678 // getTimeNanos is guaranteed to not move backward on Solaris
1679 // local spinloop created as faster for a CAS on an int than
1680 // a CAS on a 64bit jlong. Also Atomic::cmpxchg for jlong is not
1681 // supported on sparc v8 or pre supports_cx8 intel boxes.
1682 // oldgetTimeNanos for systems which do not support CAS on 64bit jlong
1683 // i.e. sparc v8 and pre supports_cx8 (i486) intel boxes
1684 inline hrtime_t oldgetTimeNanos() {
1685   int gotlock = LOCK_INVALID;
1686   hrtime_t newtime = gethrtime();
1687 
1688   for (;;) {
1689 // grab lock for max_hrtime
1690     int curlock = max_hrtime_lock;
1691     if (curlock & LOCK_BUSY)  continue;
1692     if (gotlock = Atomic::cmpxchg(LOCK_BUSY, &max_hrtime_lock, LOCK_FREE) != LOCK_FREE) continue;
1693     if (newtime > max_hrtime) {
1694       max_hrtime = newtime;
1695     } else {
1696       newtime = max_hrtime;


1785   if (fd == -1)
1786     return false;
1787 
1788   pstatus_t status;
1789   int res = os::read(fd, (void*) &status, sizeof(pstatus_t));
1790   ::close(fd);
1791   if (res != sizeof(pstatus_t))
1792     return false;
1793 
1794   return status.pr_flags & PR_MSACCT;
1795 }
1796 
1797 double os::elapsedVTime() {
1798   return (double)gethrvtime() / (double)hrtime_hz;
1799 }
1800 
1801 // Used internally for comparisons only
1802 // getTimeMillis guaranteed to not move backwards on Solaris
1803 jlong getTimeMillis() {
1804   jlong nanotime = getTimeNanos();
1805   return (jlong)(nanotime / NANOSECS_PER_MILLISEC);
1806 }
1807 
1808 // Must return millis since Jan 1 1970 for JVM_CurrentTimeMillis
1809 jlong os::javaTimeMillis() {
1810   timeval t;
1811   if (gettimeofday( &t, NULL) == -1)
1812     fatal(err_msg("os::javaTimeMillis: gettimeofday (%s)", strerror(errno)));
1813   return jlong(t.tv_sec) * 1000  +  jlong(t.tv_usec) / 1000;
1814 }
1815 
1816 jlong os::javaTimeNanos() {
1817   return (jlong)getTimeNanos();
1818 }
1819 
1820 void os::javaTimeNanos_info(jvmtiTimerInfo *info_ptr) {
1821   info_ptr->max_value = ALL_64_BITS;      // gethrtime() uses all 64 bits
1822   info_ptr->may_skip_backward = false;    // not subject to resetting or drifting
1823   info_ptr->may_skip_forward = false;     // not subject to resetting or drifting
1824   info_ptr->kind = JVMTI_TIMER_ELAPSED;   // elapsed not CPU time
1825 }


6046        status = os::Solaris::cond_signal(_cond);
6047        assert_status(status == 0, status, "cond_signal");
6048      }
6049   }
6050 }
6051 
6052 // JSR166
6053 // -------------------------------------------------------
6054 
6055 /*
6056  * The solaris and linux implementations of park/unpark are fairly
6057  * conservative for now, but can be improved. They currently use a
6058  * mutex/condvar pair, plus _counter.
6059  * Park decrements _counter if > 0, else does a condvar wait.  Unpark
6060  * sets count to 1 and signals condvar.  Only one thread ever waits
6061  * on the condvar. Contention seen when trying to park implies that someone
6062  * is unparking you, so don't wait. And spurious returns are fine, so there
6063  * is no need to track notifications.
6064  */
6065 


6066 #define MAX_SECS 100000000

6067 /*
6068  * This code is common to linux and solaris and will be moved to a
6069  * common place in dolphin.
6070  *
6071  * The passed in time value is either a relative time in nanoseconds
6072  * or an absolute time in milliseconds. Either way it has to be unpacked
6073  * into suitable seconds and nanoseconds components and stored in the
6074  * given timespec structure.
6075  * Given time is a 64-bit value and the time_t used in the timespec is only
6076  * a signed-32-bit value (except on 64-bit Linux) we have to watch for
6077  * overflow if times way in the future are given. Further on Solaris versions
6078  * prior to 10 there is a restriction (see cond_timedwait) that the specified
6079  * number of seconds, in abstime, is less than current_time  + 100,000,000.
6080  * As it will be 28 years before "now + 100000000" will overflow we can
6081  * ignore overflow and just impose a hard-limit on seconds using the value
6082  * of "now + 100,000,000". This places a limit on the timeout of about 3.17
6083  * years from "now".
6084  */
6085 static void unpackTime(timespec* absTime, bool isAbsolute, jlong time) {
6086   assert (time > 0, "convertTime");