mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-25 22:04:51 +02:00
8087322: Implement a Semaphore utility class
Reviewed-by: kbarrett, dholmes
This commit is contained in:
parent
88ff99b454
commit
1a534420a8
12 changed files with 473 additions and 136 deletions
|
@ -143,7 +143,7 @@ else
|
||||||
LIBS += -lsocket -lsched -ldl $(LIBM) -lthread -lc -ldemangle
|
LIBS += -lsocket -lsched -ldl $(LIBM) -lthread -lc -ldemangle
|
||||||
endif # sparcWorks
|
endif # sparcWorks
|
||||||
|
|
||||||
LIBS += -lkstat
|
LIBS += -lkstat -lrt
|
||||||
|
|
||||||
# By default, link the *.o into the library, not the executable.
|
# By default, link the *.o into the library, not the executable.
|
||||||
LINK_INTO$(LINK_INTO) = LIBJVM
|
LINK_INTO$(LINK_INTO) = LIBJVM
|
||||||
|
|
|
@ -59,6 +59,7 @@
|
||||||
#include "runtime/thread.inline.hpp"
|
#include "runtime/thread.inline.hpp"
|
||||||
#include "runtime/threadCritical.hpp"
|
#include "runtime/threadCritical.hpp"
|
||||||
#include "runtime/timer.hpp"
|
#include "runtime/timer.hpp"
|
||||||
|
#include "semaphore_bsd.hpp"
|
||||||
#include "services/attachListener.hpp"
|
#include "services/attachListener.hpp"
|
||||||
#include "services/memTracker.hpp"
|
#include "services/memTracker.hpp"
|
||||||
#include "services/runtimeService.hpp"
|
#include "services/runtimeService.hpp"
|
||||||
|
@ -1940,47 +1941,54 @@ typedef sem_t os_semaphore_t;
|
||||||
#define SEM_DESTROY(sem) sem_destroy(&sem)
|
#define SEM_DESTROY(sem) sem_destroy(&sem)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
class Semaphore : public StackObj {
|
#ifdef __APPLE__
|
||||||
public:
|
// OS X doesn't support unamed POSIX semaphores, so the implementation in os_posix.cpp can't be used.
|
||||||
Semaphore();
|
|
||||||
~Semaphore();
|
|
||||||
void signal();
|
|
||||||
void wait();
|
|
||||||
bool trywait();
|
|
||||||
bool timedwait(unsigned int sec, int nsec);
|
|
||||||
private:
|
|
||||||
jlong currenttime() const;
|
|
||||||
os_semaphore_t _semaphore;
|
|
||||||
};
|
|
||||||
|
|
||||||
Semaphore::Semaphore() : _semaphore(0) {
|
static const char* sem_init_strerror(kern_return_t value) {
|
||||||
SEM_INIT(_semaphore, 0);
|
switch (value) {
|
||||||
|
case KERN_INVALID_ARGUMENT: return "Invalid argument";
|
||||||
|
case KERN_RESOURCE_SHORTAGE: return "Resource shortage";
|
||||||
|
default: return "Unknown";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Semaphore::~Semaphore() {
|
OSXSemaphore::OSXSemaphore(uint value) {
|
||||||
|
kern_return_t ret = SEM_INIT(_semaphore, value);
|
||||||
|
|
||||||
|
guarantee(ret == KERN_SUCCESS, err_msg("Failed to create semaphore: %s", sem_init_strerror(ret)));
|
||||||
|
}
|
||||||
|
|
||||||
|
OSXSemaphore::~OSXSemaphore() {
|
||||||
SEM_DESTROY(_semaphore);
|
SEM_DESTROY(_semaphore);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Semaphore::signal() {
|
void OSXSemaphore::signal(uint count) {
|
||||||
SEM_POST(_semaphore);
|
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() {
|
void OSXSemaphore::wait() {
|
||||||
SEM_WAIT(_semaphore);
|
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;
|
struct timeval tv;
|
||||||
gettimeofday(&tv, NULL);
|
gettimeofday(&tv, NULL);
|
||||||
return (tv.tv_sec * NANOSECS_PER_SEC) + (tv.tv_usec * 1000);
|
return (tv.tv_sec * NANOSECS_PER_SEC) + (tv.tv_usec * 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __APPLE__
|
bool OSXSemaphore::trywait() {
|
||||||
bool Semaphore::trywait() {
|
|
||||||
return timedwait(0, 0);
|
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;
|
kern_return_t kr = KERN_ABORTED;
|
||||||
mach_timespec_t waitspec;
|
mach_timespec_t waitspec;
|
||||||
waitspec.tv_sec = sec;
|
waitspec.tv_sec = sec;
|
||||||
|
@ -2011,33 +2019,24 @@ bool Semaphore::timedwait(unsigned int sec, int nsec) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
// Use POSIX implementation of semaphores.
|
||||||
|
|
||||||
bool Semaphore::trywait() {
|
struct timespec PosixSemaphore::create_timespec(unsigned int sec, int nsec) {
|
||||||
return sem_trywait(&_semaphore) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Semaphore::timedwait(unsigned int sec, int nsec) {
|
|
||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
unpackTime(&ts, false, (sec * NANOSECS_PER_SEC) + nsec);
|
unpackTime(&ts, false, (sec * NANOSECS_PER_SEC) + nsec);
|
||||||
|
|
||||||
while (1) {
|
return ts;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // __APPLE__
|
#endif // __APPLE__
|
||||||
|
|
||||||
static os_semaphore_t sig_sem;
|
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() {
|
void os::signal_init_pd() {
|
||||||
// Initialize signal structures
|
// Initialize signal structures
|
||||||
|
|
63
hotspot/src/os/bsd/vm/semaphore_bsd.hpp
Normal file
63
hotspot/src/os/bsd/vm/semaphore_bsd.hpp
Normal file
|
@ -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 <mach/semaphore.h>
|
||||||
|
|
||||||
|
class OSXSemaphore : public CHeapObj<mtInternal>{
|
||||||
|
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
|
|
@ -60,6 +60,7 @@
|
||||||
#include "runtime/thread.inline.hpp"
|
#include "runtime/thread.inline.hpp"
|
||||||
#include "runtime/threadCritical.hpp"
|
#include "runtime/threadCritical.hpp"
|
||||||
#include "runtime/timer.hpp"
|
#include "runtime/timer.hpp"
|
||||||
|
#include "semaphore_posix.hpp"
|
||||||
#include "services/attachListener.hpp"
|
#include "services/attachListener.hpp"
|
||||||
#include "services/memTracker.hpp"
|
#include "services/memTracker.hpp"
|
||||||
#include "services/runtimeService.hpp"
|
#include "services/runtimeService.hpp"
|
||||||
|
@ -2315,40 +2316,7 @@ void* os::user_handler() {
|
||||||
return CAST_FROM_FN_PTR(void*, UserHandler);
|
return CAST_FROM_FN_PTR(void*, UserHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
class Semaphore : public StackObj {
|
struct timespec PosixSemaphore::create_timespec(unsigned int sec, int nsec) {
|
||||||
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 ts;
|
struct timespec ts;
|
||||||
// Semaphore's are always associated with CLOCK_REALTIME
|
// Semaphore's are always associated with CLOCK_REALTIME
|
||||||
os::Linux::clock_gettime(CLOCK_REALTIME, &ts);
|
os::Linux::clock_gettime(CLOCK_REALTIME, &ts);
|
||||||
|
@ -2365,18 +2333,7 @@ bool Semaphore::timedwait(unsigned int sec, int nsec) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (1) {
|
return ts;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -2416,7 +2373,7 @@ static volatile jint pending_signals[NSIG+1] = { 0 };
|
||||||
|
|
||||||
// Linux(POSIX) specific hand shaking semaphore.
|
// Linux(POSIX) specific hand shaking semaphore.
|
||||||
static sem_t sig_sem;
|
static sem_t sig_sem;
|
||||||
static Semaphore sr_semaphore;
|
static PosixSemaphore sr_semaphore;
|
||||||
|
|
||||||
void os::signal_init_pd() {
|
void os::signal_init_pd() {
|
||||||
// Initialize signal structures
|
// Initialize signal structures
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
|
|
||||||
#include "utilities/globalDefinitions.hpp"
|
#include "utilities/globalDefinitions.hpp"
|
||||||
#include "prims/jvm.h"
|
#include "prims/jvm.h"
|
||||||
|
#include "semaphore_posix.hpp"
|
||||||
#include "runtime/frame.inline.hpp"
|
#include "runtime/frame.inline.hpp"
|
||||||
#include "runtime/interfaceSupport.hpp"
|
#include "runtime/interfaceSupport.hpp"
|
||||||
#include "runtime/os.hpp"
|
#include "runtime/os.hpp"
|
||||||
|
@ -34,6 +35,7 @@
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
#include <sys/utsname.h>
|
#include <sys/utsname.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
#include <semaphore.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
||||||
PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
|
PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
|
||||||
|
@ -1015,3 +1017,73 @@ void os::WatcherThreadCrashProtection::check_crash_protection(int sig,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#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__
|
||||||
|
|
61
hotspot/src/os/posix/vm/semaphore_posix.hpp
Normal file
61
hotspot/src/os/posix/vm/semaphore_posix.hpp
Normal file
|
@ -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 <semaphore.h>
|
||||||
|
|
||||||
|
class PosixSemaphore : public CHeapObj<mtInternal> {
|
||||||
|
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
|
|
@ -60,6 +60,7 @@
|
||||||
#include "runtime/threadCritical.hpp"
|
#include "runtime/threadCritical.hpp"
|
||||||
#include "runtime/timer.hpp"
|
#include "runtime/timer.hpp"
|
||||||
#include "runtime/vm_version.hpp"
|
#include "runtime/vm_version.hpp"
|
||||||
|
#include "semaphore_posix.hpp"
|
||||||
#include "services/attachListener.hpp"
|
#include "services/attachListener.hpp"
|
||||||
#include "services/memTracker.hpp"
|
#include "services/memTracker.hpp"
|
||||||
#include "services/runtimeService.hpp"
|
#include "services/runtimeService.hpp"
|
||||||
|
@ -2263,55 +2264,11 @@ void* os::user_handler() {
|
||||||
return CAST_FROM_FN_PTR(void*, UserHandler);
|
return CAST_FROM_FN_PTR(void*, UserHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
class Semaphore : public StackObj {
|
struct timespec PosixSemaphore::create_timespec(unsigned int sec, int nsec) {
|
||||||
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 ts;
|
struct timespec ts;
|
||||||
unpackTime(&ts, false, (sec * NANOSECS_PER_SEC) + nsec);
|
unpackTime(&ts, false, (sec * NANOSECS_PER_SEC) + nsec);
|
||||||
|
|
||||||
while (1) {
|
return ts;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -3711,7 +3668,7 @@ static void suspend_save_context(OSThread *osthread, ucontext_t* context) {
|
||||||
osthread->set_ucontext(context);
|
osthread->set_ucontext(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Semaphore sr_semaphore;
|
static PosixSemaphore sr_semaphore;
|
||||||
|
|
||||||
void os::Solaris::SR_handler(Thread* thread, ucontext_t* uc) {
|
void os::Solaris::SR_handler(Thread* thread, ucontext_t* uc) {
|
||||||
// Save and restore errno to avoid confusing native code with EINTR
|
// Save and restore errno to avoid confusing native code with EINTR
|
||||||
|
|
|
@ -63,6 +63,7 @@
|
||||||
#include "runtime/threadCritical.hpp"
|
#include "runtime/threadCritical.hpp"
|
||||||
#include "runtime/timer.hpp"
|
#include "runtime/timer.hpp"
|
||||||
#include "runtime/vm_version.hpp"
|
#include "runtime/vm_version.hpp"
|
||||||
|
#include "semaphore_windows.hpp"
|
||||||
#include "services/attachListener.hpp"
|
#include "services/attachListener.hpp"
|
||||||
#include "services/memTracker.hpp"
|
#include "services/memTracker.hpp"
|
||||||
#include "services/runtimeService.hpp"
|
#include "services/runtimeService.hpp"
|
||||||
|
@ -1901,6 +1902,30 @@ int os::get_last_error() {
|
||||||
return (int)error;
|
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
|
// sun.misc.Signal
|
||||||
// NOTE that this is a workaround for an apparent kernel bug where if
|
// NOTE that this is a workaround for an apparent kernel bug where if
|
||||||
// a signal handler for SIGBREAK is installed then that signal handler
|
// a signal handler for SIGBREAK is installed then that signal handler
|
||||||
|
|
50
hotspot/src/os/windows/vm/semaphore_windows.hpp
Normal file
50
hotspot/src/os/windows/vm/semaphore_windows.hpp
Normal file
|
@ -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 <windef.h>
|
||||||
|
|
||||||
|
class WindowsSemaphore : public CHeapObj<mtInternal> {
|
||||||
|
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
|
|
@ -3848,6 +3848,7 @@ _JNI_IMPORT_OR_EXPORT_ jint JNICALL JNI_GetDefaultJavaVMInitArgs(void *args_) {
|
||||||
unit_test_function_call
|
unit_test_function_call
|
||||||
|
|
||||||
// Forward declaration
|
// Forward declaration
|
||||||
|
void test_semaphore();
|
||||||
void TestOS_test();
|
void TestOS_test();
|
||||||
void TestReservedSpace_test();
|
void TestReservedSpace_test();
|
||||||
void TestReserveMemorySpecial_test();
|
void TestReserveMemorySpecial_test();
|
||||||
|
@ -3873,6 +3874,7 @@ void FreeRegionList_test();
|
||||||
void execute_internal_vm_tests() {
|
void execute_internal_vm_tests() {
|
||||||
if (ExecuteInternalVMTests) {
|
if (ExecuteInternalVMTests) {
|
||||||
tty->print_cr("Running internal VM tests");
|
tty->print_cr("Running internal VM tests");
|
||||||
|
run_unit_test(test_semaphore());
|
||||||
run_unit_test(TestOS_test());
|
run_unit_test(TestOS_test());
|
||||||
run_unit_test(TestReservedSpace_test());
|
run_unit_test(TestReservedSpace_test());
|
||||||
run_unit_test(TestReserveMemorySpecial_test());
|
run_unit_test(TestReserveMemorySpecial_test());
|
||||||
|
|
93
hotspot/src/share/vm/runtime/semaphore.cpp
Normal file
93
hotspot/src/share/vm/runtime/semaphore.cpp
Normal file
|
@ -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
|
||||||
|
|
58
hotspot/src/share/vm/runtime/semaphore.hpp
Normal file
58
hotspot/src/share/vm/runtime/semaphore.hpp
Normal file
|
@ -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_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<mtInternal> {
|
||||||
|
SemaphoreImpl _impl;
|
||||||
|
|
||||||
|
// Prevent copying and assignment of Semaphore instances.
|
||||||
|
Semaphore(const Semaphore&);
|
||||||
|
Semaphore& operator=(const Semaphore&);
|
||||||
|
|
||||||
|
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
|
Loading…
Add table
Add a link
Reference in a new issue