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:

Split Close
Expand all
Collapse all
          --- old/src/os/linux/vm/os_linux.cpp
          +++ new/src/os/linux/vm/os_linux.cpp
↓ open down ↓ 119 lines elided ↑ open up ↑
 120  120  # include <sys/shm.h>
 121  121  # include <link.h>
 122  122  # include <stdint.h>
 123  123  # include <inttypes.h>
 124  124  # include <sys/ioctl.h>
 125  125  
 126  126  #define MAX_PATH    (2 * K)
 127  127  
 128  128  // for timer info max values which include all bits
 129  129  #define ALL_64_BITS CONST64(0xFFFFFFFFFFFFFFFF)
 130      -#define SEC_IN_NANOSECS  1000000000LL
 131  130  
 132  131  #define LARGEPAGES_BIT (1 << 6)
 133  132  ////////////////////////////////////////////////////////////////////////////////
 134  133  // global variables
 135  134  julong os::Linux::_physical_memory = 0;
 136  135  
 137  136  address   os::Linux::_initial_thread_stack_bottom = NULL;
 138  137  uintptr_t os::Linux::_initial_thread_stack_size   = 0;
 139  138  
 140  139  int (*os::Linux::_clock_gettime)(clockid_t, struct timespec *) = NULL;
↓ open down ↓ 3111 lines elided ↑ open up ↑
3252 3251  size_t os::read(int fd, void *buf, unsigned int nBytes) {
3253 3252    return ::read(fd, buf, nBytes);
3254 3253  }
3255 3254  
3256 3255  // TODO-FIXME: reconcile Solaris' os::sleep with the linux variation.
3257 3256  // Solaris uses poll(), linux uses park().
3258 3257  // Poll() is likely a better choice, assuming that Thread.interrupt()
3259 3258  // generates a SIGUSRx signal. Note that SIGUSR1 can interfere with
3260 3259  // SIGSEGV, see 4355769.
3261 3260  
3262      -const int NANOSECS_PER_MILLISECS = 1000000;
3263      -
3264 3261  int os::sleep(Thread* thread, jlong millis, bool interruptible) {
3265 3262    assert(thread == Thread::current(),  "thread consistency check");
3266 3263  
3267 3264    ParkEvent * const slp = thread->_SleepEvent ;
3268 3265    slp->reset() ;
3269 3266    OrderAccess::fence() ;
3270 3267  
3271 3268    if (interruptible) {
3272 3269      jlong prevtime = javaTimeNanos();
3273 3270  
↓ open down ↓ 2 lines elided ↑ open up ↑
3276 3273          return OS_INTRPT;
3277 3274        }
3278 3275  
3279 3276        jlong newtime = javaTimeNanos();
3280 3277  
3281 3278        if (newtime - prevtime < 0) {
3282 3279          // time moving backwards, should only happen if no monotonic clock
3283 3280          // not a guarantee() because JVM should not abort on kernel/glibc bugs
3284 3281          assert(!Linux::supports_monotonic_clock(), "time moving backwards");
3285 3282        } else {
3286      -        millis -= (newtime - prevtime) / NANOSECS_PER_MILLISECS;
     3283 +        millis -= (newtime - prevtime) / NANOSECS_PER_MILLISEC;
3287 3284        }
3288 3285  
3289 3286        if(millis <= 0) {
3290 3287          return OS_OK;
3291 3288        }
3292 3289  
3293 3290        prevtime = newtime;
3294 3291  
3295 3292        {
3296 3293          assert(thread->is_Java_thread(), "sanity check");
↓ open down ↓ 18 lines elided ↑ open up ↑
3315 3312      for (;;) {
3316 3313        // It'd be nice to avoid the back-to-back javaTimeNanos() calls on
3317 3314        // the 1st iteration ...
3318 3315        jlong newtime = javaTimeNanos();
3319 3316  
3320 3317        if (newtime - prevtime < 0) {
3321 3318          // time moving backwards, should only happen if no monotonic clock
3322 3319          // not a guarantee() because JVM should not abort on kernel/glibc bugs
3323 3320          assert(!Linux::supports_monotonic_clock(), "time moving backwards");
3324 3321        } else {
3325      -        millis -= (newtime - prevtime) / NANOSECS_PER_MILLISECS;
     3322 +        millis -= (newtime - prevtime) / NANOSECS_PER_MILLISEC;
3326 3323        }
3327 3324  
3328 3325        if(millis <= 0) break ;
3329 3326  
3330 3327        prevtime = newtime;
3331 3328        slp->park(millis);
3332 3329      }
3333 3330      return OS_OK ;
3334 3331    }
3335 3332  }
↓ open down ↓ 581 lines elided ↑ open up ↑
3917 3914  // POSIX compliant clocks are implemented in the kernels 2.6.16+.
3918 3915  // It might work on 2.6.10+ with a special kernel/glibc patch.
3919 3916  // For reference, please, see IEEE Std 1003.1-2004:
3920 3917  //   http://www.unix.org/single_unix_specification
3921 3918  
3922 3919  jlong os::Linux::fast_thread_cpu_time(clockid_t clockid) {
3923 3920    struct timespec tp;
3924 3921    int rc = os::Linux::clock_gettime(clockid, &tp);
3925 3922    assert(rc == 0, "clock_gettime is expected to return 0 code");
3926 3923  
3927      -  return (tp.tv_sec * SEC_IN_NANOSECS) + tp.tv_nsec;
     3924 +  return (tp.tv_sec * NANOSECS_PER_SEC) + tp.tv_nsec;
3928 3925  }
3929 3926  
3930 3927  /////
3931 3928  // glibc on Linux platform uses non-documented flag
3932 3929  // to indicate, that some special sort of signal
3933 3930  // trampoline is used.
3934 3931  // We will never set this flag, and we should
3935 3932  // ignore this flag in our diagnostic
3936 3933  #ifdef SIGNIFICANT_SIGNAL_MASK
3937 3934  #undef SIGNIFICANT_SIGNAL_MASK
↓ open down ↓ 1220 lines elided ↑ open up ↑
5158 5155   * The solaris and linux implementations of park/unpark are fairly
5159 5156   * conservative for now, but can be improved. They currently use a
5160 5157   * mutex/condvar pair, plus a a count.
5161 5158   * Park decrements count if > 0, else does a condvar wait.  Unpark
5162 5159   * sets count to 1 and signals condvar.  Only one thread ever waits
5163 5160   * on the condvar. Contention seen when trying to park implies that someone
5164 5161   * is unparking you, so don't wait. And spurious returns are fine, so there
5165 5162   * is no need to track notifications.
5166 5163   */
5167 5164  
5168      -
5169      -#define NANOSECS_PER_SEC 1000000000
5170      -#define NANOSECS_PER_MILLISEC 1000000
5171 5165  #define MAX_SECS 100000000
5172 5166  /*
5173 5167   * This code is common to linux and solaris and will be moved to a
5174 5168   * common place in dolphin.
5175 5169   *
5176 5170   * The passed in time value is either a relative time in nanoseconds
5177 5171   * or an absolute time in milliseconds. Either way it has to be unpacked
5178 5172   * into suitable seconds and nanoseconds components and stored in the
5179 5173   * given timespec structure.
5180 5174   * Given time is a 64-bit value and the time_t used in the timespec is only
↓ open down ↓ 362 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX