src/os/windows/vm/os_windows.cpp
Print this page
@@ -20,12 +20,12 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
-// Must be at least Windows 2000 or XP to use IsDebuggerPresent
-#define _WIN32_WINNT 0x500
+// Must be at least Windows Vista or Server 2008 to use InitOnceExecuteOnce
+#define _WIN32_WINNT 0x0600
// no precompiled headers
#include "classfile/classLoader.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/vmSymbols.hpp"
@@ -407,12 +407,10 @@
return NULL;
}
LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo);
-extern jint volatile vm_getting_terminated;
-
// Thread start routine for all new Java threads
static unsigned __stdcall java_start(Thread* thread) {
// Try to randomize the cache line index of hot stack frames.
// This helps when threads of the same stack traces evict each other's
// cache lines. The threads can be either from the same JVM instance, or
@@ -430,17 +428,14 @@
if (lgrp_id != -1) {
thread->set_lgrp_id(lgrp_id);
}
}
- // Diagnostic code to investigate JDK-6573254 (Part I)
- unsigned res = 90115; // non-java thread
+ // Diagnostic code to investigate JDK-6573254
+ int res = 90115; // non-java thread
if (thread->is_Java_thread()) {
- JavaThread* java_thread = (JavaThread*)thread;
- res = java_lang_Thread::is_daemon(java_thread->threadObj())
- ? 70115 // java daemon thread
- : 80115; // java non-daemon thread
+ res = 60115; // java thread
}
// Install a win32 structured exception handler around every thread created
// by VM, so VM can generate error dump when an exception occurred in non-
// Java thread (e.g. VM thread).
@@ -456,16 +451,13 @@
// which frees the CodeHeap containing the Atomic::add code
if (thread != VMThread::vm_thread() && VMThread::vm_thread() != NULL) {
Atomic::dec_ptr((intptr_t*)&os::win32::_os_thread_count);
}
- // Diagnostic code to investigate JDK-6573254 (Part II)
- if (OrderAccess::load_acquire(&vm_getting_terminated)) {
- return res;
- }
-
- return 0;
+ // Thread must not return from exit_process_or_thread(), but if it does,
+ // let it proceed to exit normally
+ return (unsigned)os::win32::exit_process_or_thread(os::win32::EPT_THREAD, res);
}
static OSThread* create_os_thread(Thread* thread, HANDLE thread_handle, int thread_id) {
// Allocate the OSThread object
OSThread* osthread = new OSThread(NULL, NULL);
@@ -1060,21 +1052,19 @@
CloseHandle(dumpFile);
}
-
-void os::abort(bool dump_core)
-{
+void os::abort(bool dump_core) {
os::shutdown();
// no core dump on Windows
- ::exit(1);
+ win32::exit_process_or_thread(win32::EPT_PROCESS, 1);
}
// Die immediately, no exit hook, no abort hook, no cleanup.
void os::die() {
- _exit(-1);
+ win32::exit_process_or_thread(win32::EPT_PROCESS_DIE, -1);
}
// Directory routines copied from src/win32/native/java/io/dirent_md.c
// * dirent_md.c 1.15 00/02/02
//
@@ -3621,10 +3611,14 @@
bool os::win32::_is_nt = false;
bool os::win32::_is_windows_2003 = false;
bool os::win32::_is_windows_server = false;
+// 6573254
+// Currently, the bug is observed across all the supported Windows releases,
+// including the latest one (as of this writing - Windows Server 2012 R2)
+bool os::win32::_has_exit_bug = true;
bool os::win32::_has_performance_count = 0;
void os::win32::initialize_system_info() {
SYSTEM_INFO si;
GetSystemInfo(&si);
@@ -3717,10 +3711,73 @@
jio_snprintf(ebuf, ebuflen,
"os::win32::load_windows_dll() cannot load %s from system directories.", name);
return NULL;
}
+#define MIN_EXIT_MUTEXES 1
+#define MAX_EXIT_MUTEXES 16
+
+struct ExitMutexes {
+ DWORD count;
+ HANDLE handles[MAX_EXIT_MUTEXES];
+};
+
+static BOOL CALLBACK init_muts_call(PINIT_ONCE, PVOID ppmuts, PVOID*) {
+ static ExitMutexes muts;
+
+ muts.count = os::processor_count();
+ if (muts.count < MIN_EXIT_MUTEXES) {
+ muts.count = MIN_EXIT_MUTEXES;
+ } else if (muts.count > MAX_EXIT_MUTEXES) {
+ muts.count = MAX_EXIT_MUTEXES;
+ }
+
+ for (DWORD i = 0; i < muts.count; ++i) {
+ muts.handles[i] = CreateMutex(NULL, FALSE, NULL);
+ if (muts.handles[i] == NULL) {
+ return FALSE;
+ }
+ }
+ *((ExitMutexes**)ppmuts) = &muts;
+ return TRUE;
+}
+
+int os::win32::exit_process_or_thread(Ept what, int exit_code) {
+ if (os::win32::has_exit_bug()) {
+ static INIT_ONCE init_once_muts = INIT_ONCE_STATIC_INIT;
+ static ExitMutexes* pmuts;
+
+ if (!InitOnceExecuteOnce(&init_once_muts, init_muts_call, &pmuts, NULL)) {
+ warning("ExitMutex initialization failed in %s: %d\n", __FILE__, __LINE__);
+ } else if (WaitForMultipleObjects(pmuts->count, pmuts->handles,
+ (what != EPT_THREAD), // exiting process waits for all mutexes
+ INFINITE) == WAIT_FAILED) {
+ warning("ExitMutex acquisition failed in %s: %d\n", __FILE__, __LINE__);
+ }
+ }
+
+ switch (what) {
+ case EPT_THREAD:
+ _endthreadex((unsigned)exit_code);
+ break;
+
+ case EPT_PROCESS:
+ ::exit(exit_code);
+ break;
+
+ case EPT_PROCESS_DIE:
+ _exit(exit_code);
+ break;
+ }
+
+ // should not reach here
+ return exit_code;
+}
+
+#undef MIN_EXIT_MUTEXES
+#undef MAX_EXIT_MUTEXES
+
void os::win32::setmode_streams() {
_setmode(_fileno(stdin), _O_BINARY);
_setmode(_fileno(stdout), _O_BINARY);
_setmode(_fileno(stderr), _O_BINARY);
}