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/bsd/vm/os_bsd.cpp
          +++ new/src/os/bsd/vm/os_bsd.cpp
↓ open down ↓ 142 lines elided ↑ open up ↑
 143  143  #endif
 144  144  
 145  145  #ifndef MAP_ANONYMOUS
 146  146  #define MAP_ANONYMOUS MAP_ANON
 147  147  #endif
 148  148  
 149  149  #define MAX_PATH    (2 * K)
 150  150  
 151  151  // for timer info max values which include all bits
 152  152  #define ALL_64_BITS CONST64(0xFFFFFFFFFFFFFFFF)
 153      -#define SEC_IN_NANOSECS  1000000000LL
 154  153  
 155  154  #define LARGEPAGES_BIT (1 << 6)
 156  155  ////////////////////////////////////////////////////////////////////////////////
 157  156  // global variables
 158  157  julong os::Bsd::_physical_memory = 0;
 159  158  
 160  159  #ifndef _ALLBSD_SOURCE
 161  160  address   os::Bsd::_initial_thread_stack_bottom = NULL;
 162  161  uintptr_t os::Bsd::_initial_thread_stack_size   = 0;
 163  162  #endif
↓ open down ↓ 3274 lines elided ↑ open up ↑
3438 3437  size_t os::read(int fd, void *buf, unsigned int nBytes) {
3439 3438    RESTARTABLE_RETURN_INT(::read(fd, buf, nBytes));
3440 3439  }
3441 3440  
3442 3441  // TODO-FIXME: reconcile Solaris' os::sleep with the bsd variation.
3443 3442  // Solaris uses poll(), bsd uses park().
3444 3443  // Poll() is likely a better choice, assuming that Thread.interrupt()
3445 3444  // generates a SIGUSRx signal. Note that SIGUSR1 can interfere with
3446 3445  // SIGSEGV, see 4355769.
3447 3446  
3448      -const int NANOSECS_PER_MILLISECS = 1000000;
3449      -
3450 3447  int os::sleep(Thread* thread, jlong millis, bool interruptible) {
3451 3448    assert(thread == Thread::current(),  "thread consistency check");
3452 3449  
3453 3450    ParkEvent * const slp = thread->_SleepEvent ;
3454 3451    slp->reset() ;
3455 3452    OrderAccess::fence() ;
3456 3453  
3457 3454    if (interruptible) {
3458 3455      jlong prevtime = javaTimeNanos();
3459 3456  
↓ open down ↓ 2 lines elided ↑ open up ↑
3462 3459          return OS_INTRPT;
3463 3460        }
3464 3461  
3465 3462        jlong newtime = javaTimeNanos();
3466 3463  
3467 3464        if (newtime - prevtime < 0) {
3468 3465          // time moving backwards, should only happen if no monotonic clock
3469 3466          // not a guarantee() because JVM should not abort on kernel/glibc bugs
3470 3467          assert(!Bsd::supports_monotonic_clock(), "time moving backwards");
3471 3468        } else {
3472      -        millis -= (newtime - prevtime) / NANOSECS_PER_MILLISECS;
     3469 +        millis -= (newtime - prevtime) / NANOSECS_PER_MILLISEC;
3473 3470        }
3474 3471  
3475 3472        if(millis <= 0) {
3476 3473          return OS_OK;
3477 3474        }
3478 3475  
3479 3476        prevtime = newtime;
3480 3477  
3481 3478        {
3482 3479          assert(thread->is_Java_thread(), "sanity check");
↓ open down ↓ 18 lines elided ↑ open up ↑
3501 3498      for (;;) {
3502 3499        // It'd be nice to avoid the back-to-back javaTimeNanos() calls on
3503 3500        // the 1st iteration ...
3504 3501        jlong newtime = javaTimeNanos();
3505 3502  
3506 3503        if (newtime - prevtime < 0) {
3507 3504          // time moving backwards, should only happen if no monotonic clock
3508 3505          // not a guarantee() because JVM should not abort on kernel/glibc bugs
3509 3506          assert(!Bsd::supports_monotonic_clock(), "time moving backwards");
3510 3507        } else {
3511      -        millis -= (newtime - prevtime) / NANOSECS_PER_MILLISECS;
     3508 +        millis -= (newtime - prevtime) / NANOSECS_PER_MILLISEC;
3512 3509        }
3513 3510  
3514 3511        if(millis <= 0) break ;
3515 3512  
3516 3513        prevtime = newtime;
3517 3514        slp->park(millis);
3518 3515      }
3519 3516      return OS_OK ;
3520 3517    }
3521 3518  }
↓ open down ↓ 668 lines elided ↑ open up ↑
4190 4187  // POSIX compliant clocks are implemented in the kernels 2.6.16+.
4191 4188  // It might work on 2.6.10+ with a special kernel/glibc patch.
4192 4189  // For reference, please, see IEEE Std 1003.1-2004:
4193 4190  //   http://www.unix.org/single_unix_specification
4194 4191  
4195 4192  jlong os::Bsd::fast_thread_cpu_time(clockid_t clockid) {
4196 4193    struct timespec tp;
4197 4194    int rc = os::Bsd::clock_gettime(clockid, &tp);
4198 4195    assert(rc == 0, "clock_gettime is expected to return 0 code");
4199 4196  
4200      -  return (tp.tv_sec * SEC_IN_NANOSECS) + tp.tv_nsec;
     4197 +  return (tp.tv_sec * NANOSECS_PER_SEC) + tp.tv_nsec;
4201 4198  }
4202 4199  #endif
4203 4200  
4204 4201  /////
4205 4202  // glibc on Bsd platform uses non-documented flag
4206 4203  // to indicate, that some special sort of signal
4207 4204  // trampoline is used.
4208 4205  // We will never set this flag, and we should
4209 4206  // ignore this flag in our diagnostic
4210 4207  #ifdef SIGNIFICANT_SIGNAL_MASK
↓ open down ↓ 1304 lines elided ↑ open up ↑
5515 5512   * The solaris and bsd implementations of park/unpark are fairly
5516 5513   * conservative for now, but can be improved. They currently use a
5517 5514   * mutex/condvar pair, plus a a count.
5518 5515   * Park decrements count if > 0, else does a condvar wait.  Unpark
5519 5516   * sets count to 1 and signals condvar.  Only one thread ever waits
5520 5517   * on the condvar. Contention seen when trying to park implies that someone
5521 5518   * is unparking you, so don't wait. And spurious returns are fine, so there
5522 5519   * is no need to track notifications.
5523 5520   */
5524 5521  
5525      -
5526      -#define NANOSECS_PER_SEC 1000000000
5527      -#define NANOSECS_PER_MILLISEC 1000000
5528 5522  #define MAX_SECS 100000000
5529 5523  /*
5530 5524   * This code is common to bsd and solaris and will be moved to a
5531 5525   * common place in dolphin.
5532 5526   *
5533 5527   * The passed in time value is either a relative time in nanoseconds
5534 5528   * or an absolute time in milliseconds. Either way it has to be unpacked
5535 5529   * into suitable seconds and nanoseconds components and stored in the
5536 5530   * given timespec structure.
5537 5531   * Given time is a 64-bit value and the time_t used in the timespec is only
↓ open down ↓ 282 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX