8130039: Move the platform-specific [OS]Semaphore code

8130038: Unify the semaphore usage in os_xxx.cpp
8194763: os::signal_lookup is unused

Reviewed-by: dholmes, kbarrett
This commit is contained in:
Coleen Phillimore 2018-01-11 18:42:36 -05:00
parent b0e4bce398
commit 1c41d1d3e0
12 changed files with 349 additions and 326 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2017 SAP SE. All rights reserved. * Copyright (c) 2012, 2017 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
@ -1723,7 +1723,7 @@ void os::signal_notify(int sig) {
local_sem_post(); local_sem_post();
} }
static int check_pending_signals(bool wait) { static int check_pending_signals() {
Atomic::store(0, &sigint_count); Atomic::store(0, &sigint_count);
for (;;) { for (;;) {
for (int i = 0; i < NSIG + 1; i++) { for (int i = 0; i < NSIG + 1; i++) {
@ -1732,9 +1732,6 @@ static int check_pending_signals(bool wait) {
return i; return i;
} }
} }
if (!wait) {
return -1;
}
JavaThread *thread = JavaThread::current(); JavaThread *thread = JavaThread::current();
ThreadBlockInVM tbivm(thread); ThreadBlockInVM tbivm(thread);
@ -1763,12 +1760,8 @@ static int check_pending_signals(bool wait) {
} }
} }
int os::signal_lookup() {
return check_pending_signals(false);
}
int os::signal_wait() { int os::signal_wait() {
return check_pending_signals(true); return check_pending_signals();
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -52,13 +52,13 @@
#include "runtime/orderAccess.inline.hpp" #include "runtime/orderAccess.inline.hpp"
#include "runtime/osThread.hpp" #include "runtime/osThread.hpp"
#include "runtime/perfMemory.hpp" #include "runtime/perfMemory.hpp"
#include "runtime/semaphore.hpp"
#include "runtime/sharedRuntime.hpp" #include "runtime/sharedRuntime.hpp"
#include "runtime/statSampler.hpp" #include "runtime/statSampler.hpp"
#include "runtime/stubRoutines.hpp" #include "runtime/stubRoutines.hpp"
#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"
@ -91,7 +91,6 @@
# include <time.h> # include <time.h>
# include <pwd.h> # include <pwd.h>
# include <poll.h> # include <poll.h>
# include <semaphore.h>
# include <fcntl.h> # include <fcntl.h>
# include <string.h> # include <string.h>
# include <sys/param.h> # include <sys/param.h>
@ -1829,135 +1828,28 @@ int os::sigexitnum_pd() {
// a counter for each possible signal value // a counter for each possible signal value
static volatile jint pending_signals[NSIG+1] = { 0 }; static volatile jint pending_signals[NSIG+1] = { 0 };
static Semaphore* sig_sem = NULL;
// 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
#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);
guarantee(ret == KERN_SUCCESS, "Failed to create semaphore: %s", sem_init_strerror(ret));
}
OSXSemaphore::~OSXSemaphore() {
SEM_DESTROY(_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 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 OSXSemaphore::currenttime() {
struct timeval tv;
gettimeofday(&tv, NULL);
return (tv.tv_sec * NANOSECS_PER_SEC) + (tv.tv_usec * 1000);
}
bool OSXSemaphore::trywait() {
return timedwait(0, 0);
}
bool OSXSemaphore::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();
kr = semaphore_timedwait(_semaphore, waitspec);
while (kr == KERN_ABORTED) {
jlong totalwait = (sec * NANOSECS_PER_SEC) + nsec;
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;
}
kr = semaphore_timedwait(_semaphore, waitspec);
}
return kr == KERN_SUCCESS;
}
#else
// Use POSIX implementation of semaphores.
struct timespec PosixSemaphore::create_timespec(unsigned int sec, int nsec) {
struct timespec ts;
unpackTime(&ts, false, (sec * NANOSECS_PER_SEC) + nsec);
return ts;
}
#endif // __APPLE__
static os_semaphore_t sig_sem;
#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
::memset((void*)pending_signals, 0, sizeof(pending_signals)); ::memset((void*)pending_signals, 0, sizeof(pending_signals));
// Initialize signal semaphore // Initialize signal semaphore
::SEM_INIT(sig_sem, 0); sig_sem = new Semaphore();
} }
void os::signal_notify(int sig) { void os::signal_notify(int sig) {
Atomic::inc(&pending_signals[sig]); if (sig_sem != NULL) {
::SEM_POST(sig_sem); Atomic::inc(&pending_signals[sig]);
sig_sem->signal();
} else {
// Signal thread is not created with ReduceSignalUsage and signal_init_pd
// initialization isn't called.
assert(ReduceSignalUsage, "signal semaphore should be created");
}
} }
static int check_pending_signals(bool wait) { static int check_pending_signals() {
Atomic::store(0, &sigint_count); Atomic::store(0, &sigint_count);
for (;;) { for (;;) {
for (int i = 0; i < NSIG + 1; i++) { for (int i = 0; i < NSIG + 1; i++) {
@ -1966,9 +1858,6 @@ static int check_pending_signals(bool wait) {
return i; return i;
} }
} }
if (!wait) {
return -1;
}
JavaThread *thread = JavaThread::current(); JavaThread *thread = JavaThread::current();
ThreadBlockInVM tbivm(thread); ThreadBlockInVM tbivm(thread);
@ -1976,7 +1865,7 @@ static int check_pending_signals(bool wait) {
do { do {
thread->set_suspend_equivalent(); thread->set_suspend_equivalent();
// cleared by handle_special_suspend_equivalent_condition() or java_suspend_self() // cleared by handle_special_suspend_equivalent_condition() or java_suspend_self()
::SEM_WAIT(sig_sem); sig_sem->wait();
// were we externally suspended while we were waiting? // were we externally suspended while we were waiting?
threadIsSuspended = thread->handle_special_suspend_equivalent_condition(); threadIsSuspended = thread->handle_special_suspend_equivalent_condition();
@ -1985,7 +1874,7 @@ static int check_pending_signals(bool wait) {
// another thread suspended us. We don't want to continue running // another thread suspended us. We don't want to continue running
// while suspended because that would surprise the thread that // while suspended because that would surprise the thread that
// suspended us. // suspended us.
::SEM_POST(sig_sem); sig_sem->signal();
thread->java_suspend_self(); thread->java_suspend_self();
} }
@ -1993,12 +1882,8 @@ static int check_pending_signals(bool wait) {
} }
} }
int os::signal_lookup() {
return check_pending_signals(false);
}
int os::signal_wait() { int os::signal_wait() {
return check_pending_signals(true); return check_pending_signals();
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -2663,6 +2548,12 @@ static void suspend_save_context(OSThread *osthread, siginfo_t* siginfo, ucontex
// //
// Currently only ever called on the VMThread or JavaThread // Currently only ever called on the VMThread or JavaThread
// //
#ifdef __APPLE__
static OSXSemaphore sr_semaphore;
#else
static PosixSemaphore sr_semaphore;
#endif
static void SR_handler(int sig, siginfo_t* siginfo, ucontext_t* context) { static void SR_handler(int sig, siginfo_t* siginfo, ucontext_t* context) {
// Save and restore errno to avoid confusing native code with EINTR // Save and restore errno to avoid confusing native code with EINTR
// after sigsuspend. // after sigsuspend.

View File

@ -0,0 +1,107 @@
/*
* Copyright (c) 2018, 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/precompiled.hpp"
#include "semaphore_bsd.hpp"
#include "utilities/debug.hpp"
#include <semaphore.h>
#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 = semaphore_create(mach_task_self(), &_semaphore, SYNC_POLICY_FIFO, value);
guarantee(ret == KERN_SUCCESS, "Failed to create semaphore: %s", sem_init_strerror(ret));
}
OSXSemaphore::~OSXSemaphore() {
semaphore_destroy(mach_task_self(), _semaphore);
}
void OSXSemaphore::signal(uint count) {
for (uint i = 0; i < count; i++) {
kern_return_t ret = semaphore_signal(_semaphore);
assert(ret == KERN_SUCCESS, "Failed to signal semaphore");
}
}
void OSXSemaphore::wait() {
kern_return_t ret;
while ((ret = semaphore_wait(_semaphore)) == KERN_ABORTED) {
// Semaphore was interrupted. Retry.
}
assert(ret == KERN_SUCCESS, "Failed to wait on semaphore");
}
int64_t OSXSemaphore::currenttime() {
struct timeval tv;
gettimeofday(&tv, NULL);
return (tv.tv_sec * NANOSECS_PER_SEC) + (tv.tv_usec * 1000);
}
bool OSXSemaphore::trywait() {
return timedwait(0, 0);
}
bool OSXSemaphore::timedwait(unsigned int sec, int nsec) {
kern_return_t kr = KERN_ABORTED;
mach_timespec_t waitspec;
waitspec.tv_sec = sec;
waitspec.tv_nsec = nsec;
int64_t starttime = currenttime();
kr = semaphore_timedwait(_semaphore, waitspec);
while (kr == KERN_ABORTED) {
int64_t totalwait = (sec * NANOSECS_PER_SEC) + nsec;
int64_t current = currenttime();
int64_t passedtime = current - starttime;
if (passedtime >= totalwait) {
waitspec.tv_sec = 0;
waitspec.tv_nsec = 0;
} else {
int64_t waittime = totalwait - (current - starttime);
waitspec.tv_sec = waittime / NANOSECS_PER_SEC;
waitspec.tv_nsec = waittime % NANOSECS_PER_SEC;
}
kr = semaphore_timedwait(_semaphore, waitspec);
}
return kr == KERN_SUCCESS;
}
#endif // __APPLE__

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -53,7 +53,7 @@ class OSXSemaphore : public CHeapObj<mtInternal>{
bool timedwait(unsigned int sec, int nsec); bool timedwait(unsigned int sec, int nsec);
private: private:
static jlong currenttime(); static int64_t currenttime();
}; };
typedef OSXSemaphore SemaphoreImpl; typedef OSXSemaphore SemaphoreImpl;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -95,7 +95,6 @@
# include <sys/wait.h> # include <sys/wait.h>
# include <pwd.h> # include <pwd.h>
# include <poll.h> # include <poll.h>
# include <semaphore.h>
# include <fcntl.h> # include <fcntl.h>
# include <string.h> # include <string.h>
# include <syscall.h> # include <syscall.h>
@ -2479,11 +2478,11 @@ void* os::user_handler() {
return CAST_FROM_FN_PTR(void*, UserHandler); return CAST_FROM_FN_PTR(void*, UserHandler);
} }
struct timespec PosixSemaphore::create_timespec(unsigned int sec, int nsec) { static struct timespec create_semaphore_timespec(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);
// see unpackTime for discussion on overflow checking // see os_posix.cpp for discussion on overflow checking
if (sec >= MAX_SECS) { if (sec >= MAX_SECS) {
ts.tv_sec += MAX_SECS; ts.tv_sec += MAX_SECS;
ts.tv_nsec = 0; ts.tv_nsec = 0;
@ -2535,7 +2534,7 @@ int os::sigexitnum_pd() {
static volatile jint pending_signals[NSIG+1] = { 0 }; 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 Semaphore* sig_sem = NULL;
static PosixSemaphore sr_semaphore; static PosixSemaphore sr_semaphore;
void os::signal_init_pd() { void os::signal_init_pd() {
@ -2543,15 +2542,21 @@ void os::signal_init_pd() {
::memset((void*)pending_signals, 0, sizeof(pending_signals)); ::memset((void*)pending_signals, 0, sizeof(pending_signals));
// Initialize signal semaphore // Initialize signal semaphore
::sem_init(&sig_sem, 0, 0); sig_sem = new Semaphore();
} }
void os::signal_notify(int sig) { void os::signal_notify(int sig) {
Atomic::inc(&pending_signals[sig]); if (sig_sem != NULL) {
::sem_post(&sig_sem); Atomic::inc(&pending_signals[sig]);
sig_sem->signal();
} else {
// Signal thread is not created with ReduceSignalUsage and signal_init_pd
// initialization isn't called.
assert(ReduceSignalUsage, "signal semaphore should be created");
}
} }
static int check_pending_signals(bool wait) { static int check_pending_signals() {
Atomic::store(0, &sigint_count); Atomic::store(0, &sigint_count);
for (;;) { for (;;) {
for (int i = 0; i < NSIG + 1; i++) { for (int i = 0; i < NSIG + 1; i++) {
@ -2560,9 +2565,6 @@ static int check_pending_signals(bool wait) {
return i; return i;
} }
} }
if (!wait) {
return -1;
}
JavaThread *thread = JavaThread::current(); JavaThread *thread = JavaThread::current();
ThreadBlockInVM tbivm(thread); ThreadBlockInVM tbivm(thread);
@ -2570,7 +2572,7 @@ static int check_pending_signals(bool wait) {
do { do {
thread->set_suspend_equivalent(); thread->set_suspend_equivalent();
// cleared by handle_special_suspend_equivalent_condition() or java_suspend_self() // cleared by handle_special_suspend_equivalent_condition() or java_suspend_self()
::sem_wait(&sig_sem); sig_sem->wait();
// were we externally suspended while we were waiting? // were we externally suspended while we were waiting?
threadIsSuspended = thread->handle_special_suspend_equivalent_condition(); threadIsSuspended = thread->handle_special_suspend_equivalent_condition();
@ -2579,7 +2581,7 @@ static int check_pending_signals(bool wait) {
// another thread suspended us. We don't want to continue running // another thread suspended us. We don't want to continue running
// while suspended because that would surprise the thread that // while suspended because that would surprise the thread that
// suspended us. // suspended us.
::sem_post(&sig_sem); sig_sem->signal();
thread->java_suspend_self(); thread->java_suspend_self();
} }
@ -2587,12 +2589,8 @@ static int check_pending_signals(bool wait) {
} }
} }
int os::signal_lookup() {
return check_pending_signals(false);
}
int os::signal_wait() { int os::signal_wait() {
return check_pending_signals(true); return check_pending_signals();
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -4317,7 +4315,7 @@ static bool do_suspend(OSThread* osthread) {
// managed to send the signal and switch to SUSPEND_REQUEST, now wait for SUSPENDED // managed to send the signal and switch to SUSPEND_REQUEST, now wait for SUSPENDED
while (true) { while (true) {
if (sr_semaphore.timedwait(0, 2 * NANOSECS_PER_MILLISEC)) { if (sr_semaphore.timedwait(create_semaphore_timespec(0, 2 * NANOSECS_PER_MILLISEC))) {
break; break;
} else { } else {
// timeout // timeout
@ -4351,7 +4349,7 @@ static void do_resume(OSThread* osthread) {
while (true) { while (true) {
if (sr_notify(osthread) == 0) { if (sr_notify(osthread) == 0) {
if (sr_semaphore.timedwait(0, 2 * NANOSECS_PER_MILLISEC)) { if (sr_semaphore.timedwait(create_semaphore_timespec(0, 2 * NANOSECS_PER_MILLISEC))) {
if (osthread->sr.is_running()) { if (osthread->sr.is_running()) {
return; return;
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -31,14 +31,8 @@
#include "utilities/macros.hpp" #include "utilities/macros.hpp"
#include "utilities/vmError.hpp" #include "utilities/vmError.hpp"
#ifndef __APPLE__
// POSIX unamed semaphores are not supported on OS X.
#include "semaphore_posix.hpp"
#endif
#include <dlfcn.h> #include <dlfcn.h>
#include <pthread.h> #include <pthread.h>
#include <semaphore.h>
#include <signal.h> #include <signal.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <sys/resource.h> #include <sys/resource.h>
@ -1499,67 +1493,6 @@ void os::ThreadCrashProtection::check_crash_protection(int sig,
} }
} }
// 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(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__
// Shared pthread_mutex/cond based PlatformEvent implementation. // Shared pthread_mutex/cond based PlatformEvent implementation.
// Not currently usable by Solaris. // Not currently usable by Solaris.

View File

@ -0,0 +1,98 @@
/*
* Copyright (c) 2018, 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/precompiled.hpp"
#ifndef __APPLE__
#include "runtime/os.hpp"
// POSIX unamed semaphores are not supported on OS X.
#include "semaphore_posix.hpp"
#include <semaphore.h>
#define check_with_errno(check_type, cond, msg) \
do { \
int err = errno; \
check_type(cond, "%s; error='%s' (errno=%s)", msg, os::strerror(err), \
os::errno_name(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)
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(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__

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -45,15 +45,7 @@ class PosixSemaphore : public CHeapObj<mtInternal> {
void wait(); void wait();
bool trywait(); bool trywait();
bool timedwait(unsigned int sec, int nsec) {
return timedwait(create_timespec(sec, nsec));
}
private:
bool timedwait(struct timespec ts); 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; typedef PosixSemaphore SemaphoreImpl;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -2062,7 +2062,7 @@ void* os::user_handler() {
return CAST_FROM_FN_PTR(void*, UserHandler); return CAST_FROM_FN_PTR(void*, UserHandler);
} }
struct timespec PosixSemaphore::create_timespec(unsigned int sec, int nsec) { static struct timespec create_semaphore_timespec(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);
@ -2100,7 +2100,7 @@ static int Sigexit = 0;
static jint *pending_signals = NULL; static jint *pending_signals = NULL;
static int *preinstalled_sigs = NULL; static int *preinstalled_sigs = NULL;
static struct sigaction *chainedsigactions = NULL; static struct sigaction *chainedsigactions = NULL;
static sema_t sig_sem; static Semaphore* sig_sem = NULL;
typedef int (*version_getting_t)(); typedef int (*version_getting_t)();
version_getting_t os::Solaris::get_libjsig_version = NULL; version_getting_t os::Solaris::get_libjsig_version = NULL;
@ -2115,6 +2115,7 @@ void os::Solaris::init_signal_mem() {
Sigexit = Maxsignum+1; Sigexit = Maxsignum+1;
assert(Maxsignum >0, "Unable to obtain max signal number"); assert(Maxsignum >0, "Unable to obtain max signal number");
// Initialize signal structures
// pending_signals has one int per signal // pending_signals has one int per signal
// The additional signal is for SIGEXIT - exit signal to signal_thread // The additional signal is for SIGEXIT - exit signal to signal_thread
pending_signals = (jint *)os::malloc(sizeof(jint) * (Sigexit+1), mtInternal); pending_signals = (jint *)os::malloc(sizeof(jint) * (Sigexit+1), mtInternal);
@ -2132,21 +2133,22 @@ void os::Solaris::init_signal_mem() {
} }
void os::signal_init_pd() { void os::signal_init_pd() {
int ret; // Initialize signal semaphore
sig_sem = new Semaphore();
ret = ::sema_init(&sig_sem, 0, NULL, NULL);
assert(ret == 0, "sema_init() failed");
} }
void os::signal_notify(int signal_number) { void os::signal_notify(int sig) {
int ret; if (sig_sem != NULL) {
Atomic::inc(&pending_signals[sig]);
Atomic::inc(&pending_signals[signal_number]); sig_sem->signal();
ret = ::sema_post(&sig_sem); } else {
assert(ret == 0, "sema_post() failed"); // Signal thread is not created with ReduceSignalUsage and signal_init_pd
// initialization isn't called.
assert(ReduceSignalUsage, "signal semaphore should be created");
}
} }
static int check_pending_signals(bool wait_for_signal) { static int check_pending_signals() {
int ret; int ret;
while (true) { while (true) {
for (int i = 0; i < Sigexit + 1; i++) { for (int i = 0; i < Sigexit + 1; i++) {
@ -2155,19 +2157,13 @@ static int check_pending_signals(bool wait_for_signal) {
return i; return i;
} }
} }
if (!wait_for_signal) {
return -1;
}
JavaThread *thread = JavaThread::current(); JavaThread *thread = JavaThread::current();
ThreadBlockInVM tbivm(thread); ThreadBlockInVM tbivm(thread);
bool threadIsSuspended; bool threadIsSuspended;
do { do {
thread->set_suspend_equivalent(); thread->set_suspend_equivalent();
// cleared by handle_special_suspend_equivalent_condition() or java_suspend_self() sig_sem->wait();
while ((ret = ::sema_wait(&sig_sem)) == EINTR)
;
assert(ret == 0, "sema_wait() failed");
// were we externally suspended while we were waiting? // were we externally suspended while we were waiting?
threadIsSuspended = thread->handle_special_suspend_equivalent_condition(); threadIsSuspended = thread->handle_special_suspend_equivalent_condition();
@ -2176,8 +2172,7 @@ static int check_pending_signals(bool wait_for_signal) {
// another thread suspended us. We don't want to continue running // another thread suspended us. We don't want to continue running
// while suspended because that would surprise the thread that // while suspended because that would surprise the thread that
// suspended us. // suspended us.
ret = ::sema_post(&sig_sem); sig_sem->signal();
assert(ret == 0, "sema_post() failed");
thread->java_suspend_self(); thread->java_suspend_self();
} }
@ -2185,12 +2180,8 @@ static int check_pending_signals(bool wait_for_signal) {
} }
} }
int os::signal_lookup() {
return check_pending_signals(false);
}
int os::signal_wait() { int os::signal_wait() {
return check_pending_signals(true); return check_pending_signals();
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -3599,7 +3590,7 @@ static bool do_suspend(OSThread* osthread) {
// managed to send the signal and switch to SUSPEND_REQUEST, now wait for SUSPENDED // managed to send the signal and switch to SUSPEND_REQUEST, now wait for SUSPENDED
while (true) { while (true) {
if (sr_semaphore.timedwait(0, 2000 * NANOSECS_PER_MILLISEC)) { if (sr_semaphore.timedwait(create_semaphore_timespec(0, 2000 * NANOSECS_PER_MILLISEC))) {
break; break;
} else { } else {
// timeout // timeout
@ -3633,7 +3624,7 @@ static void do_resume(OSThread* osthread) {
while (true) { while (true) {
if (sr_notify(osthread) == 0) { if (sr_notify(osthread) == 0) {
if (sr_semaphore.timedwait(0, 2 * NANOSECS_PER_MILLISEC)) { if (sr_semaphore.timedwait(create_semaphore_timespec(0, 2 * NANOSECS_PER_MILLISEC))) {
if (osthread->sr.is_running()) { if (osthread->sr.is_running()) {
return; return;
} }

View File

@ -62,7 +62,6 @@
#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"
@ -1845,36 +1844,6 @@ 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, "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, "ReleaseSemaphore failed with error code: %lu", GetLastError());
}
}
void WindowsSemaphore::wait() {
DWORD ret = ::WaitForSingleObject(_semaphore, INFINITE);
assert(ret != WAIT_FAILED, "WaitForSingleObject failed with error code: %lu", GetLastError());
assert(ret == WAIT_OBJECT_0, "WaitForSingleObject failed with return value: %lu", ret);
}
bool WindowsSemaphore::trywait() {
DWORD ret = ::WaitForSingleObject(_semaphore, 0);
assert(ret != WAIT_FAILED, "WaitForSingleObject failed with error code: %lu", GetLastError());
return ret == WAIT_OBJECT_0;
}
// 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
@ -1966,13 +1935,14 @@ int os::sigexitnum_pd() {
// a counter for each possible signal value, including signal_thread exit signal // a counter for each possible signal value, including signal_thread exit signal
static volatile jint pending_signals[NSIG+1] = { 0 }; static volatile jint pending_signals[NSIG+1] = { 0 };
static HANDLE sig_sem = NULL; static Semaphore* sig_sem = NULL;
void os::signal_init_pd() { void os::signal_init_pd() {
// Initialize signal structures // Initialize signal structures
memset((void*)pending_signals, 0, sizeof(pending_signals)); memset((void*)pending_signals, 0, sizeof(pending_signals));
sig_sem = ::CreateSemaphore(NULL, 0, NSIG+1, NULL); // Initialize signal semaphore
sig_sem = new Semaphore();
// Programs embedding the VM do not want it to attempt to receive // Programs embedding the VM do not want it to attempt to receive
// events like CTRL_LOGOFF_EVENT, which are used to implement the // events like CTRL_LOGOFF_EVENT, which are used to implement the
@ -1994,17 +1964,18 @@ void os::signal_init_pd() {
} }
} }
void os::signal_notify(int signal_number) { void os::signal_notify(int sig) {
BOOL ret;
if (sig_sem != NULL) { if (sig_sem != NULL) {
Atomic::inc(&pending_signals[signal_number]); Atomic::inc(&pending_signals[sig]);
ret = ::ReleaseSemaphore(sig_sem, 1, NULL); sig_sem->signal();
assert(ret != 0, "ReleaseSemaphore() failed"); } else {
// Signal thread is not created with ReduceSignalUsage and signal_init_pd
// initialization isn't called.
assert(ReduceSignalUsage, "signal semaphore should be created");
} }
} }
static int check_pending_signals(bool wait_for_signal) { static int check_pending_signals() {
DWORD ret;
while (true) { while (true) {
for (int i = 0; i < NSIG + 1; i++) { for (int i = 0; i < NSIG + 1; i++) {
jint n = pending_signals[i]; jint n = pending_signals[i];
@ -2012,10 +1983,6 @@ static int check_pending_signals(bool wait_for_signal) {
return i; return i;
} }
} }
if (!wait_for_signal) {
return -1;
}
JavaThread *thread = JavaThread::current(); JavaThread *thread = JavaThread::current();
ThreadBlockInVM tbivm(thread); ThreadBlockInVM tbivm(thread);
@ -2024,8 +1991,7 @@ static int check_pending_signals(bool wait_for_signal) {
do { do {
thread->set_suspend_equivalent(); thread->set_suspend_equivalent();
// cleared by handle_special_suspend_equivalent_condition() or java_suspend_self() // cleared by handle_special_suspend_equivalent_condition() or java_suspend_self()
ret = ::WaitForSingleObject(sig_sem, INFINITE); sig_sem->wait();
assert(ret == WAIT_OBJECT_0, "WaitForSingleObject() failed");
// were we externally suspended while we were waiting? // were we externally suspended while we were waiting?
threadIsSuspended = thread->handle_special_suspend_equivalent_condition(); threadIsSuspended = thread->handle_special_suspend_equivalent_condition();
@ -2034,8 +2000,7 @@ static int check_pending_signals(bool wait_for_signal) {
// another thread suspended us. We don't want to continue running // another thread suspended us. We don't want to continue running
// while suspended because that would surprise the thread that // while suspended because that would surprise the thread that
// suspended us. // suspended us.
ret = ::ReleaseSemaphore(sig_sem, 1, NULL); sig_sem->signal();
assert(ret != 0, "ReleaseSemaphore() failed");
thread->java_suspend_self(); thread->java_suspend_self();
} }
@ -2043,12 +2008,8 @@ static int check_pending_signals(bool wait_for_signal) {
} }
} }
int os::signal_lookup() {
return check_pending_signals(false);
}
int os::signal_wait() { int os::signal_wait() {
return check_pending_signals(true); return check_pending_signals();
} }
// Implicit OS exception handling // Implicit OS exception handling

View File

@ -0,0 +1,60 @@
/*
* Copyright (c) 2018, 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 "semaphore_windows.hpp"
#include "utilities/debug.hpp"
#include <windows.h>
#include <errno.h>
WindowsSemaphore::WindowsSemaphore(uint value) {
_semaphore = ::CreateSemaphore(NULL, value, LONG_MAX, NULL);
guarantee(_semaphore != NULL, "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, "ReleaseSemaphore failed with error code: %lu", GetLastError());
}
}
void WindowsSemaphore::wait() {
DWORD ret = ::WaitForSingleObject(_semaphore, INFINITE);
assert(ret != WAIT_FAILED, "WaitForSingleObject failed with error code: %lu", GetLastError());
assert(ret == WAIT_OBJECT_0, "WaitForSingleObject failed with return value: %lu", ret);
}
bool WindowsSemaphore::trywait() {
DWORD ret = ::WaitForSingleObject(_semaphore, 0);
assert(ret != WAIT_FAILED, "WaitForSingleObject failed with error code: %lu", GetLastError());
return ret == WAIT_OBJECT_0;
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -778,7 +778,6 @@ class os: AllStatic {
static void* signal(int signal_number, void* handler); static void* signal(int signal_number, void* handler);
static void signal_raise(int signal_number); static void signal_raise(int signal_number);
static int signal_wait(); static int signal_wait();
static int signal_lookup();
static void* user_handler(); static void* user_handler();
static void terminate_signal_thread(); static void terminate_signal_thread();
static int sigexitnum_pd(); static int sigexitnum_pd();