--- 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<mtThread> {
- // 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 \\?\<DRIVE>:\, 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<mtThread> {
+ // 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;
+}