Mercurial > hg > graal-jvmci-8
comparison src/os/bsd/vm/os_bsd.cpp @ 17924:917873d2983d
8040140: System.nanoTime() is slow and non-monotonic on OS X
Reviewed-by: sspitsyn, shade, dholmes, acorn
author | sla |
---|---|
date | Fri, 25 Apr 2014 07:40:33 +0200 |
parents | 6048424d3865 |
children | 78bbf4d43a14 |
comparison
equal
deleted
inserted
replaced
17923:a062c3691003 | 17924:917873d2983d |
---|---|
125 #define LARGEPAGES_BIT (1 << 6) | 125 #define LARGEPAGES_BIT (1 << 6) |
126 //////////////////////////////////////////////////////////////////////////////// | 126 //////////////////////////////////////////////////////////////////////////////// |
127 // global variables | 127 // global variables |
128 julong os::Bsd::_physical_memory = 0; | 128 julong os::Bsd::_physical_memory = 0; |
129 | 129 |
130 | 130 #ifdef __APPLE__ |
131 mach_timebase_info_data_t os::Bsd::_timebase_info = {0, 0}; | |
132 volatile uint64_t os::Bsd::_max_abstime = 0; | |
133 #else | |
131 int (*os::Bsd::_clock_gettime)(clockid_t, struct timespec *) = NULL; | 134 int (*os::Bsd::_clock_gettime)(clockid_t, struct timespec *) = NULL; |
135 #endif | |
132 pthread_t os::Bsd::_main_thread; | 136 pthread_t os::Bsd::_main_thread; |
133 int os::Bsd::_page_size = -1; | 137 int os::Bsd::_page_size = -1; |
134 | 138 |
135 static jlong initial_time_count=0; | 139 static jlong initial_time_count=0; |
136 | 140 |
984 int status = gettimeofday(&time, NULL); | 988 int status = gettimeofday(&time, NULL); |
985 assert(status != -1, "bsd error"); | 989 assert(status != -1, "bsd error"); |
986 return jlong(time.tv_sec) * 1000 + jlong(time.tv_usec / 1000); | 990 return jlong(time.tv_sec) * 1000 + jlong(time.tv_usec / 1000); |
987 } | 991 } |
988 | 992 |
993 #ifndef __APPLE__ | |
989 #ifndef CLOCK_MONOTONIC | 994 #ifndef CLOCK_MONOTONIC |
990 #define CLOCK_MONOTONIC (1) | 995 #define CLOCK_MONOTONIC (1) |
991 #endif | 996 #endif |
997 #endif | |
992 | 998 |
993 #ifdef __APPLE__ | 999 #ifdef __APPLE__ |
994 void os::Bsd::clock_init() { | 1000 void os::Bsd::clock_init() { |
995 // XXXDARWIN: Investigate replacement monotonic clock | 1001 mach_timebase_info(&_timebase_info); |
996 } | 1002 } |
997 #else | 1003 #else |
998 void os::Bsd::clock_init() { | 1004 void os::Bsd::clock_init() { |
999 struct timespec res; | 1005 struct timespec res; |
1000 struct timespec tp; | 1006 struct timespec tp; |
1005 } | 1011 } |
1006 } | 1012 } |
1007 #endif | 1013 #endif |
1008 | 1014 |
1009 | 1015 |
1016 #ifdef __APPLE__ | |
1017 | |
1018 jlong os::javaTimeNanos() { | |
1019 const uint64_t tm = mach_absolute_time(); | |
1020 const uint64_t now = (tm * Bsd::_timebase_info.numer) / Bsd::_timebase_info.denom; | |
1021 const uint64_t prev = Bsd::_max_abstime; | |
1022 if (now <= prev) { | |
1023 return prev; // same or retrograde time; | |
1024 } | |
1025 const uint64_t obsv = Atomic::cmpxchg(now, (volatile jlong*)&Bsd::_max_abstime, prev); | |
1026 assert(obsv >= prev, "invariant"); // Monotonicity | |
1027 // If the CAS succeeded then we're done and return "now". | |
1028 // If the CAS failed and the observed value "obsv" is >= now then | |
1029 // we should return "obsv". If the CAS failed and now > obsv > prv then | |
1030 // some other thread raced this thread and installed a new value, in which case | |
1031 // we could either (a) retry the entire operation, (b) retry trying to install now | |
1032 // or (c) just return obsv. We use (c). No loop is required although in some cases | |
1033 // we might discard a higher "now" value in deference to a slightly lower but freshly | |
1034 // installed obsv value. That's entirely benign -- it admits no new orderings compared | |
1035 // to (a) or (b) -- and greatly reduces coherence traffic. | |
1036 // We might also condition (c) on the magnitude of the delta between obsv and now. | |
1037 // Avoiding excessive CAS operations to hot RW locations is critical. | |
1038 // See https://blogs.oracle.com/dave/entry/cas_and_cache_trivia_invalidate | |
1039 return (prev == obsv) ? now : obsv; | |
1040 } | |
1041 | |
1042 #else // __APPLE__ | |
1043 | |
1010 jlong os::javaTimeNanos() { | 1044 jlong os::javaTimeNanos() { |
1011 if (Bsd::supports_monotonic_clock()) { | 1045 if (Bsd::supports_monotonic_clock()) { |
1012 struct timespec tp; | 1046 struct timespec tp; |
1013 int status = Bsd::clock_gettime(CLOCK_MONOTONIC, &tp); | 1047 int status = Bsd::_clock_gettime(CLOCK_MONOTONIC, &tp); |
1014 assert(status == 0, "gettime error"); | 1048 assert(status == 0, "gettime error"); |
1015 jlong result = jlong(tp.tv_sec) * (1000 * 1000 * 1000) + jlong(tp.tv_nsec); | 1049 jlong result = jlong(tp.tv_sec) * (1000 * 1000 * 1000) + jlong(tp.tv_nsec); |
1016 return result; | 1050 return result; |
1017 } else { | 1051 } else { |
1018 timeval time; | 1052 timeval time; |
1020 assert(status != -1, "bsd error"); | 1054 assert(status != -1, "bsd error"); |
1021 jlong usecs = jlong(time.tv_sec) * (1000 * 1000) + jlong(time.tv_usec); | 1055 jlong usecs = jlong(time.tv_sec) * (1000 * 1000) + jlong(time.tv_usec); |
1022 return 1000 * usecs; | 1056 return 1000 * usecs; |
1023 } | 1057 } |
1024 } | 1058 } |
1059 | |
1060 #endif // __APPLE__ | |
1025 | 1061 |
1026 void os::javaTimeNanos_info(jvmtiTimerInfo *info_ptr) { | 1062 void os::javaTimeNanos_info(jvmtiTimerInfo *info_ptr) { |
1027 if (Bsd::supports_monotonic_clock()) { | 1063 if (Bsd::supports_monotonic_clock()) { |
1028 info_ptr->max_value = ALL_64_BITS; | 1064 info_ptr->max_value = ALL_64_BITS; |
1029 | 1065 |