hotspot/src/os/windows/vm/os_windows.cpp

Print this page
rev 611 : Merge

*** 1,10 **** - #ifdef USE_PRAGMA_IDENT_SRC - #pragma ident "@(#)os_windows.cpp 1.535 07/11/15 10:56:43 JVM" - #endif /* ! * Copyright 1997-2007 Sun Microsystems, Inc. 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. --- 1,7 ---- /* ! * Copyright 1997-2009 Sun Microsystems, Inc. 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.
*** 328,337 **** --- 325,342 ---- VirtualQuery(&minfo, &minfo, sizeof(minfo)); sz = (size_t)os::current_stack_base() - (size_t)minfo.AllocationBase; return sz; } + struct tm* os::localtime_pd(const time_t* clock, struct tm* res) { + const struct tm* time_struct_ptr = localtime(clock); + if (time_struct_ptr != NULL) { + *res = *time_struct_ptr; + return res; + } + return NULL; + } LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo); // Thread start routine for all new Java threads static unsigned __stdcall java_start(Thread* thread) {
*** 738,761 **** result.dwHighDateTime = high(a); result.dwLowDateTime = low(a); return result; } ! jlong os::timeofday() { ! FILETIME wt; ! GetSystemTimeAsFileTime(&wt); ! return windows_to_java_time(wt); ! } - // Must return millis since Jan 1 1970 for JVM_CurrentTimeMillis - // _use_global_time is only set if CacheTimeMillis is true jlong os::javaTimeMillis() { if (UseFakeTimers) { return fake_time++; } else { ! return (_use_global_time ? read_global_time() : timeofday()); } } #define NANOS_PER_SEC CONST64(1000000000) #define NANOS_PER_MILLISEC 1000000 --- 743,770 ---- result.dwHighDateTime = high(a); result.dwLowDateTime = low(a); return result; } ! // For now, we say that Windows does not support vtime. I have no idea ! // whether it can actually be made to (DLD, 9/13/05). + bool os::supports_vtime() { return false; } + bool os::enable_vtime() { return false; } + bool os::vtime_enabled() { return false; } + double os::elapsedVTime() { + // better than nothing, but not much + return elapsedTime(); + } jlong os::javaTimeMillis() { if (UseFakeTimers) { return fake_time++; } else { ! FILETIME wt; ! GetSystemTimeAsFileTime(&wt); ! return windows_to_java_time(wt); } } #define NANOS_PER_SEC CONST64(1000000000) #define NANOS_PER_MILLISEC 1000000
*** 993,1002 **** --- 1002,1068 ---- path_buf[0]='\0'; return path_buf; } } + static bool file_exists(const char* filename) { + if (filename == NULL || strlen(filename) == 0) { + return false; + } + return GetFileAttributes(filename) != INVALID_FILE_ATTRIBUTES; + } + + void os::dll_build_name(char *buffer, size_t buflen, + const char* pname, const char* fname) { + // Copied from libhpi + const size_t pnamelen = pname ? strlen(pname) : 0; + const char c = (pnamelen > 0) ? pname[pnamelen-1] : 0; + + // Quietly truncates on buffer overflow. Should be an error. + if (pnamelen + strlen(fname) + 10 > buflen) { + *buffer = '\0'; + return; + } + + if (pnamelen == 0) { + jio_snprintf(buffer, buflen, "%s.dll", fname); + } else if (c == ':' || c == '\\') { + jio_snprintf(buffer, buflen, "%s%s.dll", pname, fname); + } else if (strchr(pname, *os::path_separator()) != NULL) { + int n; + char** pelements = split_path(pname, &n); + for (int i = 0 ; i < n ; i++) { + char* path = pelements[i]; + // Really shouldn't be NULL, but check can't hurt + size_t plen = (path == NULL) ? 0 : strlen(path); + if (plen == 0) { + continue; // skip the empty path values + } + const char lastchar = path[plen - 1]; + if (lastchar == ':' || lastchar == '\\') { + jio_snprintf(buffer, buflen, "%s%s.dll", path, fname); + } else { + jio_snprintf(buffer, buflen, "%s\\%s.dll", path, fname); + } + if (file_exists(buffer)) { + break; + } + } + // release the storage + for (int i = 0 ; i < n ; i++) { + if (pelements[i] != NULL) { + FREE_C_HEAP_ARRAY(char, pelements[i]); + } + } + if (pelements != NULL) { + FREE_C_HEAP_ARRAY(char*, pelements); + } + } else { + jio_snprintf(buffer, buflen, "%s\\%s.dll", pname, fname); + } + } + // Needs to be in os specific directory because windows requires another // header file <direct.h> const char* os::get_current_directory(char *buf, int buflen) { return _getcwd(buf, buflen); }
*** 1256,1265 **** --- 1322,1335 ---- if (offset) *offset = -1; if (buf) buf[0] = '\0'; return false; } + void* os::dll_lookup(void* handle, const char* name) { + return GetProcAddress((HMODULE)handle, name); + } + // save the start and end address of jvm.dll into param[0] and param[1] static int _locate_jvm_dll(int pid, char* mod_fname, address base_addr, unsigned size, void * param) { if (!param) return -1;
*** 1429,1438 **** --- 1499,1512 ---- int pid = os::current_process_id(); st->print_cr("Dynamic libraries:"); enumerate_modules(pid, _print_module, (void *)st); } + // function pointer to Windows API "GetNativeSystemInfo". + typedef void (WINAPI *GetNativeSystemInfo_func_type)(LPSYSTEM_INFO); + static GetNativeSystemInfo_func_type _GetNativeSystemInfo; + void os::print_os_info(outputStream* st) { st->print("OS:"); OSVERSIONINFOEX osvi; ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
*** 1442,1460 **** st->print_cr("N/A"); return; } int os_vers = osvi.dwMajorVersion * 1000 + osvi.dwMinorVersion; - if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT) { switch (os_vers) { case 3051: st->print(" Windows NT 3.51"); break; case 4000: st->print(" Windows NT 4.0"); break; case 5000: st->print(" Windows 2000"); break; case 5001: st->print(" Windows XP"); break; ! case 5002: st->print(" Windows Server 2003 family"); break; ! case 6000: st->print(" Windows Vista"); break; default: // future windows, print out its major and minor versions st->print(" Windows NT %d.%d", osvi.dwMajorVersion, osvi.dwMinorVersion); } } else { switch (os_vers) { --- 1516,1575 ---- st->print_cr("N/A"); return; } int os_vers = osvi.dwMajorVersion * 1000 + osvi.dwMinorVersion; if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT) { switch (os_vers) { case 3051: st->print(" Windows NT 3.51"); break; case 4000: st->print(" Windows NT 4.0"); break; case 5000: st->print(" Windows 2000"); break; case 5001: st->print(" Windows XP"); break; ! case 5002: ! case 6000: ! case 6001: { ! // Retrieve SYSTEM_INFO from GetNativeSystemInfo call so that we could ! // find out whether we are running on 64 bit processor or not. ! SYSTEM_INFO si; ! ZeroMemory(&si, sizeof(SYSTEM_INFO)); ! // Check to see if _GetNativeSystemInfo has been initialized. ! if (_GetNativeSystemInfo == NULL) { ! HMODULE hKernel32 = GetModuleHandle(TEXT("kernel32.dll")); ! _GetNativeSystemInfo = ! CAST_TO_FN_PTR(GetNativeSystemInfo_func_type, ! GetProcAddress(hKernel32, ! "GetNativeSystemInfo")); ! if (_GetNativeSystemInfo == NULL) ! GetSystemInfo(&si); ! } else { ! _GetNativeSystemInfo(&si); ! } ! if (os_vers == 5002) { ! if (osvi.wProductType == VER_NT_WORKSTATION && ! si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) ! st->print(" Windows XP x64 Edition"); ! else ! st->print(" Windows Server 2003 family"); ! } else if (os_vers == 6000) { ! if (osvi.wProductType == VER_NT_WORKSTATION) ! st->print(" Windows Vista"); ! else ! st->print(" Windows Server 2008"); ! if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) ! st->print(" , 64 bit"); ! } else { // os_vers == 6001 ! if (osvi.wProductType == VER_NT_WORKSTATION) { ! st->print(" Windows 7"); ! } else { ! // Unrecognized windows, print out its major and minor versions ! st->print(" Windows NT %d.%d", osvi.dwMajorVersion, osvi.dwMinorVersion); ! } ! if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) ! st->print(" , 64 bit"); ! } ! break; ! } default: // future windows, print out its major and minor versions st->print(" Windows NT %d.%d", osvi.dwMajorVersion, osvi.dwMinorVersion); } } else { switch (os_vers) {
*** 1463,1473 **** case 4090: st->print(" Windows Me"); break; default: // future windows, print out its major and minor versions st->print(" Windows %d.%d", osvi.dwMajorVersion, osvi.dwMinorVersion); } } - st->print(" Build %d", osvi.dwBuildNumber); st->print(" %s", osvi.szCSDVersion); // service pack st->cr(); } --- 1578,1587 ----
*** 1957,1970 **** // In conservative mode, don't unguard unless the address is in the VM if (UnguardOnExecutionViolation > 0 && addr != last_addr && (UnguardOnExecutionViolation > 1 || os::address_is_in_vm(addr))) { ! // Unguard and retry address page_start = (address) align_size_down((intptr_t) addr, (intptr_t) page_size); ! bool res = os::unguard_memory((char*) page_start, page_size); if (PrintMiscellaneous && Verbose) { char buf[256]; jio_snprintf(buf, sizeof(buf), "Execution protection violation " "at " INTPTR_FORMAT --- 2071,2085 ---- // In conservative mode, don't unguard unless the address is in the VM if (UnguardOnExecutionViolation > 0 && addr != last_addr && (UnguardOnExecutionViolation > 1 || os::address_is_in_vm(addr))) { ! // Set memory to RWX and retry address page_start = (address) align_size_down((intptr_t) addr, (intptr_t) page_size); ! bool res = os::protect_memory((char*) page_start, page_size, ! os::MEM_PROT_RWX); if (PrintMiscellaneous && Verbose) { char buf[256]; jio_snprintf(buf, sizeof(buf), "Execution protection violation " "at " INTPTR_FORMAT
*** 2154,2172 **** // // Check for implicit null // We only expect null pointers in the stubs (vtable) // the rest are checked explicitly now. // - CodeBlob* cb = CodeCache::find_blob(pc); - if (cb != NULL) { - if (VtableStubs::stub_containing(pc) != NULL) { if (((uintptr_t)addr) < os::vm_page_size() ) { // an access to the first page of VM--assume it is a null pointer ! return Handle_Exception(exceptionInfo, ! SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL)); ! } ! } } } } // in_java // IA64 doesn't use implicit null checking yet. So we shouldn't --- 2269,2282 ---- // // Check for implicit null // We only expect null pointers in the stubs (vtable) // the rest are checked explicitly now. // if (((uintptr_t)addr) < os::vm_page_size() ) { // an access to the first page of VM--assume it is a null pointer ! address stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL); ! if (stub != NULL) return Handle_Exception(exceptionInfo, stub); } } } // in_java // IA64 doesn't use implicit null checking yet. So we shouldn't
*** 2178,2189 **** #else /* !IA64 */ // Windows 98 reports faulting addresses incorrectly if (!MacroAssembler::needs_explicit_null_check((intptr_t)addr) || !os::win32::is_nt()) { ! return Handle_Exception(exceptionInfo, ! SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL)); } report_error(t, exception_code, pc, exceptionInfo->ExceptionRecord, exceptionInfo->ContextRecord); return EXCEPTION_CONTINUE_SEARCH; #endif --- 2288,2299 ---- #else /* !IA64 */ // Windows 98 reports faulting addresses incorrectly if (!MacroAssembler::needs_explicit_null_check((intptr_t)addr) || !os::win32::is_nt()) { ! address stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL); ! if (stub != NULL) return Handle_Exception(exceptionInfo, stub); } report_error(t, exception_code, pc, exceptionInfo->ExceptionRecord, exceptionInfo->ContextRecord); return EXCEPTION_CONTINUE_SEARCH; #endif
*** 2524,2537 **** // and committed in a single VirtualAlloc() call. This may change in the // future, but with Windows 2003 it's not possible to commit on demand. return false; } char* os::reserve_memory_special(size_t bytes) { DWORD flag = MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES; ! char * res = (char *)VirtualAlloc(NULL, bytes, flag, PAGE_READWRITE); return res; } bool os::release_memory_special(char* base, size_t bytes) { return release_memory(base, bytes); } --- 2634,2746 ---- // and committed in a single VirtualAlloc() call. This may change in the // future, but with Windows 2003 it's not possible to commit on demand. return false; } + bool os::can_execute_large_page_memory() { + return true; + } + char* os::reserve_memory_special(size_t bytes) { + + if (UseLargePagesIndividualAllocation) { + if (TracePageSizes && Verbose) { + tty->print_cr("Reserving large pages individually."); + } + char * p_buf; + // first reserve enough address space in advance since we want to be + // able to break a single contiguous virtual address range into multiple + // large page commits but WS2003 does not allow reserving large page space + // so we just use 4K pages for reserve, this gives us a legal contiguous + // address space. then we will deallocate that reservation, and re alloc + // using large pages + const size_t size_of_reserve = bytes + _large_page_size; + if (bytes > size_of_reserve) { + // Overflowed. + warning("Individually allocated large pages failed, " + "use -XX:-UseLargePagesIndividualAllocation to turn off"); + return NULL; + } + p_buf = (char *) VirtualAlloc(NULL, + size_of_reserve, // size of Reserve + MEM_RESERVE, + PAGE_EXECUTE_READWRITE); + // If reservation failed, return NULL + if (p_buf == NULL) return NULL; + + release_memory(p_buf, bytes + _large_page_size); + // round up to page boundary. If the size_of_reserve did not + // overflow and the reservation did not fail, this align up + // should not overflow. + p_buf = (char *) align_size_up((size_t)p_buf, _large_page_size); + + // now go through and allocate one page at a time until all bytes are + // allocated + size_t bytes_remaining = align_size_up(bytes, _large_page_size); + // An overflow of align_size_up() would have been caught above + // in the calculation of size_of_reserve. + char * next_alloc_addr = p_buf; + + #ifdef ASSERT + // Variable for the failure injection + long ran_num = os::random(); + size_t fail_after = ran_num % bytes; + #endif + + while (bytes_remaining) { + size_t bytes_to_rq = MIN2(bytes_remaining, _large_page_size); + // Note allocate and commit + char * p_new; + + #ifdef ASSERT + bool inject_error = LargePagesIndividualAllocationInjectError && + (bytes_remaining <= fail_after); + #else + const bool inject_error = false; + #endif + + if (inject_error) { + p_new = NULL; + } else { + p_new = (char *) VirtualAlloc(next_alloc_addr, + bytes_to_rq, + MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES, + PAGE_EXECUTE_READWRITE); + } + + if (p_new == NULL) { + // Free any allocated pages + if (next_alloc_addr > p_buf) { + // Some memory was committed so release it. + size_t bytes_to_release = bytes - bytes_remaining; + release_memory(p_buf, bytes_to_release); + } + #ifdef ASSERT + if (UseLargePagesIndividualAllocation && + LargePagesIndividualAllocationInjectError) { + if (TracePageSizes && Verbose) { + tty->print_cr("Reserving large pages individually failed."); + } + } + #endif + return NULL; + } + bytes_remaining -= bytes_to_rq; + next_alloc_addr += bytes_to_rq; + } + + return p_buf; + + } else { + // normal policy just allocate it all at once DWORD flag = MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES; ! char * res = (char *)VirtualAlloc(NULL, ! bytes, ! flag, ! PAGE_EXECUTE_READWRITE); return res; + } } bool os::release_memory_special(char* base, size_t bytes) { return release_memory(base, bytes); }
*** 2567,2595 **** bool os::release_memory(char* addr, size_t bytes) { return VirtualFree(addr, 0, MEM_RELEASE) != 0; } ! bool os::protect_memory(char* addr, size_t bytes) { DWORD old_status; ! return VirtualProtect(addr, bytes, PAGE_READONLY, &old_status) != 0; } bool os::guard_memory(char* addr, size_t bytes) { DWORD old_status; ! return VirtualProtect(addr, bytes, PAGE_EXECUTE_READWRITE | PAGE_GUARD, &old_status) != 0; } bool os::unguard_memory(char* addr, size_t bytes) { DWORD old_status; ! return VirtualProtect(addr, bytes, PAGE_EXECUTE_READWRITE, &old_status) != 0; } void os::realign_memory(char *addr, size_t bytes, size_t alignment_hint) { } void os::free_memory(char *addr, size_t bytes) { } void os::numa_make_global(char *addr, size_t bytes) { } ! void os::numa_make_local(char *addr, size_t bytes) { } bool os::numa_topology_changed() { return false; } size_t os::numa_get_groups_num() { return 1; } int os::numa_get_group_id() { return 0; } size_t os::numa_get_leaf_groups(int *ids, size_t size) { if (size > 0) { --- 2776,2828 ---- bool os::release_memory(char* addr, size_t bytes) { return VirtualFree(addr, 0, MEM_RELEASE) != 0; } ! // Set protections specified ! bool os::protect_memory(char* addr, size_t bytes, ProtType prot, ! bool is_committed) { ! unsigned int p = 0; ! switch (prot) { ! case MEM_PROT_NONE: p = PAGE_NOACCESS; break; ! case MEM_PROT_READ: p = PAGE_READONLY; break; ! case MEM_PROT_RW: p = PAGE_READWRITE; break; ! case MEM_PROT_RWX: p = PAGE_EXECUTE_READWRITE; break; ! default: ! ShouldNotReachHere(); ! } ! DWORD old_status; ! ! // Strange enough, but on Win32 one can change protection only for committed ! // memory, not a big deal anyway, as bytes less or equal than 64K ! if (!is_committed && !commit_memory(addr, bytes)) { ! fatal("cannot commit protection page"); ! } ! // One cannot use os::guard_memory() here, as on Win32 guard page ! // have different (one-shot) semantics, from MSDN on PAGE_GUARD: ! // ! // Pages in the region become guard pages. Any attempt to access a guard page ! // causes the system to raise a STATUS_GUARD_PAGE exception and turn off ! // the guard page status. Guard pages thus act as a one-time access alarm. ! return VirtualProtect(addr, bytes, p, &old_status) != 0; } bool os::guard_memory(char* addr, size_t bytes) { DWORD old_status; ! return VirtualProtect(addr, bytes, PAGE_READWRITE | PAGE_GUARD, &old_status) != 0; } bool os::unguard_memory(char* addr, size_t bytes) { DWORD old_status; ! return VirtualProtect(addr, bytes, PAGE_READWRITE, &old_status) != 0; } void os::realign_memory(char *addr, size_t bytes, size_t alignment_hint) { } void os::free_memory(char *addr, size_t bytes) { } void os::numa_make_global(char *addr, size_t bytes) { } ! void os::numa_make_local(char *addr, size_t bytes, int lgrp_hint) { } bool os::numa_topology_changed() { return false; } size_t os::numa_get_groups_num() { return 1; } int os::numa_get_group_id() { return 0; } size_t os::numa_get_leaf_groups(int *ids, size_t size) { if (size > 0) {
*** 2891,2900 **** --- 3124,3134 ---- intx os::win32::_os_thread_limit = 0; volatile intx os::win32::_os_thread_count = 0; bool os::win32::_is_nt = false; + bool os::win32::_is_windows_2003 = false; void os::win32::initialize_system_info() { SYSTEM_INFO si; GetSystemInfo(&si);
*** 2913,2923 **** OSVERSIONINFO oi; oi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&oi); switch(oi.dwPlatformId) { case VER_PLATFORM_WIN32_WINDOWS: _is_nt = false; break; ! case VER_PLATFORM_WIN32_NT: _is_nt = true; break; default: fatal("Unknown platform"); } _default_stack_size = os::current_stack_size(); assert(_default_stack_size > (size_t) _vm_page_size, "invalid stack size"); --- 3147,3165 ---- OSVERSIONINFO oi; oi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&oi); switch(oi.dwPlatformId) { case VER_PLATFORM_WIN32_WINDOWS: _is_nt = false; break; ! case VER_PLATFORM_WIN32_NT: ! _is_nt = true; ! { ! int os_vers = oi.dwMajorVersion * 1000 + oi.dwMinorVersion; ! if (os_vers == 5002) { ! _is_windows_2003 = true; ! } ! } ! break; default: fatal("Unknown platform"); } _default_stack_size = os::current_stack_size(); assert(_default_stack_size > (size_t) _vm_page_size, "invalid stack size");
*** 3011,3020 **** --- 3253,3266 ---- #ifndef PRODUCT if (is_MP()) { NoYieldsInMicrolock = true; } #endif + // This may be overridden later when argument processing is done. + FLAG_SET_ERGO(bool, UseLargePagesIndividualAllocation, + os::win32::is_windows_2003()); + // Initialize main_process and main_thread main_process = GetCurrentProcess(); // Remember main_process is a pseudo handle if (!DuplicateHandle(main_process, GetCurrentThread(), main_process, &main_thread, THREAD_ALL_ACCESS, false, 0)) { fatal("DuplicateHandle failed\n");
*** 3120,3130 **** // // TODO: consider performing a similar calculation for commit size instead // as reserve size, since on a 64-bit platform we'll run into that more // often than running out of virtual memory space. We can use the // lower value of the two calculations as the os_thread_limit. ! size_t max_address_space = ((size_t)1 << (BitsPerOop - 1)) - (200 * K * K); win32::_os_thread_limit = (intx)(max_address_space / actual_reserve_size); // at exit methods are called in the reverse order of their registration. // there is no limit to the number of functions registered. atexit does // not set errno. --- 3366,3376 ---- // // TODO: consider performing a similar calculation for commit size instead // as reserve size, since on a 64-bit platform we'll run into that more // often than running out of virtual memory space. We can use the // lower value of the two calculations as the os_thread_limit. ! size_t max_address_space = ((size_t)1 << (BitsPerWord - 1)) - (200 * K * K); win32::_os_thread_limit = (intx)(max_address_space / actual_reserve_size); // at exit methods are called in the reverse order of their registration. // there is no limit to the number of functions registered. atexit does // not set errno.
*** 3153,3162 **** --- 3399,3412 ---- #endif // initialize thread priority policy prio_init(); + if (UseNUMA && !ForceNUMA) { + UseNUMA = false; // Currently unsupported. + } + return JNI_OK; } // Mark the polling page as unreadable