< prev index next >
src/os/windows/vm/os_windows.cpp
Print this page
*** 906,916 ****
}
}
void os::javaTimeNanos_info(jvmtiTimerInfo *info_ptr) {
if (!win32::_has_performance_count) {
! // javaTimeMillis() doesn't have much percision,
// but it is not going to wrap -- so all 64 bits
info_ptr->max_value = ALL_64_BITS;
// this is a wall clock timer, so may skip
info_ptr->may_skip_backward = true;
--- 906,916 ----
}
}
void os::javaTimeNanos_info(jvmtiTimerInfo *info_ptr) {
if (!win32::_has_performance_count) {
! // javaTimeMillis() doesn't have much precision,
// but it is not going to wrap -- so all 64 bits
info_ptr->max_value = ALL_64_BITS;
// this is a wall clock timer, so may skip
info_ptr->may_skip_backward = true;
*** 3884,3893 ****
--- 3884,3894 ----
jio_snprintf(ebuf, ebuflen,
"os::win32::load_windows_dll() cannot load %s from system directories.", name);
return NULL;
}
+ #define MAXIMUM_THREADS_TO_KEEP (16 * MAXIMUM_WAIT_OBJECTS)
#define EXIT_TIMEOUT 300000 /* 5 minutes */
static BOOL CALLBACK init_crit_sect_call(PINIT_ONCE, PVOID pcrit_sect, PVOID*) {
InitializeCriticalSection((CRITICAL_SECTION*)pcrit_sect);
return TRUE;
*** 3902,3925 ****
if (os::win32::has_exit_bug()) {
// The array holds handles of the threads that have started exiting by calling
// _endthreadex().
// Should be large enough to avoid blocking the exiting thread due to lack of
// a free slot.
! static HANDLE handles[MAXIMUM_WAIT_OBJECTS];
static int handle_count = 0;
static INIT_ONCE init_once_crit_sect = INIT_ONCE_STATIC_INIT;
static CRITICAL_SECTION crit_sect;
static volatile jint process_exiting = 0;
int i, j;
DWORD res;
HANDLE hproc, hthr;
// The first thread that reached this point, initializes the critical section.
if (!InitOnceExecuteOnce(&init_once_crit_sect, init_crit_sect_call, &crit_sect, NULL)) {
warning("crit_sect initialization failed in %s: %d\n", __FILE__, __LINE__);
} else if (OrderAccess::load_acquire(&process_exiting) == 0) {
EnterCriticalSection(&crit_sect);
if (what == EPT_THREAD && OrderAccess::load_acquire(&process_exiting) == 0) {
// Remove from the array those handles of the threads that have completed exiting.
for (i = 0, j = 0; i < handle_count; ++i) {
--- 3903,3930 ----
if (os::win32::has_exit_bug()) {
// The array holds handles of the threads that have started exiting by calling
// _endthreadex().
// Should be large enough to avoid blocking the exiting thread due to lack of
// a free slot.
! static HANDLE handles[MAXIMUM_THREADS_TO_KEEP];
static int handle_count = 0;
static INIT_ONCE init_once_crit_sect = INIT_ONCE_STATIC_INIT;
static CRITICAL_SECTION crit_sect;
static volatile jint process_exiting = 0;
+ jint pr_ex;
int i, j;
DWORD res;
HANDLE hproc, hthr;
// The first thread that reached this point, initializes the critical section.
if (!InitOnceExecuteOnce(&init_once_crit_sect, init_crit_sect_call, &crit_sect, NULL)) {
warning("crit_sect initialization failed in %s: %d\n", __FILE__, __LINE__);
} else if (OrderAccess::load_acquire(&process_exiting) == 0) {
+ if (what != EPT_THREAD) {
+ Atomic::cmpxchg((jint)GetCurrentThreadId(), &process_exiting, 0);
+ }
EnterCriticalSection(&crit_sect);
if (what == EPT_THREAD && OrderAccess::load_acquire(&process_exiting) == 0) {
// Remove from the array those handles of the threads that have completed exiting.
for (i = 0, j = 0; i < handle_count; ++i) {
*** 3936,3962 ****
}
}
// If there's no free slot in the array of the kept handles, we'll have to
// wait until at least one thread completes exiting.
! if ((handle_count = j) == MAXIMUM_WAIT_OBJECTS) {
// Raise the priority of the oldest exiting thread to increase its chances
// to complete sooner.
SetThreadPriority(handles[0], THREAD_PRIORITY_ABOVE_NORMAL);
res = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, handles, FALSE, EXIT_TIMEOUT);
if (res >= WAIT_OBJECT_0 && res < (WAIT_OBJECT_0 + MAXIMUM_WAIT_OBJECTS)) {
i = (res - WAIT_OBJECT_0);
! handle_count = MAXIMUM_WAIT_OBJECTS - 1;
for (; i < handle_count; ++i) {
handles[i] = handles[i + 1];
}
} else {
warning("WaitForMultipleObjects %s (%u) in %s: %d\n",
(res == WAIT_FAILED ? "failed" : "timed out"),
GetLastError(), __FILE__, __LINE__);
// Don't keep handles, if we failed waiting for them.
! for (i = 0; i < MAXIMUM_WAIT_OBJECTS; ++i) {
CloseHandle(handles[i]);
}
handle_count = 0;
}
}
--- 3941,3967 ----
}
}
// If there's no free slot in the array of the kept handles, we'll have to
// wait until at least one thread completes exiting.
! if ((handle_count = j) == MAXIMUM_THREADS_TO_KEEP) {
// Raise the priority of the oldest exiting thread to increase its chances
// to complete sooner.
SetThreadPriority(handles[0], THREAD_PRIORITY_ABOVE_NORMAL);
res = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, handles, FALSE, EXIT_TIMEOUT);
if (res >= WAIT_OBJECT_0 && res < (WAIT_OBJECT_0 + MAXIMUM_WAIT_OBJECTS)) {
i = (res - WAIT_OBJECT_0);
! handle_count = MAXIMUM_THREADS_TO_KEEP - 1;
for (; i < handle_count; ++i) {
handles[i] = handles[i + 1];
}
} else {
warning("WaitForMultipleObjects %s (%u) in %s: %d\n",
(res == WAIT_FAILED ? "failed" : "timed out"),
GetLastError(), __FILE__, __LINE__);
// Don't keep handles, if we failed waiting for them.
! for (i = 0; i < MAXIMUM_THREADS_TO_KEEP; ++i) {
CloseHandle(handles[i]);
}
handle_count = 0;
}
}
*** 3975,4018 ****
// The current exiting thread has stored its handle in the array, and now
// should leave the critical section before calling _endthreadex().
} else if (what != EPT_THREAD) {
if (handle_count > 0) {
// Before ending the process, make sure all the threads that had called
// _endthreadex() completed.
// Set the priority level of the current thread to the same value as
// the priority level of exiting threads.
// This is to ensure it will be given a fair chance to execute if
// the timeout expires.
hthr = GetCurrentThread();
SetThreadPriority(hthr, THREAD_PRIORITY_ABOVE_NORMAL);
! for (i = 0; i < handle_count; ++i) {
! SetThreadPriority(handles[i], THREAD_PRIORITY_ABOVE_NORMAL);
}
! res = WaitForMultipleObjects(handle_count, handles, TRUE, EXIT_TIMEOUT);
if (res == WAIT_FAILED || res == WAIT_TIMEOUT) {
warning("WaitForMultipleObjects %s (%u) in %s: %d\n",
(res == WAIT_FAILED ? "failed" : "timed out"),
GetLastError(), __FILE__, __LINE__);
}
! for (i = 0; i < handle_count; ++i) {
! CloseHandle(handles[i]);
}
handle_count = 0;
}
-
- OrderAccess::release_store(&process_exiting, 1);
}
LeaveCriticalSection(&crit_sect);
}
! if (what == EPT_THREAD) {
! while (OrderAccess::load_acquire(&process_exiting) != 0) {
// Some other thread is about to call exit(), so we
! // don't let the current thread proceed to _endthreadex()
SuspendThread(GetCurrentThread());
// Avoid busy-wait loop, if SuspendThread() failed.
Sleep(EXIT_TIMEOUT);
}
}
--- 3980,4040 ----
// The current exiting thread has stored its handle in the array, and now
// should leave the critical section before calling _endthreadex().
} else if (what != EPT_THREAD) {
if (handle_count > 0) {
+ jlong start_time, finish_time, timeout_left;
// Before ending the process, make sure all the threads that had called
// _endthreadex() completed.
// Set the priority level of the current thread to the same value as
// the priority level of exiting threads.
// This is to ensure it will be given a fair chance to execute if
// the timeout expires.
hthr = GetCurrentThread();
SetThreadPriority(hthr, THREAD_PRIORITY_ABOVE_NORMAL);
! start_time = os::javaTimeNanos();
! finish_time = start_time + ((jlong)EXIT_TIMEOUT * 1000000L);
! for (i = 0; ; ) {
! int portion_count = handle_count - i;
! if (portion_count > MAXIMUM_WAIT_OBJECTS) {
! portion_count = MAXIMUM_WAIT_OBJECTS;
! }
! for (j = 0; j < portion_count; ++j) {
! SetThreadPriority(handles[i + j], THREAD_PRIORITY_ABOVE_NORMAL);
! }
! timeout_left = (finish_time - start_time) / 1000000L;
! if (timeout_left < 0) {
! timeout_left = 0;
}
! res = WaitForMultipleObjects(portion_count, handles + i, TRUE, timeout_left);
if (res == WAIT_FAILED || res == WAIT_TIMEOUT) {
warning("WaitForMultipleObjects %s (%u) in %s: %d\n",
(res == WAIT_FAILED ? "failed" : "timed out"),
GetLastError(), __FILE__, __LINE__);
+ portion_count = handle_count - i;
}
! for (j = 0; j < portion_count; ++j) {
! CloseHandle(handles[i + j]);
! }
! if ((i += portion_count) >= handle_count) {
! break;
! }
! start_time = os::javaTimeNanos();
}
handle_count = 0;
}
}
LeaveCriticalSection(&crit_sect);
}
! if ((pr_ex = OrderAccess::load_acquire(&process_exiting)) != 0) {
! jint curr_id = (jint)GetCurrentThreadId();
! while (pr_ex != curr_id) {
// Some other thread is about to call exit(), so we
! // don't let the current thread proceed to exit() or _endthreadex()
SuspendThread(GetCurrentThread());
// Avoid busy-wait loop, if SuspendThread() failed.
Sleep(EXIT_TIMEOUT);
}
}
< prev index next >