diff -r 13588c901957 -r 9cf78a70fa4f src/hotspot/os/windows/os_windows.cpp --- a/src/hotspot/os/windows/os_windows.cpp Thu Oct 17 20:27:44 2019 +0100 +++ b/src/hotspot/os/windows/os_windows.cpp Thu Oct 17 20:53:35 2019 +0100 @@ -224,18 +224,12 @@ } home_path = NEW_C_HEAP_ARRAY(char, strlen(home_dir) + 1, mtInternal); - if (home_path == NULL) { - return; - } strcpy(home_path, home_dir); Arguments::set_java_home(home_path); FREE_C_HEAP_ARRAY(char, home_path); dll_path = NEW_C_HEAP_ARRAY(char, strlen(home_dir) + strlen(bin) + 1, mtInternal); - if (dll_path == NULL) { - return; - } strcpy(dll_path, home_dir); strcat(dll_path, bin); Arguments::set_dll_dir(dll_path); @@ -497,7 +491,10 @@ OSThread* osthread = new OSThread(NULL, NULL); if (osthread == NULL) return NULL; - // Initialize support for Java interrupts + // Initialize the JDK library's interrupt event. + // This should really be done when OSThread is constructed, + // but there is no way for a constructor to report failure to + // allocate the event. HANDLE interrupt_event = CreateEvent(NULL, true, false, NULL); if (interrupt_event == NULL) { delete osthread; @@ -599,14 +596,19 @@ return false; } - // Initialize support for Java interrupts + // Initialize the JDK library's interrupt event. + // This should really be done when OSThread is constructed, + // but there is no way for a constructor to report failure to + // allocate the event. HANDLE interrupt_event = CreateEvent(NULL, true, false, NULL); if (interrupt_event == NULL) { delete osthread; return false; } osthread->set_interrupt_event(interrupt_event); - osthread->set_interrupted(false); + // We don't call set_interrupted(false) as it will trip the assert in there + // as we are not operating on the current thread. We don't need to call it + // because the initial state is already correct. thread->set_osthread(osthread); @@ -678,7 +680,6 @@ if (thread_handle == NULL) { // Need to clean up stuff we've allocated so far - CloseHandle(osthread->interrupt_event()); thread->set_osthread(NULL); delete osthread; return false; @@ -708,7 +709,6 @@ "os::free_thread but not current thread"); CloseHandle(osthread->thread_handle()); - CloseHandle(osthread->interrupt_event()); delete osthread; } @@ -826,11 +826,6 @@ } __except(EXCEPTION_EXECUTE_HANDLER) {} } -bool os::distribute_processes(uint length, uint* distribution) { - // Not yet implemented. - return false; -} - bool os::bind_to_processor(uint processor_id) { // Not yet implemented. return false; @@ -911,8 +906,6 @@ } bool os::supports_vtime() { return true; } -bool os::enable_vtime() { return false; } -bool os::vtime_enabled() { return false; } double os::elapsedVTime() { FILETIME created; @@ -1365,14 +1358,24 @@ // in case of error it checks if .dll/.so was built for the // same architecture as Hotspot is running on void * os::dll_load(const char *name, char *ebuf, int ebuflen) { + log_info(os)("attempting shared library load of %s", name); + void * result = LoadLibrary(name); if (result != NULL) { + Events::log(NULL, "Loaded shared library %s", name); // Recalculate pdb search path if a DLL was loaded successfully. SymbolEngine::recalc_search_path(); + log_info(os)("shared library load of %s was successful", name); return result; } - DWORD errcode = GetLastError(); + // Read system error message into ebuf + // It may or may not be overwritten below (in the for loop and just above) + lasterror(ebuf, (size_t) ebuflen); + ebuf[ebuflen - 1] = '\0'; + Events::log(NULL, "Loading shared library %s failed, error code %lu", name, errcode); + log_info(os)("shared library load of %s failed, error code %lu", name, errcode); + if (errcode == ERROR_MOD_NOT_FOUND) { strncpy(ebuf, "Can't find dependent libraries", ebuflen - 1); ebuf[ebuflen - 1] = '\0'; @@ -1384,11 +1387,6 @@ // for an architecture other than Hotspot is running in // - then print to buffer "DLL was built for a different architecture" // else call os::lasterror to obtain system error message - - // Read system error message into ebuf - // It may or may not be overwritten below (in the for loop and just above) - lasterror(ebuf, (size_t) ebuflen); - ebuf[ebuflen - 1] = '\0'; int fd = ::open(name, O_RDONLY | O_BINARY, 0); if (fd < 0) { return NULL; @@ -2580,10 +2578,18 @@ CodeBlob* cb = CodeCache::find_blob_unsafe(pc); nm = (cb != NULL) ? cb->as_compiled_method_or_null() : NULL; } - if ((thread->thread_state() == _thread_in_vm && + + bool is_unsafe_arraycopy = (thread->thread_state() == _thread_in_native || in_java) && UnsafeCopyMemory::contains_pc(pc); + if (((thread->thread_state() == _thread_in_vm || + thread->thread_state() == _thread_in_native || + is_unsafe_arraycopy) && thread->doing_unsafe_access()) || (nm != NULL && nm->has_unsafe_access())) { - return Handle_Exception(exceptionInfo, SharedRuntime::handle_unsafe_access(thread, (address)Assembler::locate_next_instruction(pc))); + address next_pc = Assembler::locate_next_instruction(pc); + if (is_unsafe_arraycopy) { + next_pc = UnsafeCopyMemory::page_error_continue_pc(pc); + } + return Handle_Exception(exceptionInfo, SharedRuntime::handle_unsafe_access(thread, next_pc)); } } @@ -2708,9 +2714,7 @@ int _numa_used_node_count; void free_node_list() { - if (_numa_used_node_list != NULL) { - FREE_C_HEAP_ARRAY(int, _numa_used_node_list); - } + FREE_C_HEAP_ARRAY(int, _numa_used_node_list); } public: @@ -3467,87 +3471,6 @@ assert(ret != SYS_THREAD_ERROR, "StartThread failed"); // should propagate back } -class HighResolutionInterval : public CHeapObj { - // The default timer resolution seems to be 10 milliseconds. - // (Where is this written down?) - // If someone wants to sleep for only a fraction of the default, - // then we set the timer resolution down to 1 millisecond for - // the duration of their interval. - // We carefully set the resolution back, since otherwise we - // seem to incur an overhead (3%?) that we don't need. - // CONSIDER: if ms is small, say 3, then we should run with a high resolution time. - // Buf if ms is large, say 500, or 503, we should avoid the call to timeBeginPeriod(). - // Alternatively, we could compute the relative error (503/500 = .6%) and only use - // timeBeginPeriod() if the relative error exceeded some threshold. - // timeBeginPeriod() has been linked to problems with clock drift on win32 systems and - // to decreased efficiency related to increased timer "tick" rates. We want to minimize - // (a) calls to timeBeginPeriod() and timeEndPeriod() and (b) time spent with high - // resolution timers running. - private: - jlong resolution; - public: - HighResolutionInterval(jlong ms) { - resolution = ms % 10L; - if (resolution != 0) { - MMRESULT result = timeBeginPeriod(1L); - } - } - ~HighResolutionInterval() { - if (resolution != 0) { - MMRESULT result = timeEndPeriod(1L); - } - resolution = 0L; - } -}; - -int os::sleep(Thread* thread, jlong ms, bool interruptable) { - jlong limit = (jlong) MAXDWORD; - - while (ms > limit) { - int res; - if ((res = sleep(thread, limit, interruptable)) != OS_TIMEOUT) { - return res; - } - ms -= limit; - } - - assert(thread == Thread::current(), "thread consistency check"); - OSThread* osthread = thread->osthread(); - OSThreadWaitState osts(osthread, false /* not Object.wait() */); - int result; - if (interruptable) { - assert(thread->is_Java_thread(), "must be java thread"); - JavaThread *jt = (JavaThread *) thread; - ThreadBlockInVM tbivm(jt); - - jt->set_suspend_equivalent(); - // cleared by handle_special_suspend_equivalent_condition() or - // java_suspend_self() via check_and_wait_while_suspended() - - HANDLE events[1]; - events[0] = osthread->interrupt_event(); - HighResolutionInterval *phri=NULL; - if (!ForceTimeHighResolution) { - phri = new HighResolutionInterval(ms); - } - if (WaitForMultipleObjects(1, events, FALSE, (DWORD)ms) == WAIT_TIMEOUT) { - result = OS_TIMEOUT; - } else { - ResetEvent(osthread->interrupt_event()); - osthread->set_interrupted(false); - result = OS_INTRPT; - } - delete phri; //if it is NULL, harmless - - // were we externally suspended while we were waiting? - jt->check_and_wait_while_suspended(); - } else { - assert(!thread->is_Java_thread(), "must not be java thread"); - Sleep((long) ms); - result = OS_TIMEOUT; - } - return result; -} // Short sleep, direct OS call. // @@ -3656,47 +3579,6 @@ return OS_OK; } -void os::interrupt(Thread* thread) { - debug_only(Thread::check_for_dangling_thread_pointer(thread);) - - OSThread* osthread = thread->osthread(); - osthread->set_interrupted(true); - // More than one thread can get here with the same value of osthread, - // resulting in multiple notifications. We do, however, want the store - // to interrupted() to be visible to other threads before we post - // the interrupt event. - OrderAccess::release(); - SetEvent(osthread->interrupt_event()); - // For JSR166: unpark after setting status - if (thread->is_Java_thread()) { - ((JavaThread*)thread)->parker()->unpark(); - } - - ParkEvent * ev = thread->_ParkEvent; - if (ev != NULL) ev->unpark(); -} - - -bool os::is_interrupted(Thread* thread, bool clear_interrupted) { - debug_only(Thread::check_for_dangling_thread_pointer(thread);) - - OSThread* osthread = thread->osthread(); - // There is no synchronization between the setting of the interrupt - // and it being cleared here. It is critical - see 6535709 - that - // we only clear the interrupt state, and reset the interrupt event, - // if we are going to report that we were indeed interrupted - else - // an interrupt can be "lost", leading to spurious wakeups or lost wakeups - // depending on the timing. By checking thread interrupt event to see - // if the thread gets real interrupt thus prevent spurious wakeup. - bool interrupted = osthread->interrupted() && (WaitForSingleObject(osthread->interrupt_event(), 0) == WAIT_OBJECT_0); - if (interrupted && clear_interrupted) { - osthread->set_interrupted(false); - ResetEvent(osthread->interrupt_event()); - } // Otherwise leave the interrupted state alone - - return interrupted; -} - // GetCurrentThreadId() returns DWORD intx os::current_thread_id() { return GetCurrentThreadId(); } @@ -4015,12 +3897,6 @@ _setmode(_fileno(stderr), _O_BINARY); } - -bool os::is_debugger_attached() { - return IsDebuggerPresent() ? true : false; -} - - void os::wait_for_keypress_at_exit(void) { if (PauseAtExit) { fprintf(stderr, "Press any key to continue...\n"); @@ -4109,7 +3985,7 @@ // in order to forward implicit exceptions from code in AOT // generated DLLs. This is necessary since these DLLs are not // registered for structured exceptions like codecache methods are. - if (UseAOT) { + if (AOTLibrary != NULL && (UseAOT || FLAG_IS_DEFAULT(UseAOT))) { topLevelVectoredExceptionHandler = AddVectoredExceptionHandler( 1, topLevelVectoredExceptionFilter); } #endif @@ -4270,94 +4146,182 @@ } } -// The following function is adapted from java.base/windows/native/libjava/canonicalize_md.c -// Creates an UNC path from a single byte path. Return buffer is -// allocated in C heap and needs to be freed by the caller. -// Returns NULL on error. -static wchar_t* create_unc_path(const char* path, errno_t &err) { - wchar_t* wpath = NULL; - size_t converted_chars = 0; - size_t path_len = strlen(path) + 1; // includes the terminating NULL - if (path[0] == '\\' && path[1] == '\\') { - if (path[2] == '?' && path[3] == '\\'){ - // if it already has a \\?\ don't do the prefix - wpath = (wchar_t*)os::malloc(path_len * sizeof(wchar_t), mtInternal); - if (wpath != NULL) { - err = ::mbstowcs_s(&converted_chars, wpath, path_len, path, path_len); +// Returns the given path as an absolute wide path in unc format. The returned path is NULL +// on error (with err being set accordingly) and should be freed via os::free() otherwise. +// additional_space is the number of additionally allocated wchars after the terminating L'\0'. +// This is based on pathToNTPath() in io_util_md.cpp, but omits the optimizations for +// short paths. +static wchar_t* wide_abs_unc_path(char const* path, errno_t & err, int additional_space = 0) { + if ((path == NULL) || (path[0] == '\0')) { + err = ENOENT; + return NULL; + } + + size_t path_len = strlen(path); + // Need to allocate at least room for 3 characters, since os::native_path transforms C: to C:. + char* buf = (char*) os::malloc(1 + MAX2((size_t) 3, path_len), mtInternal); + wchar_t* result = NULL; + + if (buf == NULL) { + err = ENOMEM; + } else { + memcpy(buf, path, path_len + 1); + os::native_path(buf); + + wchar_t* prefix; + int prefix_off = 0; + bool is_abs = true; + bool needs_fullpath = true; + + if (::isalpha(buf[0]) && !::IsDBCSLeadByte(buf[0]) && buf[1] == ':' && buf[2] == '\\') { + prefix = L"\\\\?\\"; + } else if (buf[0] == '\\' && buf[1] == '\\') { + if (buf[2] == '?' && buf[3] == '\\') { + prefix = L""; + needs_fullpath = false; } else { - err = ENOMEM; + prefix = L"\\\\?\\UNC"; + prefix_off = 1; // Overwrite the first char with the prefix, so \\share\path becomes \\?\UNC\share\path } } else { - // only UNC pathname includes double slashes here - wpath = (wchar_t*)os::malloc((path_len + 7) * sizeof(wchar_t), mtInternal); - if (wpath != NULL) { - ::wcscpy(wpath, L"\\\\?\\UNC\0"); - err = ::mbstowcs_s(&converted_chars, &wpath[7], path_len, path, path_len); - } else { - err = ENOMEM; + is_abs = false; + prefix = L"\\\\?\\"; + } + + size_t buf_len = strlen(buf); + size_t prefix_len = wcslen(prefix); + size_t full_path_size = is_abs ? 1 + buf_len : JVM_MAXPATHLEN; + size_t result_size = prefix_len + full_path_size - prefix_off; + result = (wchar_t*) os::malloc(sizeof(wchar_t) * (additional_space + result_size), mtInternal); + + if (result == NULL) { + err = ENOMEM; + } else { + size_t converted_chars; + wchar_t* path_start = result + prefix_len - prefix_off; + err = ::mbstowcs_s(&converted_chars, path_start, buf_len + 1, buf, buf_len); + + if ((err == ERROR_SUCCESS) && needs_fullpath) { + wchar_t* tmp = (wchar_t*) os::malloc(sizeof(wchar_t) * full_path_size, mtInternal); + + if (tmp == NULL) { + err = ENOMEM; + } else { + if (!_wfullpath(tmp, path_start, full_path_size)) { + err = ENOENT; + } else { + ::memcpy(path_start, tmp, (1 + wcslen(tmp)) * sizeof(wchar_t)); + } + + os::free(tmp); + } + } + + memcpy(result, prefix, sizeof(wchar_t) * prefix_len); + + // Remove trailing pathsep (not for \\?\:\, since it would make it relative) + size_t result_len = wcslen(result); + + if (result[result_len - 1] == L'\\') { + if (!(::iswalpha(result[4]) && result[5] == L':' && result_len == 7)) { + result[result_len - 1] = L'\0'; + } } } - } else { - wpath = (wchar_t*)os::malloc((path_len + 4) * sizeof(wchar_t), mtInternal); - if (wpath != NULL) { - ::wcscpy(wpath, L"\\\\?\\\0"); - err = ::mbstowcs_s(&converted_chars, &wpath[4], path_len, path, path_len); - } else { - err = ENOMEM; - } - } - return wpath; -} - -static void destroy_unc_path(wchar_t* wpath) { - os::free(wpath); + } + + os::free(buf); + + if (err != ERROR_SUCCESS) { + os::free(result); + result = NULL; + } + + return result; } int os::stat(const char *path, struct stat *sbuf) { - char* pathbuf = (char*)os::strdup(path, mtInternal); - if (pathbuf == NULL) { - errno = ENOMEM; + errno_t err; + wchar_t* wide_path = wide_abs_unc_path(path, err); + + if (wide_path == NULL) { + errno = err; + return -1; + } + + WIN32_FILE_ATTRIBUTE_DATA file_data;; + BOOL bret = ::GetFileAttributesExW(wide_path, GetFileExInfoStandard, &file_data); + os::free(wide_path); + + if (!bret) { + errno = ::GetLastError(); return -1; } - os::native_path(pathbuf); - int ret; - WIN32_FILE_ATTRIBUTE_DATA file_data; - // Not using stat() to avoid the problem described in JDK-6539723 - if (strlen(path) < MAX_PATH) { - BOOL bret = ::GetFileAttributesExA(pathbuf, GetFileExInfoStandard, &file_data); - if (!bret) { - errno = ::GetLastError(); - ret = -1; - } - else { - file_attribute_data_to_stat(sbuf, file_data); - ret = 0; + + file_attribute_data_to_stat(sbuf, file_data); + return 0; +} + +static HANDLE create_read_only_file_handle(const char* file) { + errno_t err; + wchar_t* wide_path = wide_abs_unc_path(file, err); + + if (wide_path == NULL) { + errno = err; + return INVALID_HANDLE_VALUE; + } + + HANDLE handle = ::CreateFileW(wide_path, 0, FILE_SHARE_READ, + NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + os::free(wide_path); + + return handle; +} + +bool os::same_files(const char* file1, const char* file2) { + + if (file1 == NULL && file2 == NULL) { + return true; + } + + if (file1 == NULL || file2 == NULL) { + return false; + } + + if (strcmp(file1, file2) == 0) { + return true; + } + + HANDLE handle1 = create_read_only_file_handle(file1); + HANDLE handle2 = create_read_only_file_handle(file2); + bool result = false; + + // if we could open both paths... + if (handle1 != INVALID_HANDLE_VALUE && handle2 != INVALID_HANDLE_VALUE) { + BY_HANDLE_FILE_INFORMATION fileInfo1; + BY_HANDLE_FILE_INFORMATION fileInfo2; + if (::GetFileInformationByHandle(handle1, &fileInfo1) && + ::GetFileInformationByHandle(handle2, &fileInfo2)) { + // the paths are the same if they refer to the same file (fileindex) on the same volume (volume serial number) + if (fileInfo1.dwVolumeSerialNumber == fileInfo2.dwVolumeSerialNumber && + fileInfo1.nFileIndexHigh == fileInfo2.nFileIndexHigh && + fileInfo1.nFileIndexLow == fileInfo2.nFileIndexLow) { + result = true; + } } - } else { - errno_t err = ERROR_SUCCESS; - wchar_t* wpath = create_unc_path(pathbuf, err); - if (err != ERROR_SUCCESS) { - if (wpath != NULL) { - destroy_unc_path(wpath); - } - os::free(pathbuf); - errno = err; - return -1; - } - BOOL bret = ::GetFileAttributesExW(wpath, GetFileExInfoStandard, &file_data); - if (!bret) { - errno = ::GetLastError(); - ret = -1; - } else { - file_attribute_data_to_stat(sbuf, file_data); - ret = 0; - } - destroy_unc_path(wpath); - } - os::free(pathbuf); - return ret; -} - + } + + //free the handles + if (handle1 != INVALID_HANDLE_VALUE) { + ::CloseHandle(handle1); + } + + if (handle2 != INVALID_HANDLE_VALUE) { + ::CloseHandle(handle2); + } + + return result; +} #define FT2INT64(ft) \ ((jlong)((jlong)(ft).dwHighDateTime << 32 | (julong)(ft).dwLowDateTime)) @@ -4463,38 +4427,22 @@ return DontYieldALot; } -// This method is a slightly reworked copy of JDK's sysOpen -// from src/windows/hpi/src/sys_api_md.c - int os::open(const char *path, int oflag, int mode) { - char* pathbuf = (char*)os::strdup(path, mtInternal); - if (pathbuf == NULL) { - errno = ENOMEM; + errno_t err; + wchar_t* wide_path = wide_abs_unc_path(path, err); + + if (wide_path == NULL) { + errno = err; return -1; } - os::native_path(pathbuf); - int ret; - if (strlen(path) < MAX_PATH) { - ret = ::open(pathbuf, oflag | O_BINARY | O_NOINHERIT, mode); - } else { - errno_t err = ERROR_SUCCESS; - wchar_t* wpath = create_unc_path(pathbuf, err); - if (err != ERROR_SUCCESS) { - if (wpath != NULL) { - destroy_unc_path(wpath); - } - os::free(pathbuf); - errno = err; - return -1; - } - ret = ::_wopen(wpath, oflag | O_BINARY | O_NOINHERIT, mode); - if (ret == -1) { - errno = ::GetLastError(); - } - destroy_unc_path(wpath); - } - os::free(pathbuf); - return ret; + int fd = ::_wopen(wide_path, oflag | O_BINARY | O_NOINHERIT, mode); + os::free(wide_path); + + if (fd == -1) { + errno = ::GetLastError(); + } + + return fd; } FILE* os::open(int fd, const char* mode) { @@ -4503,37 +4451,26 @@ // Is a (classpath) directory empty? bool os::dir_is_empty(const char* path) { - char* search_path = (char*)os::malloc(strlen(path) + 3, mtInternal); - if (search_path == NULL) { - errno = ENOMEM; - return false; - } - strcpy(search_path, path); - os::native_path(search_path); - // Append "*", or possibly "\\*", to path - if (search_path[1] == ':' && - (search_path[2] == '\0' || - (search_path[2] == '\\' && search_path[3] == '\0'))) { - // No '\\' needed for cases like "Z:" or "Z:\" - strcat(search_path, "*"); - } - else { - strcat(search_path, "\\*"); - } - errno_t err = ERROR_SUCCESS; - wchar_t* wpath = create_unc_path(search_path, err); - if (err != ERROR_SUCCESS) { - if (wpath != NULL) { - destroy_unc_path(wpath); - } - os::free(search_path); + errno_t err; + wchar_t* wide_path = wide_abs_unc_path(path, err, 2); + + if (wide_path == NULL) { errno = err; return false; } + + // Make sure we end with "\\*" + if (wide_path[wcslen(wide_path) - 1] == L'\\') { + wcscat(wide_path, L"*"); + } else { + wcscat(wide_path, L"\\*"); + } + WIN32_FIND_DATAW fd; - HANDLE f = ::FindFirstFileW(wpath, &fd); - destroy_unc_path(wpath); + HANDLE f = ::FindFirstFileW(wide_path, &fd); + os::free(wide_path); bool is_empty = true; + if (f != INVALID_HANDLE_VALUE) { while (is_empty && ::FindNextFileW(f, &fd)) { // An empty directory contains only the current directory file @@ -4544,8 +4481,10 @@ } } FindClose(f); - } - os::free(search_path); + } else { + errno = ::GetLastError(); + } + return is_empty; } @@ -4910,6 +4849,9 @@ return NULL; } + // Record virtual memory allocation + MemTracker::record_virtual_memory_reserve_and_commit((address)addr, bytes, CALLER_PC); + DWORD bytes_read; OVERLAPPED overlapped; overlapped.Offset = (DWORD)file_offset; @@ -5020,7 +4962,7 @@ void os::pause() { char filename[MAX_PATH]; if (PauseAtStartupFile && PauseAtStartupFile[0]) { - jio_snprintf(filename, MAX_PATH, PauseAtStartupFile); + jio_snprintf(filename, MAX_PATH, "%s", PauseAtStartupFile); } else { jio_snprintf(filename, MAX_PATH, "./vm.paused.%d", current_process_id()); } @@ -5072,6 +5014,40 @@ return success; } + +class HighResolutionInterval : public CHeapObj { + // The default timer resolution seems to be 10 milliseconds. + // (Where is this written down?) + // If someone wants to sleep for only a fraction of the default, + // then we set the timer resolution down to 1 millisecond for + // the duration of their interval. + // We carefully set the resolution back, since otherwise we + // seem to incur an overhead (3%?) that we don't need. + // CONSIDER: if ms is small, say 3, then we should run with a high resolution time. + // Buf if ms is large, say 500, or 503, we should avoid the call to timeBeginPeriod(). + // Alternatively, we could compute the relative error (503/500 = .6%) and only use + // timeBeginPeriod() if the relative error exceeded some threshold. + // timeBeginPeriod() has been linked to problems with clock drift on win32 systems and + // to decreased efficiency related to increased timer "tick" rates. We want to minimize + // (a) calls to timeBeginPeriod() and timeEndPeriod() and (b) time spent with high + // resolution timers running. + private: + jlong resolution; + public: + HighResolutionInterval(jlong ms) { + resolution = ms % 10L; + if (resolution != 0) { + MMRESULT result = timeBeginPeriod(1L); + } + } + ~HighResolutionInterval() { + if (resolution != 0) { + MMRESULT result = timeEndPeriod(1L); + } + resolution = 0L; + } +}; + // An Event wraps a win32 "CreateEvent" kernel handle. // // We have a number of choices regarding "CreateEvent" win32 handle leakage: @@ -5107,7 +5083,7 @@ // 1. Reconcile Doug's JSR166 j.u.c park-unpark with the objectmonitor implementation. // 2. Consider wrapping the WaitForSingleObject(Ex) calls in SEH try/finally blocks // to recover from (or at least detect) the dreaded Windows 841176 bug. -// 3. Collapse the interrupt_event, the JSR166 parker event, and the objectmonitor ParkEvent +// 3. Collapse the JSR166 parker event, and the objectmonitor ParkEvent // into a single win32 CreateEvent() handle. // // Assumption: @@ -5180,11 +5156,16 @@ if (Millis > MAXTIMEOUT) { prd = MAXTIMEOUT; } + HighResolutionInterval *phri = NULL; + if (!ForceTimeHighResolution) { + phri = new HighResolutionInterval(prd); + } rv = ::WaitForSingleObject(_ParkHandle, prd); assert(rv == WAIT_OBJECT_0 || rv == WAIT_TIMEOUT, "WaitForSingleObject failed"); if (rv == WAIT_TIMEOUT) { Millis -= prd; } + delete phri; // if it is NULL, harmless } v = _Event; _Event = 0; @@ -5283,7 +5264,7 @@ JavaThread* thread = JavaThread::current(); // Don't wait if interrupted or already triggered - if (Thread::is_interrupted(thread, false) || + if (thread->is_interrupted(false) || WaitForSingleObject(_ParkEvent, 0) == WAIT_OBJECT_0) { ResetEvent(_ParkEvent); return; @@ -5705,3 +5686,7 @@ os::os_exception_wrapper((java_call_t)call_wrapper_dummy, NULL, NULL, NULL, NULL); } + +bool os::supports_map_sync() { + return false; +}