--- old/make/solaris/makefiles/vm.make 2015-06-25 18:19:57.012359411 +0200 +++ new/make/solaris/makefiles/vm.make 2015-06-25 18:19:56.880354916 +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-25 18:19:57.276368403 +0200 +++ new/src/os/bsd/vm/os_bsd.cpp 2015-06-25 18:19:57.124363226 +0200 @@ -59,6 +59,7 @@ #include "runtime/thread.inline.hpp" #include "runtime/threadCritical.hpp" #include "runtime/timer.hpp" +#include "semaphore_bsd.hpp" #include "services/attachListener.hpp" #include "services/memTracker.hpp" #include "services/runtimeService.hpp" @@ -1956,47 +1957,54 @@ #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. + +static const char* sem_init_strerror(kern_return_t value) { + switch (value) { + case KERN_INVALID_ARGUMENT: return "Invalid argument"; + case KERN_RESOURCE_SHORTAGE: return "Resource shortage"; + default: return "Unknown"; + } +} + +OSXSemaphore::OSXSemaphore(uint value) { + kern_return_t ret = SEM_INIT(_semaphore, value); -Semaphore::Semaphore() : _semaphore(0) { - SEM_INIT(_semaphore, 0); + guarantee(ret == KERN_SUCCESS, err_msg("Failed to create semaphore: %s", sem_init_strerror(ret))); } -Semaphore::~Semaphore() { +OSXSemaphore::~OSXSemaphore() { SEM_DESTROY(_semaphore); } -void Semaphore::signal() { - SEM_POST(_semaphore); +void OSXSemaphore::signal(uint count) { + for (uint i = 0; i < count; i++) { + kern_return_t ret = SEM_POST(_semaphore); + + assert(ret == KERN_SUCCESS, "Failed to signal semaphore"); + } } -void Semaphore::wait() { - SEM_WAIT(_semaphore); +void OSXSemaphore::wait() { + kern_return_t ret; + while ((ret = SEM_WAIT(_semaphore)) == KERN_ABORTED) { + // Semaphore was interrupted. Retry. + } + assert(ret == KERN_SUCCESS, "Failed to wait on semaphore"); } -jlong Semaphore::currenttime() const { +jlong OSXSemaphore::currenttime() { struct timeval tv; gettimeofday(&tv, NULL); return (tv.tv_sec * NANOSECS_PER_SEC) + (tv.tv_usec * 1000); } -#ifdef __APPLE__ -bool Semaphore::trywait() { +bool OSXSemaphore::trywait() { return timedwait(0, 0); } -bool Semaphore::timedwait(unsigned int sec, int nsec) { +bool OSXSemaphore::timedwait(unsigned int sec, int nsec) { kern_return_t kr = KERN_ABORTED; mach_timespec_t waitspec; waitspec.tv_sec = sec; @@ -2027,33 +2035,24 @@ } #else +// Use POSIX implementation of semaphores. -bool Semaphore::trywait() { - return sem_trywait(&_semaphore) == 0; -} - -bool Semaphore::timedwait(unsigned int sec, int nsec) { +struct timespec 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; } #endif // __APPLE__ static os_semaphore_t sig_sem; -static Semaphore sr_semaphore; + +#ifdef __APPLE__ +static OSXSemaphore sr_semaphore; +#else +static PosixSemaphore sr_semaphore; +#endif void os::signal_init_pd() { // Initialize signal structures --- old/src/os/linux/vm/os_linux.cpp 2015-06-25 18:19:57.664381616 +0200 +++ new/src/os/linux/vm/os_linux.cpp 2015-06-25 18:19:57.492375758 +0200 @@ -60,6 +60,7 @@ #include "runtime/thread.inline.hpp" #include "runtime/threadCritical.hpp" #include "runtime/timer.hpp" +#include "semaphore_posix.hpp" #include "services/attachListener.hpp" #include "services/memTracker.hpp" #include "services/runtimeService.hpp" @@ -2393,40 +2394,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 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 +2411,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 +2451,7 @@ // Linux(POSIX) specific hand shaking semaphore. static sem_t sig_sem; -static Semaphore sr_semaphore; +static PosixSemaphore sr_semaphore; void os::signal_init_pd() { // Initialize signal structures --- old/src/os/posix/vm/os_posix.cpp 2015-06-25 18:19:58.028394012 +0200 +++ new/src/os/posix/vm/os_posix.cpp 2015-06-25 18:19:57.872388699 +0200 @@ -24,6 +24,7 @@ #include "utilities/globalDefinitions.hpp" #include "prims/jvm.h" +#include "semaphore_posix.hpp" #include "runtime/frame.inline.hpp" #include "runtime/interfaceSupport.hpp" #include "runtime/os.hpp" @@ -34,6 +35,7 @@ #include #include #include +#include #include PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC @@ -1015,3 +1017,73 @@ } } } + +#define check_with_errno(check_type, cond, msg) \ + do { \ + int err = errno; \ + check_type(cond, err_msg("%s; error='%s' (errno=%d)", msg, strerror(err), err)); \ +} while (false) + +#define assert_with_errno(cond, msg) check_with_errno(assert, cond, msg) +#define guarantee_with_errno(cond, msg) check_with_errno(guarantee, cond, msg) + +// POSIX unamed semaphores are not supported on OS X. +#ifndef __APPLE__ + +PosixSemaphore::PosixSemaphore(uint value) { + int ret = sem_init(&_semaphore, 0, value); + + guarantee_with_errno(ret == 0, "Failed to initialize semaphore"); +} + +PosixSemaphore::~PosixSemaphore() { + sem_destroy(&_semaphore); +} + +void PosixSemaphore::signal(uint count) { + for (uint i = 0; i < count; i++) { + int ret = sem_post(&_semaphore); + + assert_with_errno(ret == 0, "sem_post failed"); + } +} + +void PosixSemaphore::wait() { + int ret; + + do { + ret = sem_wait(&_semaphore); + } while (ret != 0 && errno == EINTR); + + assert_with_errno(ret == 0, "sem_wait failed"); +} + +bool PosixSemaphore::trywait() { + int ret; + + do { + ret = sem_trywait(&_semaphore); + } while (ret != 0 && errno == EINTR); + + assert_with_errno(ret == 0 || errno == EAGAIN, "trywait failed"); + + return ret == 0; +} + +bool 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/solaris/vm/os_solaris.cpp 2015-06-25 18:19:58.576412674 +0200 +++ new/src/os/solaris/vm/os_solaris.cpp 2015-06-25 18:19:58.408406953 +0200 @@ -60,6 +60,7 @@ #include "runtime/threadCritical.hpp" #include "runtime/timer.hpp" #include "runtime/vm_version.hpp" +#include "semaphore_posix.hpp" #include "services/attachListener.hpp" #include "services/memTracker.hpp" #include "services/runtimeService.hpp" @@ -2266,55 +2267,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 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 +3671,7 @@ osthread->set_ucontext(context); } -static Semaphore sr_semaphore; +static 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-25 18:19:58.964425888 +0200 +++ new/src/os/windows/vm/os_windows.cpp 2015-06-25 18:19:58.800420303 +0200 @@ -63,6 +63,7 @@ #include "runtime/threadCritical.hpp" #include "runtime/timer.hpp" #include "runtime/vm_version.hpp" +#include "semaphore_windows.hpp" #include "services/attachListener.hpp" #include "services/memTracker.hpp" #include "services/runtimeService.hpp" @@ -1895,6 +1896,30 @@ return (int)error; } +WindowsSemaphore::WindowsSemaphore(uint value) { + _semaphore = ::CreateSemaphore(NULL, value, LONG_MAX, NULL); + + guarantee(_semaphore != NULL, err_msg("CreateSemaphore failed with error code: %lu", GetLastError())); +} + +WindowsSemaphore::~WindowsSemaphore() { + ::CloseHandle(_semaphore); +} + +void WindowsSemaphore::signal(uint count) { + if (count > 0) { + BOOL ret = ::ReleaseSemaphore(_semaphore, count, NULL); + + assert(ret != 0, err_msg("ReleaseSemaphore failed with error code: %lu", GetLastError())); + } +} + +void WindowsSemaphore::wait() { + DWORD ret = ::WaitForSingleObject(_semaphore, INFINITE); + assert(ret != WAIT_FAILED, err_msg("WaitForSingleObject failed with error code: %lu", GetLastError())); + assert(ret == WAIT_OBJECT_0, err_msg("WaitForSingleObject failed with return value: %lu", ret)); +} + // 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-25 18:19:59.344438829 +0200 +++ new/src/share/vm/prims/jni.cpp 2015-06-25 18:19:59.180433244 +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()); --- /dev/null 2015-05-29 12:41:18.476004839 +0200 +++ new/src/os/bsd/vm/semaphore_bsd.hpp 2015-06-25 18:19:59.800454358 +0200 @@ -0,0 +1,63 @@ +/* + * 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 + +#ifndef __APPLE__ +// Use POSIX semaphores. +# include "semaphore_posix.hpp" + +#else +// OS X doesn't support unamed POSIX semaphores, so the implementation in os_posix.cpp can't be used. +# include "memory/allocation.hpp" +# include + +class OSXSemaphore : public CHeapObj{ + semaphore_t _semaphore; + + // Prevent copying and assignment. + OSXSemaphore(const OSXSemaphore&); + OSXSemaphore& operator=(const OSXSemaphore&); + + public: + OSXSemaphore(uint value = 0); + ~OSXSemaphore(); + + void signal(uint count = 1); + + void wait(); + + bool trywait(); + bool timedwait(unsigned int sec, int nsec); + + private: + static jlong currenttime(); +}; + +typedef OSXSemaphore SemaphoreImpl; + +#endif // __APPLE__ + +#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-25 18:20:00.016461714 +0200 @@ -0,0 +1,61 @@ +/* + * 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 "memory/allocation.hpp" + +#include + +class PosixSemaphore : public CHeapObj { + sem_t _semaphore; + + // Prevent copying and assignment. + PosixSemaphore(const PosixSemaphore&); + PosixSemaphore& operator=(const PosixSemaphore&); + + public: + PosixSemaphore(uint value = 0); + ~PosixSemaphore(); + + void signal(uint count = 1); + + void wait(); + + 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. + struct timespec create_timespec(unsigned int set, int nsec); +}; + +typedef PosixSemaphore SemaphoreImpl; + +#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-25 18:20:00.232469070 +0200 @@ -0,0 +1,50 @@ +/* + * 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 "memory/allocation.hpp" + +#include + +class WindowsSemaphore : public CHeapObj { + HANDLE _semaphore; + + // Prevent copying and assignment. + WindowsSemaphore(const WindowsSemaphore&); + WindowsSemaphore& operator=(const WindowsSemaphore&); + + public: + WindowsSemaphore(uint value = 0); + ~WindowsSemaphore(); + + void signal(uint count = 1); + + void wait(); +}; + +typedef WindowsSemaphore SemaphoreImpl; + +#endif // OS_WINDOWS_VM_SEMAPHORE_WINDOWS_HPP --- /dev/null 2015-05-29 12:41:18.476004839 +0200 +++ new/src/share/vm/runtime/semaphore.cpp 2015-06-25 18:20:00.456476698 +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 "runtime/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/runtime/semaphore.hpp 2015-06-25 18:20:00.688484599 +0200 @@ -0,0 +1,60 @@ +/* + * 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_RUNTIME_SEMAPHORE_HPP +#define SHARE_VM_RUNTIME_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 + +// Implements the limited, platform independent Semaphore API. +class Semaphore : public CHeapObj { + private: + // Prevent copying and assignment of Semaphore instances. + Semaphore(const Semaphore&); + Semaphore& operator=(const Semaphore&); + + protected: + SemaphoreImpl _impl; + + public: + Semaphore(uint value = 0) : _impl(value) {} + ~Semaphore() {} + + void signal(uint count = 1) { _impl.signal(count); } + + void wait() { _impl.wait(); } +}; + + +#endif // SHARE_VM_RUNTIME_SEMAPHORE_HPP