--- old/make/solaris/makefiles/vm.make 2015-06-22 16:01:34.284880601 +0200 +++ new/make/solaris/makefiles/vm.make 2015-06-22 16:01:34.136875556 +0200 @@ -143,7 +143,7 @@ LIBS += -lsocket -lsched -ldl $(LIBM) -lthread -lc -ldemangle endif # sparcWorks -LIBS += -lkstat +LIBS += -lkstat -lrt # By default, link the *.o into the library, not the executable. LINK_INTO$(LINK_INTO) = LIBJVM --- old/src/os/bsd/vm/os_bsd.cpp 2015-06-22 16:01:34.536889191 +0200 +++ new/src/os/bsd/vm/os_bsd.cpp 2015-06-22 16:01:34.392884283 +0200 @@ -66,6 +66,7 @@ #include "utilities/defaultStream.hpp" #include "utilities/events.hpp" #include "utilities/growableArray.hpp" +#include "utilities/semaphore.hpp" #include "utilities/vmError.hpp" // put OS-includes here @@ -1941,119 +1942,103 @@ // Bsd(POSIX) specific hand shaking semaphore. #ifdef __APPLE__ -typedef semaphore_t os_semaphore_t; - #define SEM_INIT(sem, value) semaphore_create(mach_task_self(), &sem, SYNC_POLICY_FIFO, value) #define SEM_WAIT(sem) semaphore_wait(sem) #define SEM_POST(sem) semaphore_signal(sem) #define SEM_DESTROY(sem) semaphore_destroy(mach_task_self(), sem) #else -typedef sem_t os_semaphore_t; - #define SEM_INIT(sem, value) sem_init(&sem, 0, value) #define SEM_WAIT(sem) sem_wait(&sem) #define SEM_POST(sem) sem_post(&sem) #define SEM_DESTROY(sem) sem_destroy(&sem) #endif -class Semaphore : public StackObj { - public: - Semaphore(); - ~Semaphore(); - void signal(); - void wait(); - bool trywait(); - bool timedwait(unsigned int sec, int nsec); - private: - jlong currenttime() const; - os_semaphore_t _semaphore; -}; +#ifdef __APPLE__ +// OS X doesn't support unamed POSIX semaphores, so the implementation in os_posix.cpp can't be used. -Semaphore::Semaphore() : _semaphore(0) { - SEM_INIT(_semaphore, 0); +Semaphore::Semaphore(uint value) : _semaphore(0) { + SEM_INIT(_semaphore, value); } Semaphore::~Semaphore() { SEM_DESTROY(_semaphore); } -void Semaphore::signal() { - SEM_POST(_semaphore); +void Semaphore::signal(uint count) { + for (uint i = 0; i < count; i++) { + SEM_POST(_semaphore); + } } void Semaphore::wait() { - SEM_WAIT(_semaphore); + while (SEM_WAIT(_semaphore) == KERN_ABORTED) { + // Semaphore was interrupted. Retry. + } } -jlong Semaphore::currenttime() const { - struct timeval tv; - gettimeofday(&tv, NULL); - return (tv.tv_sec * NANOSECS_PER_SEC) + (tv.tv_usec * 1000); -} +class BsdSemaphore : public Semaphore { + private: + static jlong currenttime() { + struct timeval tv; + gettimeofday(&tv, NULL); + return (tv.tv_sec * NANOSECS_PER_SEC) + (tv.tv_usec * 1000); + } -#ifdef __APPLE__ -bool Semaphore::trywait() { - return timedwait(0, 0); -} + public: + BsdSemaphore(uint value = 0) : Semaphore(value) {} + + bool trywait() { + return timedwait(0, 0); + } -bool Semaphore::timedwait(unsigned int sec, int nsec) { - kern_return_t kr = KERN_ABORTED; - mach_timespec_t waitspec; - waitspec.tv_sec = sec; - waitspec.tv_nsec = nsec; + bool timedwait(unsigned int sec, int nsec) { + kern_return_t kr = KERN_ABORTED; + mach_timespec_t waitspec; + waitspec.tv_sec = sec; + waitspec.tv_nsec = nsec; - jlong starttime = currenttime(); + jlong starttime = currenttime(); - kr = semaphore_timedwait(_semaphore, waitspec); - while (kr == KERN_ABORTED) { - jlong totalwait = (sec * NANOSECS_PER_SEC) + nsec; + kr = semaphore_timedwait(_semaphore, waitspec); + while (kr == KERN_ABORTED) { + jlong totalwait = (sec * NANOSECS_PER_SEC) + nsec; - jlong current = currenttime(); - jlong passedtime = current - starttime; + jlong current = currenttime(); + jlong passedtime = current - starttime; - if (passedtime >= totalwait) { - waitspec.tv_sec = 0; - waitspec.tv_nsec = 0; - } else { - jlong waittime = totalwait - (current - starttime); - waitspec.tv_sec = waittime / NANOSECS_PER_SEC; - waitspec.tv_nsec = waittime % NANOSECS_PER_SEC; + if (passedtime >= totalwait) { + waitspec.tv_sec = 0; + waitspec.tv_nsec = 0; + } else { + jlong waittime = totalwait - (current - starttime); + waitspec.tv_sec = waittime / NANOSECS_PER_SEC; + waitspec.tv_nsec = waittime % NANOSECS_PER_SEC; + } + + kr = semaphore_timedwait(_semaphore, waitspec); } - kr = semaphore_timedwait(_semaphore, waitspec); + return kr == KERN_SUCCESS; } +}; - return kr == KERN_SUCCESS; -} +typedef BsdSemaphore OSSemaphore; #else -bool Semaphore::trywait() { - return sem_trywait(&_semaphore) == 0; -} - -bool Semaphore::timedwait(unsigned int sec, int nsec) { +struct timespec os::PosixSemaphore::create_timespec(unsigned int sec, int nsec) { struct timespec ts; unpackTime(&ts, false, (sec * NANOSECS_PER_SEC) + nsec); - while (1) { - int result = sem_timedwait(&_semaphore, &ts); - if (result == 0) { - return true; - } else if (errno == EINTR) { - continue; - } else if (errno == ETIMEDOUT) { - return false; - } else { - return false; - } - } + return ts; } +typedef os::PosixSemaphore OSSemaphore; + #endif // __APPLE__ static os_semaphore_t sig_sem; -static Semaphore sr_semaphore; +static OSSemaphore sr_semaphore; void os::signal_init_pd() { // Initialize signal structures --- old/src/os/linux/vm/os_linux.cpp 2015-06-22 16:01:34.912902008 +0200 +++ new/src/os/linux/vm/os_linux.cpp 2015-06-22 16:01:34.756896691 +0200 @@ -2393,40 +2393,7 @@ return CAST_FROM_FN_PTR(void*, UserHandler); } -class Semaphore : public StackObj { - public: - Semaphore(); - ~Semaphore(); - void signal(); - void wait(); - bool trywait(); - bool timedwait(unsigned int sec, int nsec); - private: - sem_t _semaphore; -}; - -Semaphore::Semaphore() { - sem_init(&_semaphore, 0, 0); -} - -Semaphore::~Semaphore() { - sem_destroy(&_semaphore); -} - -void Semaphore::signal() { - sem_post(&_semaphore); -} - -void Semaphore::wait() { - sem_wait(&_semaphore); -} - -bool Semaphore::trywait() { - return sem_trywait(&_semaphore) == 0; -} - -bool Semaphore::timedwait(unsigned int sec, int nsec) { - +struct timespec os::PosixSemaphore::create_timespec(unsigned int sec, int nsec) { struct timespec ts; // Semaphore's are always associated with CLOCK_REALTIME os::Linux::clock_gettime(CLOCK_REALTIME, &ts); @@ -2443,18 +2410,7 @@ } } - while (1) { - int result = sem_timedwait(&_semaphore, &ts); - if (result == 0) { - return true; - } else if (errno == EINTR) { - continue; - } else if (errno == ETIMEDOUT) { - return false; - } else { - return false; - } - } + return ts; } extern "C" { @@ -2494,7 +2450,7 @@ // Linux(POSIX) specific hand shaking semaphore. static sem_t sig_sem; -static Semaphore sr_semaphore; +static os::PosixSemaphore sr_semaphore; void os::signal_init_pd() { // Initialize signal structures --- old/src/os/posix/vm/os_posix.cpp 2015-06-22 16:01:35.264914007 +0200 +++ new/src/os/posix/vm/os_posix.cpp 2015-06-22 16:01:35.096908280 +0200 @@ -1015,3 +1015,58 @@ } } } + +#define assert_with_errno(cond, msg) \ + do { \ + int err = errno; \ + assert(cond, err_msg("%s; error='%s' (errno=%d)", msg, strerror(err), err)); \ +} while (false) + +// POSIX unamed semaphores are not supported on OS X. +#ifndef __APPLE__ + +Semaphore::Semaphore(uint value) { + int ret = sem_init(&_semaphore, 0, value); + + assert_with_errno(ret == 0, "Failed to initialize semaphore"); +} + +Semaphore::~Semaphore() { + sem_destroy(&_semaphore); +} + +void Semaphore::signal(uint count) { + for (uint i = 0; i < count; i++) { + int ret = sem_post(&_semaphore); + + assert_with_errno(ret == 0, "sem_post failed"); + } +} + +void Semaphore::wait() { + while (sem_wait(&_semaphore) == -1 && errno == EINTR) { + // Retry if the wait was interrupted by a signal. + } +} + +bool os::PosixSemaphore::trywait() { + return sem_trywait(&_semaphore) == 0; +} + +bool os::PosixSemaphore::timedwait(const struct timespec ts) { + while (true) { + int result = sem_timedwait(&_semaphore, &ts); + if (result == 0) { + return true; + } else if (errno == EINTR) { + continue; + } else if (errno == ETIMEDOUT) { + return false; + } else { + assert_with_errno(false, "timedwait failed"); + return false; + } + } +} + +#endif // __APPLE__ --- old/src/os/posix/vm/os_posix.hpp 2015-06-22 16:01:35.532923143 +0200 +++ new/src/os/posix/vm/os_posix.hpp 2015-06-22 16:01:35.380917961 +0200 @@ -89,4 +89,20 @@ sigjmp_buf _jmpbuf; }; +class PosixSemaphore : public Semaphore { + public: + PosixSemaphore(uint value = 0) : Semaphore(value) {} + + bool trywait(); + bool timedwait(unsigned int sec, int nsec) { + return timedwait(create_timespec(sec, nsec)); + } + + private: + bool timedwait(struct timespec ts); + + // OS specific implementation to create a timespec suitable for semaphores. + static struct timespec create_timespec(unsigned int set, int nsec); +}; + #endif // OS_POSIX_VM_OS_POSIX_HPP --- old/src/os/solaris/vm/os_solaris.cpp 2015-06-22 16:01:35.780931597 +0200 +++ new/src/os/solaris/vm/os_solaris.cpp 2015-06-22 16:01:35.640926824 +0200 @@ -2266,55 +2266,11 @@ return CAST_FROM_FN_PTR(void*, UserHandler); } -class Semaphore : public StackObj { - public: - Semaphore(); - ~Semaphore(); - void signal(); - void wait(); - bool trywait(); - bool timedwait(unsigned int sec, int nsec); - private: - sema_t _semaphore; -}; - - -Semaphore::Semaphore() { - sema_init(&_semaphore, 0, NULL, NULL); -} - -Semaphore::~Semaphore() { - sema_destroy(&_semaphore); -} - -void Semaphore::signal() { - sema_post(&_semaphore); -} - -void Semaphore::wait() { - sema_wait(&_semaphore); -} - -bool Semaphore::trywait() { - return sema_trywait(&_semaphore) == 0; -} - -bool Semaphore::timedwait(unsigned int sec, int nsec) { +struct timespec os::PosixSemaphore::create_timespec(unsigned int sec, int nsec) { struct timespec ts; unpackTime(&ts, false, (sec * NANOSECS_PER_SEC) + nsec); - while (1) { - int result = sema_timedwait(&_semaphore, &ts); - if (result == 0) { - return true; - } else if (errno == EINTR) { - continue; - } else if (errno == ETIME) { - return false; - } else { - return false; - } - } + return ts; } extern "C" { @@ -3714,7 +3670,7 @@ osthread->set_ucontext(context); } -static Semaphore sr_semaphore; +static os::PosixSemaphore sr_semaphore; void os::Solaris::SR_handler(Thread* thread, ucontext_t* uc) { // Save and restore errno to avoid confusing native code with EINTR --- old/src/os/windows/vm/os_windows.cpp 2015-06-22 16:01:36.120943186 +0200 +++ new/src/os/windows/vm/os_windows.cpp 2015-06-22 16:01:35.980938414 +0200 @@ -70,6 +70,7 @@ #include "utilities/defaultStream.hpp" #include "utilities/events.hpp" #include "utilities/growableArray.hpp" +#include "utilities/semaphore.hpp" #include "utilities/vmError.hpp" #ifdef _DEBUG @@ -1895,6 +1896,31 @@ return (int)error; } +Semaphore::Semaphore(uint value) { + _semaphore = ::CreateSemaphore(NULL, value, LONG_MAX, NULL); + + assert(_semaphore != NULL, err_msg("CreateSemaphore failed: %ld", GetLastError())); +} + +Semaphore::~Semaphore() { + if (_semaphore != NULL) { + ::CloseHandle(_semaphore); + } +} + +void Semaphore::signal(uint count) { + if (count > 0) { + BOOL ret = ::ReleaseSemaphore(_semaphore, count, NULL); + + assert(ret != 0, err_msg("ReleaseSemaphore failed: %d", GetLastError())); + } +} + +void Semaphore::wait() { + DWORD ret = ::WaitForSingleObject(_semaphore, INFINITE); + assert(ret == WAIT_OBJECT_0, err_msg("WaitForSingleObject failed: %d", GetLastError())); +} + // sun.misc.Signal // NOTE that this is a workaround for an apparent kernel bug where if // a signal handler for SIGBREAK is installed then that signal handler --- old/src/share/vm/prims/jni.cpp 2015-06-22 16:01:36.444954231 +0200 +++ new/src/share/vm/prims/jni.cpp 2015-06-22 16:01:36.308949595 +0200 @@ -3855,6 +3855,7 @@ unit_test_function_call // Forward declaration +void test_semaphore(); void TestOS_test(); void TestReservedSpace_test(); void TestReserveMemorySpecial_test(); @@ -3880,6 +3881,7 @@ void execute_internal_vm_tests() { if (ExecuteInternalVMTests) { tty->print_cr("Running internal VM tests"); + run_unit_test(test_semaphore()); run_unit_test(TestOS_test()); run_unit_test(TestReservedSpace_test()); run_unit_test(TestReserveMemorySpecial_test()); --- old/src/share/vm/runtime/os.hpp 2015-06-22 16:01:36.784965820 +0200 +++ new/src/share/vm/runtime/os.hpp 2015-06-22 16:01:36.624960367 +0200 @@ -28,6 +28,7 @@ #include "jvmtifiles/jvmti.h" #include "runtime/extendedPC.hpp" #include "runtime/handles.hpp" +#include "utilities/semaphore.hpp" #include "utilities/top.hpp" #ifdef TARGET_OS_FAMILY_linux # include "jvm_linux.h" --- /dev/null 2015-05-29 12:41:18.476004839 +0200 +++ new/src/os/bsd/vm/semaphore_bsd.hpp 2015-06-22 16:01:36.908970047 +0200 @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef OS_BSD_VM_SEMAPHORE_BSD_HPP +#define OS_BSD_VM_SEMAPHORE_BSD_HPP + +#include + +#ifdef __APPLE__ + typedef semaphore_t os_semaphore_t; +#else + typedef sem_t os_semaphore_t; +#endif + +#endif // OS_BSD_VM_SEMAPHORE_BSD_HPP --- /dev/null 2015-05-29 12:41:18.476004839 +0200 +++ new/src/os/posix/vm/semaphore_posix.hpp 2015-06-22 16:01:37.108976865 +0200 @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef OS_POSIX_VM_SEMAPHORE_POSIX_HPP +#define OS_POSIX_VM_SEMAPHORE_POSIX_HPP + +#include + +typedef sem_t os_semaphore_t; + +#endif // OS_POSIX_VM_SEMAPHORE_POSIX_HPP --- /dev/null 2015-05-29 12:41:18.476004839 +0200 +++ new/src/os/windows/vm/semaphore_windows.hpp 2015-06-22 16:01:37.328984364 +0200 @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef OS_WINDOWS_VM_SEMAPHORE_WINDOWS_HPP +#define OS_WINDOWS_VM_SEMAPHORE_WINDOWS_HPP + +#include + +typedef HANDLE os_semaphore_t; + +#endif // OS_WINDOWS_VM_SEMAPHORE_WINDOWS_HPP --- /dev/null 2015-05-29 12:41:18.476004839 +0200 +++ new/src/share/vm/utilities/semaphore.cpp 2015-06-22 16:01:37.524991045 +0200 @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "utilities/debug.hpp" +#include "utilities/semaphore.hpp" + +/////////////// Unit tests /////////////// + +#ifndef PRODUCT + +static void test_semaphore_single_separate(uint count) { + Semaphore sem(0); + + for (uint i = 0; i < count; i++) { + sem.signal(); + } + + for (uint i = 0; i < count; i++) { + sem.wait(); + } +} + +static void test_semaphore_single_combined(uint count) { + Semaphore sem(0); + + for (uint i = 0; i < count; i++) { + sem.signal(); + sem.wait(); + } +} + +static void test_semaphore_many(uint value, uint max, uint increments) { + Semaphore sem(value); + + uint total = value; + + for (uint i = value; i + increments <= max; i += increments) { + sem.signal(increments); + + total += increments; + } + + for (uint i = 0; i < total; i++) { + sem.wait(); + } +} + +static void test_semaphore_many() { + for (uint max = 0; max < 10; max++) { + for (uint value = 0; value < max; value++) { + for (uint inc = 1; inc <= max - value; inc++) { + test_semaphore_many(value, max, inc); + } + } + } +} + +void test_semaphore() { + for (uint i = 1; i < 10; i++) { + test_semaphore_single_separate(i); + } + + for (uint i = 0; i < 10; i++) { + test_semaphore_single_combined(i); + } + + test_semaphore_many(); +} + +#endif // PRODUCT + --- /dev/null 2015-05-29 12:41:18.476004839 +0200 +++ new/src/share/vm/utilities/semaphore.hpp 2015-06-22 16:01:37.712997454 +0200 @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_UTILITIES_SEMAPHORE_HPP +#define SHARE_VM_UTILITIES_SEMAPHORE_HPP + +#include "memory/allocation.hpp" + +#if defined(TARGET_OS_FAMILY_linux) || defined(TARGET_OS_FAMILY_solaris) || defined(TARGET_OS_FAMILY_aix) +# include "semaphore_posix.hpp" +#elif defined(TARGET_OS_FAMILY_bsd) +# include "semaphore_bsd.hpp" +#elif defined(TARGET_OS_FAMILY_windows) +# include "semaphore_windows.hpp" +#else +# error "No semaphore implementation provided for this OS" +#endif + +class Semaphore : public CHeapObj { + private: + // Prevent copying and assignment of Semaphore instances. + Semaphore(const Semaphore&); + Semaphore& operator=(const Semaphore&); + + protected: + os_semaphore_t _semaphore; + + public: + Semaphore(uint value = 0); + virtual ~Semaphore(); + + void signal(uint count = 1); + + void wait(); +}; + +#endif // SHARE_VM_UTILITIES_SEMAPHORE_HPP