From 606b421c43c4e12de79d9466bef517c0bc81f6f2 Mon Sep 17 00:00:00 2001 From: kvn Date: Sun, 26 Jul 2009 16:40:14 -0700 Subject: [PATCH] 6863420: os::javaTimeNanos() go backward on Solaris x86 Summary: Use new atomic long load method Atomic::load() to load max_hrtime. Reviewed-by: never, ysr, johnc, phh, dcubed, acorn --- src/os/solaris/vm/os_solaris.cpp | 3 +- .../vm/atomic_solaris_sparc.inline.hpp | 2 + .../vm/atomic_solaris_x86.inline.hpp | 11 +++ src/os_cpu/solaris_x86/vm/solaris_x86_32.il | 9 ++ src/share/vm/runtime/atomic.hpp | 2 + test/compiler/6863420/Test.java | 91 +++++++++++++++++++ 6 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 test/compiler/6863420/Test.java diff --git a/src/os/solaris/vm/os_solaris.cpp b/src/os/solaris/vm/os_solaris.cpp index ce201c3fa..13abbf9d4 100644 --- a/src/os/solaris/vm/os_solaris.cpp +++ b/src/os/solaris/vm/os_solaris.cpp @@ -1643,7 +1643,8 @@ inline hrtime_t oldgetTimeNanos() { inline hrtime_t getTimeNanos() { if (VM_Version::supports_cx8()) { const hrtime_t now = gethrtime(); - const hrtime_t prev = max_hrtime; + // Use atomic long load since 32-bit x86 uses 2 registers to keep long. + const hrtime_t prev = Atomic::load((volatile jlong*)&max_hrtime); if (now <= prev) return prev; // same or retrograde time; const hrtime_t obsv = Atomic::cmpxchg(now, (volatile jlong*)&max_hrtime, prev); assert(obsv >= prev, "invariant"); // Monotonicity diff --git a/src/os_cpu/solaris_sparc/vm/atomic_solaris_sparc.inline.hpp b/src/os_cpu/solaris_sparc/vm/atomic_solaris_sparc.inline.hpp index e3ee2bc23..d4ff20061 100644 --- a/src/os_cpu/solaris_sparc/vm/atomic_solaris_sparc.inline.hpp +++ b/src/os_cpu/solaris_sparc/vm/atomic_solaris_sparc.inline.hpp @@ -46,6 +46,8 @@ inline void Atomic::dec (volatile jint* dest) { (void)add (-1, dest); inline void Atomic::dec_ptr(volatile intptr_t* dest) { (void)add_ptr(-1, dest); } inline void Atomic::dec_ptr(volatile void* dest) { (void)add_ptr(-1, dest); } +inline jlong Atomic::load(volatile jlong* src) { return *src; } + #ifdef _GNU_SOURCE inline jint Atomic::add (jint add_value, volatile jint* dest) { diff --git a/src/os_cpu/solaris_x86/vm/atomic_solaris_x86.inline.hpp b/src/os_cpu/solaris_x86/vm/atomic_solaris_x86.inline.hpp index 469e01800..d127d6ea9 100644 --- a/src/os_cpu/solaris_x86/vm/atomic_solaris_x86.inline.hpp +++ b/src/os_cpu/solaris_x86/vm/atomic_solaris_x86.inline.hpp @@ -99,6 +99,8 @@ inline void* Atomic::cmpxchg_ptr(void* exchange_value, volatile void* return (void*)_Atomic_cmpxchg_long((jlong)exchange_value, (volatile jlong*)dest, (jlong)compare_value, (int) os::is_MP()); } +inline jlong Atomic::load(volatile jlong* src) { return *src; } + #else // !AMD64 inline intptr_t Atomic::add_ptr(intptr_t add_value, volatile intptr_t* dest) { @@ -131,6 +133,15 @@ inline intptr_t Atomic::cmpxchg_ptr(intptr_t exchange_value, volatile intptr_t* inline void* Atomic::cmpxchg_ptr(void* exchange_value, volatile void* dest, void* compare_value) { return (void*)cmpxchg((jint)exchange_value, (volatile jint*)dest, (jint)compare_value); } + +extern "C" void _Atomic_load_long(volatile jlong* src, volatile jlong* dst); + +inline jlong Atomic::load(volatile jlong* src) { + volatile jlong dest; + _Atomic_load_long(src, &dest); + return dest; +} + #endif // AMD64 #ifdef _GNU_SOURCE diff --git a/src/os_cpu/solaris_x86/vm/solaris_x86_32.il b/src/os_cpu/solaris_x86/vm/solaris_x86_32.il index 5ac1d25a7..0ffd87d85 100644 --- a/src/os_cpu/solaris_x86/vm/solaris_x86_32.il +++ b/src/os_cpu/solaris_x86/vm/solaris_x86_32.il @@ -97,6 +97,15 @@ popl %ebx .end + // Support for void Atomic::load(volatile jlong* src, volatile jlong* dest). + .inline _Atomic_load_long,2 + movl 0(%esp), %eax // src + fildll (%eax) + movl 4(%esp), %eax // dest + fistpll (%eax) + .end + + // Support for OrderAccess::acquire() .inline _OrderAccess_acquire,0 movl 0(%esp), %eax diff --git a/src/share/vm/runtime/atomic.hpp b/src/share/vm/runtime/atomic.hpp index c54103cbd..9c8ba27ba 100644 --- a/src/share/vm/runtime/atomic.hpp +++ b/src/share/vm/runtime/atomic.hpp @@ -39,6 +39,8 @@ class Atomic : AllStatic { static void store_ptr(intptr_t store_value, volatile intptr_t* dest); static void store_ptr(void* store_value, volatile void* dest); + static jlong load(volatile jlong* src); + // Atomically add to a location, return updated value static jint add (jint add_value, volatile jint* dest); static intptr_t add_ptr(intptr_t add_value, volatile intptr_t* dest); diff --git a/test/compiler/6863420/Test.java b/test/compiler/6863420/Test.java new file mode 100644 index 000000000..58a0e8123 --- /dev/null +++ b/test/compiler/6863420/Test.java @@ -0,0 +1,91 @@ +/* + * Copyright 2009 D.E. Shaw. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +/** + * @test + * @bug 6863420 + * @summary os::javaTimeNanos() go backward on Solaris x86 + * + * @run main/othervm Test + */ + +public class Test { + static long value = 0; + static boolean got_backward_time = false; + + public static void main(String args[]) { + final int count = 100000; + + for (int numThreads = 1; numThreads <= 32; numThreads++) { + final int numRuns = 1; + for (int t=1; t <= numRuns; t++) { + final int curRun = t; + + System.out.println("Spawning " + numThreads + " threads"); + final Thread threads[] = new Thread[numThreads]; + for (int i = 0; i < threads.length; i++) { + Runnable thread = + new Runnable() { + public void run() { + for (long l = 0; l < 100000; l++) { + final long start = System.nanoTime(); + if (value == 12345678) { + System.out.println("Wow!"); + } + final long end = System.nanoTime(); + final long time = end - start; + value += time; + if (time < 0) { + System.out.println( + "Backwards: " + + "start=" + start + " " + + "end=" + end + " " + + "time= " + time + ); + got_backward_time = true; + } + } + } + }; + threads[i] = new Thread(thread, "Thread" + i); + } + for (int i = 0; i < threads.length; i++) { + threads[i].start(); + } + for (int i = 0; i < threads.length; i++) { + try { + threads[i].join(); + } + catch (InterruptedException e) { + continue; + } + } + } + } + + if (got_backward_time) { + System.exit(97); + } + } +} -- GitLab