Path: blob/master/src/hotspot/os/windows/os_windows.cpp
40930 views
/*1* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324// Must be at least Windows Vista or Server 2008 to use InitOnceExecuteOnce25#define _WIN32_WINNT 0x06002627// no precompiled headers28#include "jvm.h"29#include "classfile/vmSymbols.hpp"30#include "code/codeCache.hpp"31#include "code/icBuffer.hpp"32#include "code/nativeInst.hpp"33#include "code/vtableStubs.hpp"34#include "compiler/compileBroker.hpp"35#include "compiler/disassembler.hpp"36#include "interpreter/interpreter.hpp"37#include "jvmtifiles/jvmti.h"38#include "logging/log.hpp"39#include "logging/logStream.hpp"40#include "memory/allocation.inline.hpp"41#include "oops/oop.inline.hpp"42#include "os_share_windows.hpp"43#include "os_windows.inline.hpp"44#include "prims/jniFastGetField.hpp"45#include "prims/jvm_misc.hpp"46#include "runtime/arguments.hpp"47#include "runtime/atomic.hpp"48#include "runtime/globals.hpp"49#include "runtime/globals_extension.hpp"50#include "runtime/interfaceSupport.inline.hpp"51#include "runtime/java.hpp"52#include "runtime/javaCalls.hpp"53#include "runtime/mutexLocker.hpp"54#include "runtime/objectMonitor.hpp"55#include "runtime/orderAccess.hpp"56#include "runtime/osThread.hpp"57#include "runtime/perfMemory.hpp"58#include "runtime/safefetch.inline.hpp"59#include "runtime/safepointMechanism.hpp"60#include "runtime/semaphore.inline.hpp"61#include "runtime/sharedRuntime.hpp"62#include "runtime/statSampler.hpp"63#include "runtime/thread.inline.hpp"64#include "runtime/threadCritical.hpp"65#include "runtime/timer.hpp"66#include "runtime/vm_version.hpp"67#include "services/attachListener.hpp"68#include "services/memTracker.hpp"69#include "services/runtimeService.hpp"70#include "utilities/align.hpp"71#include "utilities/decoder.hpp"72#include "utilities/defaultStream.hpp"73#include "utilities/events.hpp"74#include "utilities/macros.hpp"75#include "utilities/vmError.hpp"76#include "symbolengine.hpp"77#include "windbghelp.hpp"7879#ifdef _DEBUG80#include <crtdbg.h>81#endif8283#include <windows.h>84#include <sys/types.h>85#include <sys/stat.h>86#include <sys/timeb.h>87#include <objidl.h>88#include <shlobj.h>8990#include <malloc.h>91#include <signal.h>92#include <direct.h>93#include <errno.h>94#include <fcntl.h>95#include <io.h>96#include <process.h> // For _beginthreadex(), _endthreadex()97#include <imagehlp.h> // For os::dll_address_to_function_name98// for enumerating dll libraries99#include <vdmdbg.h>100#include <psapi.h>101#include <mmsystem.h>102#include <winsock2.h>103104// for timer info max values which include all bits105#define ALL_64_BITS CONST64(-1)106107// For DLL loading/load error detection108// Values of PE COFF109#define IMAGE_FILE_PTR_TO_SIGNATURE 0x3c110#define IMAGE_FILE_SIGNATURE_LENGTH 4111112static HANDLE main_process;113static HANDLE main_thread;114static int main_thread_id;115116static FILETIME process_creation_time;117static FILETIME process_exit_time;118static FILETIME process_user_time;119static FILETIME process_kernel_time;120121#if defined(_M_ARM64)122#define __CPU__ aarch64123#elif defined(_M_AMD64)124#define __CPU__ amd64125#else126#define __CPU__ i486127#endif128129#if defined(USE_VECTORED_EXCEPTION_HANDLING)130PVOID topLevelVectoredExceptionHandler = NULL;131LPTOP_LEVEL_EXCEPTION_FILTER previousUnhandledExceptionFilter = NULL;132#endif133134// save DLL module handle, used by GetModuleFileName135136HINSTANCE vm_lib_handle;137138BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, LPVOID reserved) {139switch (reason) {140case DLL_PROCESS_ATTACH:141vm_lib_handle = hinst;142if (ForceTimeHighResolution) {143timeBeginPeriod(1L);144}145WindowsDbgHelp::pre_initialize();146SymbolEngine::pre_initialize();147break;148case DLL_PROCESS_DETACH:149if (ForceTimeHighResolution) {150timeEndPeriod(1L);151}152#if defined(USE_VECTORED_EXCEPTION_HANDLING)153if (topLevelVectoredExceptionHandler != NULL) {154RemoveVectoredExceptionHandler(topLevelVectoredExceptionHandler);155topLevelVectoredExceptionHandler = NULL;156}157#endif158break;159default:160break;161}162return true;163}164165static inline double fileTimeAsDouble(FILETIME* time) {166const double high = (double) ((unsigned int) ~0);167const double split = 10000000.0;168double result = (time->dwLowDateTime / split) +169time->dwHighDateTime * (high/split);170return result;171}172173// Implementation of os174175#define RANGE_FORMAT "[" PTR_FORMAT "-" PTR_FORMAT ")"176#define RANGE_FORMAT_ARGS(p, len) p2i(p), p2i((address)p + len)177178// A number of wrappers for more frequently used system calls, to add standard logging.179180struct PreserveLastError {181const DWORD v;182PreserveLastError() : v(::GetLastError()) {}183~PreserveLastError() { ::SetLastError(v); }184};185186// Logging wrapper for VirtualAlloc187static LPVOID virtualAlloc(LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect) {188LPVOID result = ::VirtualAlloc(lpAddress, dwSize, flAllocationType, flProtect);189if (result != NULL) {190log_trace(os)("VirtualAlloc(" PTR_FORMAT ", " SIZE_FORMAT ", %x, %x) returned " PTR_FORMAT "%s.",191p2i(lpAddress), dwSize, flAllocationType, flProtect, p2i(result),192((lpAddress != NULL && result != lpAddress) ? " <different base!>" : ""));193} else {194PreserveLastError ple;195log_info(os)("VirtualAlloc(" PTR_FORMAT ", " SIZE_FORMAT ", %x, %x) failed (%u).",196p2i(lpAddress), dwSize, flAllocationType, flProtect, ple.v);197}198return result;199}200201// Logging wrapper for VirtualFree202static BOOL virtualFree(LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType) {203BOOL result = ::VirtualFree(lpAddress, dwSize, dwFreeType);204if (result != FALSE) {205log_trace(os)("VirtualFree(" PTR_FORMAT ", " SIZE_FORMAT ", %x) succeeded",206p2i(lpAddress), dwSize, dwFreeType);207} else {208PreserveLastError ple;209log_info(os)("VirtualFree(" PTR_FORMAT ", " SIZE_FORMAT ", %x) failed (%u).",210p2i(lpAddress), dwSize, dwFreeType, ple.v);211}212return result;213}214215// Logging wrapper for VirtualAllocExNuma216static LPVOID virtualAllocExNuma(HANDLE hProcess, LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType,217DWORD flProtect, DWORD nndPreferred) {218LPVOID result = ::VirtualAllocExNuma(hProcess, lpAddress, dwSize, flAllocationType, flProtect, nndPreferred);219if (result != NULL) {220log_trace(os)("VirtualAllocExNuma(" PTR_FORMAT ", " SIZE_FORMAT ", %x, %x, %x) returned " PTR_FORMAT "%s.",221p2i(lpAddress), dwSize, flAllocationType, flProtect, nndPreferred, p2i(result),222((lpAddress != NULL && result != lpAddress) ? " <different base!>" : ""));223} else {224PreserveLastError ple;225log_info(os)("VirtualAllocExNuma(" PTR_FORMAT ", " SIZE_FORMAT ", %x, %x, %x) failed (%u).",226p2i(lpAddress), dwSize, flAllocationType, flProtect, nndPreferred, ple.v);227}228return result;229}230231// Logging wrapper for MapViewOfFileEx232static LPVOID mapViewOfFileEx(HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh,233DWORD dwFileOffsetLow, SIZE_T dwNumberOfBytesToMap, LPVOID lpBaseAddress) {234LPVOID result = ::MapViewOfFileEx(hFileMappingObject, dwDesiredAccess, dwFileOffsetHigh,235dwFileOffsetLow, dwNumberOfBytesToMap, lpBaseAddress);236if (result != NULL) {237log_trace(os)("MapViewOfFileEx(" PTR_FORMAT ", " SIZE_FORMAT ") returned " PTR_FORMAT "%s.",238p2i(lpBaseAddress), dwNumberOfBytesToMap, p2i(result),239((lpBaseAddress != NULL && result != lpBaseAddress) ? " <different base!>" : ""));240} else {241PreserveLastError ple;242log_info(os)("MapViewOfFileEx(" PTR_FORMAT ", " SIZE_FORMAT ") failed (%u).",243p2i(lpBaseAddress), dwNumberOfBytesToMap, ple.v);244}245return result;246}247248// Logging wrapper for UnmapViewOfFile249static BOOL unmapViewOfFile(LPCVOID lpBaseAddress) {250BOOL result = ::UnmapViewOfFile(lpBaseAddress);251if (result != FALSE) {252log_trace(os)("UnmapViewOfFile(" PTR_FORMAT ") succeeded", p2i(lpBaseAddress));253} else {254PreserveLastError ple;255log_info(os)("UnmapViewOfFile(" PTR_FORMAT ") failed (%u).", p2i(lpBaseAddress), ple.v);256}257return result;258}259260bool os::unsetenv(const char* name) {261assert(name != NULL, "Null pointer");262return (SetEnvironmentVariable(name, NULL) == TRUE);263}264265char** os::get_environ() { return _environ; }266267// No setuid programs under Windows.268bool os::have_special_privileges() {269return false;270}271272273// This method is a periodic task to check for misbehaving JNI applications274// under CheckJNI, we can add any periodic checks here.275// For Windows at the moment does nothing276void os::run_periodic_checks() {277return;278}279280// previous UnhandledExceptionFilter, if there is one281static LPTOP_LEVEL_EXCEPTION_FILTER prev_uef_handler = NULL;282283LONG WINAPI Handle_FLT_Exception(struct _EXCEPTION_POINTERS* exceptionInfo);284285void os::init_system_properties_values() {286// sysclasspath, java_home, dll_dir287{288char *home_path;289char *dll_path;290char *pslash;291const char *bin = "\\bin";292char home_dir[MAX_PATH + 1];293char *alt_home_dir = ::getenv("_ALT_JAVA_HOME_DIR");294295if (alt_home_dir != NULL) {296strncpy(home_dir, alt_home_dir, MAX_PATH + 1);297home_dir[MAX_PATH] = '\0';298} else {299os::jvm_path(home_dir, sizeof(home_dir));300// Found the full path to jvm.dll.301// Now cut the path to <java_home>/jre if we can.302*(strrchr(home_dir, '\\')) = '\0'; // get rid of \jvm.dll303pslash = strrchr(home_dir, '\\');304if (pslash != NULL) {305*pslash = '\0'; // get rid of \{client|server}306pslash = strrchr(home_dir, '\\');307if (pslash != NULL) {308*pslash = '\0'; // get rid of \bin309}310}311}312313home_path = NEW_C_HEAP_ARRAY(char, strlen(home_dir) + 1, mtInternal);314strcpy(home_path, home_dir);315Arguments::set_java_home(home_path);316FREE_C_HEAP_ARRAY(char, home_path);317318dll_path = NEW_C_HEAP_ARRAY(char, strlen(home_dir) + strlen(bin) + 1,319mtInternal);320strcpy(dll_path, home_dir);321strcat(dll_path, bin);322Arguments::set_dll_dir(dll_path);323FREE_C_HEAP_ARRAY(char, dll_path);324325if (!set_boot_path('\\', ';')) {326vm_exit_during_initialization("Failed setting boot class path.", NULL);327}328}329330// library_path331#define EXT_DIR "\\lib\\ext"332#define BIN_DIR "\\bin"333#define PACKAGE_DIR "\\Sun\\Java"334{335// Win32 library search order (See the documentation for LoadLibrary):336//337// 1. The directory from which application is loaded.338// 2. The system wide Java Extensions directory (Java only)339// 3. System directory (GetSystemDirectory)340// 4. Windows directory (GetWindowsDirectory)341// 5. The PATH environment variable342// 6. The current directory343344char *library_path;345char tmp[MAX_PATH];346char *path_str = ::getenv("PATH");347348library_path = NEW_C_HEAP_ARRAY(char, MAX_PATH * 5 + sizeof(PACKAGE_DIR) +349sizeof(BIN_DIR) + (path_str ? strlen(path_str) : 0) + 10, mtInternal);350351library_path[0] = '\0';352353GetModuleFileName(NULL, tmp, sizeof(tmp));354*(strrchr(tmp, '\\')) = '\0';355strcat(library_path, tmp);356357GetWindowsDirectory(tmp, sizeof(tmp));358strcat(library_path, ";");359strcat(library_path, tmp);360strcat(library_path, PACKAGE_DIR BIN_DIR);361362GetSystemDirectory(tmp, sizeof(tmp));363strcat(library_path, ";");364strcat(library_path, tmp);365366GetWindowsDirectory(tmp, sizeof(tmp));367strcat(library_path, ";");368strcat(library_path, tmp);369370if (path_str) {371strcat(library_path, ";");372strcat(library_path, path_str);373}374375strcat(library_path, ";.");376377Arguments::set_library_path(library_path);378FREE_C_HEAP_ARRAY(char, library_path);379}380381// Default extensions directory382{383char path[MAX_PATH];384char buf[2 * MAX_PATH + 2 * sizeof(EXT_DIR) + sizeof(PACKAGE_DIR) + 1];385GetWindowsDirectory(path, MAX_PATH);386sprintf(buf, "%s%s;%s%s%s", Arguments::get_java_home(), EXT_DIR,387path, PACKAGE_DIR, EXT_DIR);388Arguments::set_ext_dirs(buf);389}390#undef EXT_DIR391#undef BIN_DIR392#undef PACKAGE_DIR393394#ifndef _WIN64395// set our UnhandledExceptionFilter and save any previous one396prev_uef_handler = SetUnhandledExceptionFilter(Handle_FLT_Exception);397#endif398399// Done400return;401}402403void os::breakpoint() {404DebugBreak();405}406407// Invoked from the BREAKPOINT Macro408extern "C" void breakpoint() {409os::breakpoint();410}411412// RtlCaptureStackBackTrace Windows API may not exist prior to Windows XP.413// So far, this method is only used by Native Memory Tracking, which is414// only supported on Windows XP or later.415//416int os::get_native_stack(address* stack, int frames, int toSkip) {417int captured = RtlCaptureStackBackTrace(toSkip + 1, frames, (PVOID*)stack, NULL);418for (int index = captured; index < frames; index ++) {419stack[index] = NULL;420}421return captured;422}423424// os::current_stack_base()425//426// Returns the base of the stack, which is the stack's427// starting address. This function must be called428// while running on the stack of the thread being queried.429430address os::current_stack_base() {431MEMORY_BASIC_INFORMATION minfo;432address stack_bottom;433size_t stack_size;434435VirtualQuery(&minfo, &minfo, sizeof(minfo));436stack_bottom = (address)minfo.AllocationBase;437stack_size = minfo.RegionSize;438439// Add up the sizes of all the regions with the same440// AllocationBase.441while (1) {442VirtualQuery(stack_bottom+stack_size, &minfo, sizeof(minfo));443if (stack_bottom == (address)minfo.AllocationBase) {444stack_size += minfo.RegionSize;445} else {446break;447}448}449return stack_bottom + stack_size;450}451452size_t os::current_stack_size() {453size_t sz;454MEMORY_BASIC_INFORMATION minfo;455VirtualQuery(&minfo, &minfo, sizeof(minfo));456sz = (size_t)os::current_stack_base() - (size_t)minfo.AllocationBase;457return sz;458}459460bool os::committed_in_range(address start, size_t size, address& committed_start, size_t& committed_size) {461MEMORY_BASIC_INFORMATION minfo;462committed_start = NULL;463committed_size = 0;464address top = start + size;465const address start_addr = start;466while (start < top) {467VirtualQuery(start, &minfo, sizeof(minfo));468if ((minfo.State & MEM_COMMIT) == 0) { // not committed469if (committed_start != NULL) {470break;471}472} else { // committed473if (committed_start == NULL) {474committed_start = start;475}476size_t offset = start - (address)minfo.BaseAddress;477committed_size += minfo.RegionSize - offset;478}479start = (address)minfo.BaseAddress + minfo.RegionSize;480}481482if (committed_start == NULL) {483assert(committed_size == 0, "Sanity");484return false;485} else {486assert(committed_start >= start_addr && committed_start < top, "Out of range");487// current region may go beyond the limit, trim to the limit488committed_size = MIN2(committed_size, size_t(top - committed_start));489return true;490}491}492493struct tm* os::localtime_pd(const time_t* clock, struct tm* res) {494const struct tm* time_struct_ptr = localtime(clock);495if (time_struct_ptr != NULL) {496*res = *time_struct_ptr;497return res;498}499return NULL;500}501502struct tm* os::gmtime_pd(const time_t* clock, struct tm* res) {503const struct tm* time_struct_ptr = gmtime(clock);504if (time_struct_ptr != NULL) {505*res = *time_struct_ptr;506return res;507}508return NULL;509}510511JNIEXPORT512LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo);513514// Thread start routine for all newly created threads515static unsigned __stdcall thread_native_entry(Thread* thread) {516517thread->record_stack_base_and_size();518thread->initialize_thread_current();519520OSThread* osthr = thread->osthread();521assert(osthr->get_state() == RUNNABLE, "invalid os thread state");522523if (UseNUMA) {524int lgrp_id = os::numa_get_group_id();525if (lgrp_id != -1) {526thread->set_lgrp_id(lgrp_id);527}528}529530// Diagnostic code to investigate JDK-6573254531int res = 30115; // non-java thread532if (thread->is_Java_thread()) {533res = 20115; // java thread534}535536log_info(os, thread)("Thread is alive (tid: " UINTX_FORMAT ").", os::current_thread_id());537538#ifdef USE_VECTORED_EXCEPTION_HANDLING539// Any exception is caught by the Vectored Exception Handler, so VM can540// generate error dump when an exception occurred in non-Java thread541// (e.g. VM thread).542thread->call_run();543#else544// Install a win32 structured exception handler around every thread created545// by VM, so VM can generate error dump when an exception occurred in non-546// Java thread (e.g. VM thread).547__try {548thread->call_run();549} __except(topLevelExceptionFilter(550(_EXCEPTION_POINTERS*)_exception_info())) {551// Nothing to do.552}553#endif554555// Note: at this point the thread object may already have deleted itself.556// Do not dereference it from here on out.557558log_info(os, thread)("Thread finished (tid: " UINTX_FORMAT ").", os::current_thread_id());559560// One less thread is executing561// When the VMThread gets here, the main thread may have already exited562// which frees the CodeHeap containing the Atomic::add code563if (thread != VMThread::vm_thread() && VMThread::vm_thread() != NULL) {564Atomic::dec(&os::win32::_os_thread_count);565}566567// Thread must not return from exit_process_or_thread(), but if it does,568// let it proceed to exit normally569return (unsigned)os::win32::exit_process_or_thread(os::win32::EPT_THREAD, res);570}571572static OSThread* create_os_thread(Thread* thread, HANDLE thread_handle,573int thread_id) {574// Allocate the OSThread object575OSThread* osthread = new OSThread(NULL, NULL);576if (osthread == NULL) return NULL;577578// Initialize the JDK library's interrupt event.579// This should really be done when OSThread is constructed,580// but there is no way for a constructor to report failure to581// allocate the event.582HANDLE interrupt_event = CreateEvent(NULL, true, false, NULL);583if (interrupt_event == NULL) {584delete osthread;585return NULL;586}587osthread->set_interrupt_event(interrupt_event);588589// Store info on the Win32 thread into the OSThread590osthread->set_thread_handle(thread_handle);591osthread->set_thread_id(thread_id);592593if (UseNUMA) {594int lgrp_id = os::numa_get_group_id();595if (lgrp_id != -1) {596thread->set_lgrp_id(lgrp_id);597}598}599600// Initial thread state is INITIALIZED, not SUSPENDED601osthread->set_state(INITIALIZED);602603return osthread;604}605606607bool os::create_attached_thread(JavaThread* thread) {608#ifdef ASSERT609thread->verify_not_published();610#endif611HANDLE thread_h;612if (!DuplicateHandle(main_process, GetCurrentThread(), GetCurrentProcess(),613&thread_h, THREAD_ALL_ACCESS, false, 0)) {614fatal("DuplicateHandle failed\n");615}616OSThread* osthread = create_os_thread(thread, thread_h,617(int)current_thread_id());618if (osthread == NULL) {619return false;620}621622// Initial thread state is RUNNABLE623osthread->set_state(RUNNABLE);624625thread->set_osthread(osthread);626627log_info(os, thread)("Thread attached (tid: " UINTX_FORMAT ").",628os::current_thread_id());629630return true;631}632633bool os::create_main_thread(JavaThread* thread) {634#ifdef ASSERT635thread->verify_not_published();636#endif637if (_starting_thread == NULL) {638_starting_thread = create_os_thread(thread, main_thread, main_thread_id);639if (_starting_thread == NULL) {640return false;641}642}643644// The primordial thread is runnable from the start)645_starting_thread->set_state(RUNNABLE);646647thread->set_osthread(_starting_thread);648return true;649}650651// Helper function to trace _beginthreadex attributes,652// similar to os::Posix::describe_pthread_attr()653static char* describe_beginthreadex_attributes(char* buf, size_t buflen,654size_t stacksize, unsigned initflag) {655stringStream ss(buf, buflen);656if (stacksize == 0) {657ss.print("stacksize: default, ");658} else {659ss.print("stacksize: " SIZE_FORMAT "k, ", stacksize / 1024);660}661ss.print("flags: ");662#define PRINT_FLAG(f) if (initflag & f) ss.print( #f " ");663#define ALL(X) \664X(CREATE_SUSPENDED) \665X(STACK_SIZE_PARAM_IS_A_RESERVATION)666ALL(PRINT_FLAG)667#undef ALL668#undef PRINT_FLAG669return buf;670}671672// Allocate and initialize a new OSThread673bool os::create_thread(Thread* thread, ThreadType thr_type,674size_t stack_size) {675unsigned thread_id;676677// Allocate the OSThread object678OSThread* osthread = new OSThread(NULL, NULL);679if (osthread == NULL) {680return false;681}682683// Initialize the JDK library's interrupt event.684// This should really be done when OSThread is constructed,685// but there is no way for a constructor to report failure to686// allocate the event.687HANDLE interrupt_event = CreateEvent(NULL, true, false, NULL);688if (interrupt_event == NULL) {689delete osthread;690return false;691}692osthread->set_interrupt_event(interrupt_event);693// We don't call set_interrupted(false) as it will trip the assert in there694// as we are not operating on the current thread. We don't need to call it695// because the initial state is already correct.696697thread->set_osthread(osthread);698699if (stack_size == 0) {700switch (thr_type) {701case os::java_thread:702// Java threads use ThreadStackSize which default value can be changed with the flag -Xss703if (JavaThread::stack_size_at_create() > 0) {704stack_size = JavaThread::stack_size_at_create();705}706break;707case os::compiler_thread:708if (CompilerThreadStackSize > 0) {709stack_size = (size_t)(CompilerThreadStackSize * K);710break;711} // else fall through:712// use VMThreadStackSize if CompilerThreadStackSize is not defined713case os::vm_thread:714case os::pgc_thread:715case os::cgc_thread:716case os::asynclog_thread:717case os::watcher_thread:718if (VMThreadStackSize > 0) stack_size = (size_t)(VMThreadStackSize * K);719break;720}721}722723// Create the Win32 thread724//725// Contrary to what MSDN document says, "stack_size" in _beginthreadex()726// does not specify stack size. Instead, it specifies the size of727// initially committed space. The stack size is determined by728// PE header in the executable. If the committed "stack_size" is larger729// than default value in the PE header, the stack is rounded up to the730// nearest multiple of 1MB. For example if the launcher has default731// stack size of 320k, specifying any size less than 320k does not732// affect the actual stack size at all, it only affects the initial733// commitment. On the other hand, specifying 'stack_size' larger than734// default value may cause significant increase in memory usage, because735// not only the stack space will be rounded up to MB, but also the736// entire space is committed upfront.737//738// Finally Windows XP added a new flag 'STACK_SIZE_PARAM_IS_A_RESERVATION'739// for CreateThread() that can treat 'stack_size' as stack size. However we740// are not supposed to call CreateThread() directly according to MSDN741// document because JVM uses C runtime library. The good news is that the742// flag appears to work with _beginthredex() as well.743744const unsigned initflag = CREATE_SUSPENDED | STACK_SIZE_PARAM_IS_A_RESERVATION;745HANDLE thread_handle =746(HANDLE)_beginthreadex(NULL,747(unsigned)stack_size,748(unsigned (__stdcall *)(void*)) thread_native_entry,749thread,750initflag,751&thread_id);752753char buf[64];754if (thread_handle != NULL) {755log_info(os, thread)("Thread started (tid: %u, attributes: %s)",756thread_id, describe_beginthreadex_attributes(buf, sizeof(buf), stack_size, initflag));757} else {758log_warning(os, thread)("Failed to start thread - _beginthreadex failed (%s) for attributes: %s.",759os::errno_name(errno), describe_beginthreadex_attributes(buf, sizeof(buf), stack_size, initflag));760// Log some OS information which might explain why creating the thread failed.761log_info(os, thread)("Number of threads approx. running in the VM: %d", Threads::number_of_threads());762LogStream st(Log(os, thread)::info());763os::print_memory_info(&st);764}765766if (thread_handle == NULL) {767// Need to clean up stuff we've allocated so far768thread->set_osthread(NULL);769delete osthread;770return false;771}772773Atomic::inc(&os::win32::_os_thread_count);774775// Store info on the Win32 thread into the OSThread776osthread->set_thread_handle(thread_handle);777osthread->set_thread_id(thread_id);778779// Initial thread state is INITIALIZED, not SUSPENDED780osthread->set_state(INITIALIZED);781782// The thread is returned suspended (in state INITIALIZED), and is started higher up in the call chain783return true;784}785786787// Free Win32 resources related to the OSThread788void os::free_thread(OSThread* osthread) {789assert(osthread != NULL, "osthread not set");790791// We are told to free resources of the argument thread,792// but we can only really operate on the current thread.793assert(Thread::current()->osthread() == osthread,794"os::free_thread but not current thread");795796CloseHandle(osthread->thread_handle());797delete osthread;798}799800static jlong first_filetime;801static jlong initial_performance_count;802static jlong performance_frequency;803804805jlong as_long(LARGE_INTEGER x) {806jlong result = 0; // initialization to avoid warning807set_high(&result, x.HighPart);808set_low(&result, x.LowPart);809return result;810}811812813jlong os::elapsed_counter() {814LARGE_INTEGER count;815QueryPerformanceCounter(&count);816return as_long(count) - initial_performance_count;817}818819820jlong os::elapsed_frequency() {821return performance_frequency;822}823824825julong os::available_memory() {826return win32::available_memory();827}828829julong os::win32::available_memory() {830// Use GlobalMemoryStatusEx() because GlobalMemoryStatus() may return incorrect831// value if total memory is larger than 4GB832MEMORYSTATUSEX ms;833ms.dwLength = sizeof(ms);834GlobalMemoryStatusEx(&ms);835836return (julong)ms.ullAvailPhys;837}838839julong os::physical_memory() {840return win32::physical_memory();841}842843bool os::has_allocatable_memory_limit(size_t* limit) {844MEMORYSTATUSEX ms;845ms.dwLength = sizeof(ms);846GlobalMemoryStatusEx(&ms);847#ifdef _LP64848*limit = (size_t)ms.ullAvailVirtual;849return true;850#else851// Limit to 1400m because of the 2gb address space wall852*limit = MIN2((size_t)1400*M, (size_t)ms.ullAvailVirtual);853return true;854#endif855}856857int os::active_processor_count() {858// User has overridden the number of active processors859if (ActiveProcessorCount > 0) {860log_trace(os)("active_processor_count: "861"active processor count set by user : %d",862ActiveProcessorCount);863return ActiveProcessorCount;864}865866DWORD_PTR lpProcessAffinityMask = 0;867DWORD_PTR lpSystemAffinityMask = 0;868int proc_count = processor_count();869if (proc_count <= sizeof(UINT_PTR) * BitsPerByte &&870GetProcessAffinityMask(GetCurrentProcess(), &lpProcessAffinityMask, &lpSystemAffinityMask)) {871// Nof active processors is number of bits in process affinity mask872int bitcount = 0;873while (lpProcessAffinityMask != 0) {874lpProcessAffinityMask = lpProcessAffinityMask & (lpProcessAffinityMask-1);875bitcount++;876}877return bitcount;878} else {879return proc_count;880}881}882883uint os::processor_id() {884return (uint)GetCurrentProcessorNumber();885}886887void os::set_native_thread_name(const char *name) {888889// See: http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx890//891// Note that unfortunately this only works if the process892// is already attached to a debugger; debugger must observe893// the exception below to show the correct name.894895// If there is no debugger attached skip raising the exception896if (!IsDebuggerPresent()) {897return;898}899900const DWORD MS_VC_EXCEPTION = 0x406D1388;901struct {902DWORD dwType; // must be 0x1000903LPCSTR szName; // pointer to name (in user addr space)904DWORD dwThreadID; // thread ID (-1=caller thread)905DWORD dwFlags; // reserved for future use, must be zero906} info;907908info.dwType = 0x1000;909info.szName = name;910info.dwThreadID = -1;911info.dwFlags = 0;912913__try {914RaiseException (MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(DWORD), (const ULONG_PTR*)&info );915} __except(EXCEPTION_EXECUTE_HANDLER) {}916}917918bool os::bind_to_processor(uint processor_id) {919// Not yet implemented.920return false;921}922923void os::win32::initialize_performance_counter() {924LARGE_INTEGER count;925QueryPerformanceFrequency(&count);926performance_frequency = as_long(count);927QueryPerformanceCounter(&count);928initial_performance_count = as_long(count);929}930931932double os::elapsedTime() {933return (double) elapsed_counter() / (double) elapsed_frequency();934}935936937// Windows format:938// The FILETIME structure is a 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601.939// Java format:940// Java standards require the number of milliseconds since 1/1/1970941942// Constant offset - calculated using offset()943static jlong _offset = 116444736000000000;944// Fake time counter for reproducible results when debugging945static jlong fake_time = 0;946947#ifdef ASSERT948// Just to be safe, recalculate the offset in debug mode949static jlong _calculated_offset = 0;950static int _has_calculated_offset = 0;951952jlong offset() {953if (_has_calculated_offset) return _calculated_offset;954SYSTEMTIME java_origin;955java_origin.wYear = 1970;956java_origin.wMonth = 1;957java_origin.wDayOfWeek = 0; // ignored958java_origin.wDay = 1;959java_origin.wHour = 0;960java_origin.wMinute = 0;961java_origin.wSecond = 0;962java_origin.wMilliseconds = 0;963FILETIME jot;964if (!SystemTimeToFileTime(&java_origin, &jot)) {965fatal("Error = %d\nWindows error", GetLastError());966}967_calculated_offset = jlong_from(jot.dwHighDateTime, jot.dwLowDateTime);968_has_calculated_offset = 1;969assert(_calculated_offset == _offset, "Calculated and constant time offsets must be equal");970return _calculated_offset;971}972#else973jlong offset() {974return _offset;975}976#endif977978jlong windows_to_java_time(FILETIME wt) {979jlong a = jlong_from(wt.dwHighDateTime, wt.dwLowDateTime);980return (a - offset()) / 10000;981}982983// Returns time ticks in (10th of micro seconds)984jlong windows_to_time_ticks(FILETIME wt) {985jlong a = jlong_from(wt.dwHighDateTime, wt.dwLowDateTime);986return (a - offset());987}988989FILETIME java_to_windows_time(jlong l) {990jlong a = (l * 10000) + offset();991FILETIME result;992result.dwHighDateTime = high(a);993result.dwLowDateTime = low(a);994return result;995}996997bool os::supports_vtime() { return true; }998999double os::elapsedVTime() {1000FILETIME created;1001FILETIME exited;1002FILETIME kernel;1003FILETIME user;1004if (GetThreadTimes(GetCurrentThread(), &created, &exited, &kernel, &user) != 0) {1005// the resolution of windows_to_java_time() should be sufficient (ms)1006return (double) (windows_to_java_time(kernel) + windows_to_java_time(user)) / MILLIUNITS;1007} else {1008return elapsedTime();1009}1010}10111012jlong os::javaTimeMillis() {1013FILETIME wt;1014GetSystemTimeAsFileTime(&wt);1015return windows_to_java_time(wt);1016}10171018void os::javaTimeSystemUTC(jlong &seconds, jlong &nanos) {1019FILETIME wt;1020GetSystemTimeAsFileTime(&wt);1021jlong ticks = windows_to_time_ticks(wt); // 10th of micros1022jlong secs = jlong(ticks / 10000000); // 10000 * 10001023seconds = secs;1024nanos = jlong(ticks - (secs*10000000)) * 100;1025}10261027jlong os::javaTimeNanos() {1028LARGE_INTEGER current_count;1029QueryPerformanceCounter(¤t_count);1030double current = as_long(current_count);1031double freq = performance_frequency;1032jlong time = (jlong)((current/freq) * NANOSECS_PER_SEC);1033return time;1034}10351036void os::javaTimeNanos_info(jvmtiTimerInfo *info_ptr) {1037jlong freq = performance_frequency;1038if (freq < NANOSECS_PER_SEC) {1039// the performance counter is 64 bits and we will1040// be multiplying it -- so no wrap in 64 bits1041info_ptr->max_value = ALL_64_BITS;1042} else if (freq > NANOSECS_PER_SEC) {1043// use the max value the counter can reach to1044// determine the max value which could be returned1045julong max_counter = (julong)ALL_64_BITS;1046info_ptr->max_value = (jlong)(max_counter / (freq / NANOSECS_PER_SEC));1047} else {1048// the performance counter is 64 bits and we will1049// be using it directly -- so no wrap in 64 bits1050info_ptr->max_value = ALL_64_BITS;1051}10521053// using a counter, so no skipping1054info_ptr->may_skip_backward = false;1055info_ptr->may_skip_forward = false;10561057info_ptr->kind = JVMTI_TIMER_ELAPSED; // elapsed not CPU time1058}10591060char* os::local_time_string(char *buf, size_t buflen) {1061SYSTEMTIME st;1062GetLocalTime(&st);1063jio_snprintf(buf, buflen, "%d-%02d-%02d %02d:%02d:%02d",1064st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);1065return buf;1066}10671068bool os::getTimesSecs(double* process_real_time,1069double* process_user_time,1070double* process_system_time) {1071HANDLE h_process = GetCurrentProcess();1072FILETIME create_time, exit_time, kernel_time, user_time;1073BOOL result = GetProcessTimes(h_process,1074&create_time,1075&exit_time,1076&kernel_time,1077&user_time);1078if (result != 0) {1079FILETIME wt;1080GetSystemTimeAsFileTime(&wt);1081jlong rtc_millis = windows_to_java_time(wt);1082*process_real_time = ((double) rtc_millis) / ((double) MILLIUNITS);1083*process_user_time =1084(double) jlong_from(user_time.dwHighDateTime, user_time.dwLowDateTime) / (10 * MICROUNITS);1085*process_system_time =1086(double) jlong_from(kernel_time.dwHighDateTime, kernel_time.dwLowDateTime) / (10 * MICROUNITS);1087return true;1088} else {1089return false;1090}1091}10921093void os::shutdown() {1094// allow PerfMemory to attempt cleanup of any persistent resources1095perfMemory_exit();10961097// flush buffered output, finish log files1098ostream_abort();10991100// Check for abort hook1101abort_hook_t abort_hook = Arguments::abort_hook();1102if (abort_hook != NULL) {1103abort_hook();1104}1105}110611071108static HANDLE dumpFile = NULL;11091110// Check if dump file can be created.1111void os::check_dump_limit(char* buffer, size_t buffsz) {1112bool status = true;1113if (!FLAG_IS_DEFAULT(CreateCoredumpOnCrash) && !CreateCoredumpOnCrash) {1114jio_snprintf(buffer, buffsz, "CreateCoredumpOnCrash is disabled from command line");1115status = false;1116}11171118#ifndef ASSERT1119if (!os::win32::is_windows_server() && FLAG_IS_DEFAULT(CreateCoredumpOnCrash)) {1120jio_snprintf(buffer, buffsz, "Minidumps are not enabled by default on client versions of Windows");1121status = false;1122}1123#endif11241125if (status) {1126const char* cwd = get_current_directory(NULL, 0);1127int pid = current_process_id();1128if (cwd != NULL) {1129jio_snprintf(buffer, buffsz, "%s\\hs_err_pid%u.mdmp", cwd, pid);1130} else {1131jio_snprintf(buffer, buffsz, ".\\hs_err_pid%u.mdmp", pid);1132}11331134if (dumpFile == NULL &&1135(dumpFile = CreateFile(buffer, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL))1136== INVALID_HANDLE_VALUE) {1137jio_snprintf(buffer, buffsz, "Failed to create minidump file (0x%x).", GetLastError());1138status = false;1139}1140}1141VMError::record_coredump_status(buffer, status);1142}11431144void os::abort(bool dump_core, void* siginfo, const void* context) {1145EXCEPTION_POINTERS ep;1146MINIDUMP_EXCEPTION_INFORMATION mei;1147MINIDUMP_EXCEPTION_INFORMATION* pmei;11481149HANDLE hProcess = GetCurrentProcess();1150DWORD processId = GetCurrentProcessId();1151MINIDUMP_TYPE dumpType;11521153shutdown();1154if (!dump_core || dumpFile == NULL) {1155if (dumpFile != NULL) {1156CloseHandle(dumpFile);1157}1158win32::exit_process_or_thread(win32::EPT_PROCESS, 1);1159}11601161dumpType = (MINIDUMP_TYPE)(MiniDumpWithFullMemory | MiniDumpWithHandleData |1162MiniDumpWithFullMemoryInfo | MiniDumpWithThreadInfo | MiniDumpWithUnloadedModules);11631164if (siginfo != NULL && context != NULL) {1165ep.ContextRecord = (PCONTEXT) context;1166ep.ExceptionRecord = (PEXCEPTION_RECORD) siginfo;11671168mei.ThreadId = GetCurrentThreadId();1169mei.ExceptionPointers = &ep;1170pmei = &mei;1171} else {1172pmei = NULL;1173}11741175// Older versions of dbghelp.dll (the one shipped with Win2003 for example) may not support all1176// the dump types we really want. If first call fails, lets fall back to just use MiniDumpWithFullMemory then.1177if (!WindowsDbgHelp::miniDumpWriteDump(hProcess, processId, dumpFile, dumpType, pmei, NULL, NULL) &&1178!WindowsDbgHelp::miniDumpWriteDump(hProcess, processId, dumpFile, (MINIDUMP_TYPE)MiniDumpWithFullMemory, pmei, NULL, NULL)) {1179jio_fprintf(stderr, "Call to MiniDumpWriteDump() failed (Error 0x%x)\n", GetLastError());1180}1181CloseHandle(dumpFile);1182win32::exit_process_or_thread(win32::EPT_PROCESS, 1);1183}11841185// Die immediately, no exit hook, no abort hook, no cleanup.1186void os::die() {1187win32::exit_process_or_thread(win32::EPT_PROCESS_DIE, -1);1188}11891190const char* os::dll_file_extension() { return ".dll"; }11911192void os::dll_unload(void *lib) {1193::FreeLibrary((HMODULE)lib);1194}11951196void* os::dll_lookup(void *lib, const char *name) {1197return (void*)::GetProcAddress((HMODULE)lib, name);1198}11991200// Directory routines copied from src/win32/native/java/io/dirent_md.c1201// * dirent_md.c 1.15 00/02/021202//1203// The declarations for DIR and struct dirent are in jvm_win32.h.12041205// Caller must have already run dirname through JVM_NativePath, which removes1206// duplicate slashes and converts all instances of '/' into '\\'.12071208DIR * os::opendir(const char *dirname) {1209assert(dirname != NULL, "just checking"); // hotspot change1210DIR *dirp = (DIR *)malloc(sizeof(DIR), mtInternal);1211DWORD fattr; // hotspot change1212char alt_dirname[4] = { 0, 0, 0, 0 };12131214if (dirp == 0) {1215errno = ENOMEM;1216return 0;1217}12181219// Win32 accepts "\" in its POSIX stat(), but refuses to treat it1220// as a directory in FindFirstFile(). We detect this case here and1221// prepend the current drive name.1222//1223if (dirname[1] == '\0' && dirname[0] == '\\') {1224alt_dirname[0] = _getdrive() + 'A' - 1;1225alt_dirname[1] = ':';1226alt_dirname[2] = '\\';1227alt_dirname[3] = '\0';1228dirname = alt_dirname;1229}12301231dirp->path = (char *)malloc(strlen(dirname) + 5, mtInternal);1232if (dirp->path == 0) {1233free(dirp);1234errno = ENOMEM;1235return 0;1236}1237strcpy(dirp->path, dirname);12381239fattr = GetFileAttributes(dirp->path);1240if (fattr == 0xffffffff) {1241free(dirp->path);1242free(dirp);1243errno = ENOENT;1244return 0;1245} else if ((fattr & FILE_ATTRIBUTE_DIRECTORY) == 0) {1246free(dirp->path);1247free(dirp);1248errno = ENOTDIR;1249return 0;1250}12511252// Append "*.*", or possibly "\\*.*", to path1253if (dirp->path[1] == ':' &&1254(dirp->path[2] == '\0' ||1255(dirp->path[2] == '\\' && dirp->path[3] == '\0'))) {1256// No '\\' needed for cases like "Z:" or "Z:\"1257strcat(dirp->path, "*.*");1258} else {1259strcat(dirp->path, "\\*.*");1260}12611262dirp->handle = FindFirstFile(dirp->path, &dirp->find_data);1263if (dirp->handle == INVALID_HANDLE_VALUE) {1264if (GetLastError() != ERROR_FILE_NOT_FOUND) {1265free(dirp->path);1266free(dirp);1267errno = EACCES;1268return 0;1269}1270}1271return dirp;1272}12731274struct dirent * os::readdir(DIR *dirp) {1275assert(dirp != NULL, "just checking"); // hotspot change1276if (dirp->handle == INVALID_HANDLE_VALUE) {1277return NULL;1278}12791280strcpy(dirp->dirent.d_name, dirp->find_data.cFileName);12811282if (!FindNextFile(dirp->handle, &dirp->find_data)) {1283if (GetLastError() == ERROR_INVALID_HANDLE) {1284errno = EBADF;1285return NULL;1286}1287FindClose(dirp->handle);1288dirp->handle = INVALID_HANDLE_VALUE;1289}12901291return &dirp->dirent;1292}12931294int os::closedir(DIR *dirp) {1295assert(dirp != NULL, "just checking"); // hotspot change1296if (dirp->handle != INVALID_HANDLE_VALUE) {1297if (!FindClose(dirp->handle)) {1298errno = EBADF;1299return -1;1300}1301dirp->handle = INVALID_HANDLE_VALUE;1302}1303free(dirp->path);1304free(dirp);1305return 0;1306}13071308// This must be hard coded because it's the system's temporary1309// directory not the java application's temp directory, ala java.io.tmpdir.1310const char* os::get_temp_directory() {1311static char path_buf[MAX_PATH];1312if (GetTempPath(MAX_PATH, path_buf) > 0) {1313return path_buf;1314} else {1315path_buf[0] = '\0';1316return path_buf;1317}1318}13191320// Needs to be in os specific directory because windows requires another1321// header file <direct.h>1322const char* os::get_current_directory(char *buf, size_t buflen) {1323int n = static_cast<int>(buflen);1324if (buflen > INT_MAX) n = INT_MAX;1325return _getcwd(buf, n);1326}13271328//-----------------------------------------------------------1329// Helper functions for fatal error handler1330#ifdef _WIN641331// Helper routine which returns true if address in1332// within the NTDLL address space.1333//1334static bool _addr_in_ntdll(address addr) {1335HMODULE hmod;1336MODULEINFO minfo;13371338hmod = GetModuleHandle("NTDLL.DLL");1339if (hmod == NULL) return false;1340if (!GetModuleInformation(GetCurrentProcess(), hmod,1341&minfo, sizeof(MODULEINFO))) {1342return false;1343}13441345if ((addr >= minfo.lpBaseOfDll) &&1346(addr < (address)((uintptr_t)minfo.lpBaseOfDll + (uintptr_t)minfo.SizeOfImage))) {1347return true;1348} else {1349return false;1350}1351}1352#endif13531354struct _modinfo {1355address addr;1356char* full_path; // point to a char buffer1357int buflen; // size of the buffer1358address base_addr;1359};13601361static int _locate_module_by_addr(const char * mod_fname, address base_addr,1362address top_address, void * param) {1363struct _modinfo *pmod = (struct _modinfo *)param;1364if (!pmod) return -1;13651366if (base_addr <= pmod->addr &&1367top_address > pmod->addr) {1368// if a buffer is provided, copy path name to the buffer1369if (pmod->full_path) {1370jio_snprintf(pmod->full_path, pmod->buflen, "%s", mod_fname);1371}1372pmod->base_addr = base_addr;1373return 1;1374}1375return 0;1376}13771378bool os::dll_address_to_library_name(address addr, char* buf,1379int buflen, int* offset) {1380// buf is not optional, but offset is optional1381assert(buf != NULL, "sanity check");13821383// NOTE: the reason we don't use SymGetModuleInfo() is it doesn't always1384// return the full path to the DLL file, sometimes it returns path1385// to the corresponding PDB file (debug info); sometimes it only1386// returns partial path, which makes life painful.13871388struct _modinfo mi;1389mi.addr = addr;1390mi.full_path = buf;1391mi.buflen = buflen;1392if (get_loaded_modules_info(_locate_module_by_addr, (void *)&mi)) {1393// buf already contains path name1394if (offset) *offset = addr - mi.base_addr;1395return true;1396}13971398buf[0] = '\0';1399if (offset) *offset = -1;1400return false;1401}14021403bool os::dll_address_to_function_name(address addr, char *buf,1404int buflen, int *offset,1405bool demangle) {1406// buf is not optional, but offset is optional1407assert(buf != NULL, "sanity check");14081409if (Decoder::decode(addr, buf, buflen, offset, demangle)) {1410return true;1411}1412if (offset != NULL) *offset = -1;1413buf[0] = '\0';1414return false;1415}14161417// save the start and end address of jvm.dll into param[0] and param[1]1418static int _locate_jvm_dll(const char* mod_fname, address base_addr,1419address top_address, void * param) {1420if (!param) return -1;14211422if (base_addr <= (address)_locate_jvm_dll &&1423top_address > (address)_locate_jvm_dll) {1424((address*)param)[0] = base_addr;1425((address*)param)[1] = top_address;1426return 1;1427}1428return 0;1429}14301431address vm_lib_location[2]; // start and end address of jvm.dll14321433// check if addr is inside jvm.dll1434bool os::address_is_in_vm(address addr) {1435if (!vm_lib_location[0] || !vm_lib_location[1]) {1436if (!get_loaded_modules_info(_locate_jvm_dll, (void *)vm_lib_location)) {1437assert(false, "Can't find jvm module.");1438return false;1439}1440}14411442return (vm_lib_location[0] <= addr) && (addr < vm_lib_location[1]);1443}14441445// print module info; param is outputStream*1446static int _print_module(const char* fname, address base_address,1447address top_address, void* param) {1448if (!param) return -1;14491450outputStream* st = (outputStream*)param;14511452st->print(PTR_FORMAT " - " PTR_FORMAT " \t%s\n", base_address, top_address, fname);1453return 0;1454}14551456// Loads .dll/.so and1457// in case of error it checks if .dll/.so was built for the1458// same architecture as Hotspot is running on1459void * os::dll_load(const char *name, char *ebuf, int ebuflen) {1460log_info(os)("attempting shared library load of %s", name);14611462void * result = LoadLibrary(name);1463if (result != NULL) {1464Events::log(NULL, "Loaded shared library %s", name);1465// Recalculate pdb search path if a DLL was loaded successfully.1466SymbolEngine::recalc_search_path();1467log_info(os)("shared library load of %s was successful", name);1468return result;1469}1470DWORD errcode = GetLastError();1471// Read system error message into ebuf1472// It may or may not be overwritten below (in the for loop and just above)1473lasterror(ebuf, (size_t) ebuflen);1474ebuf[ebuflen - 1] = '\0';1475Events::log(NULL, "Loading shared library %s failed, error code %lu", name, errcode);1476log_info(os)("shared library load of %s failed, error code %lu", name, errcode);14771478if (errcode == ERROR_MOD_NOT_FOUND) {1479strncpy(ebuf, "Can't find dependent libraries", ebuflen - 1);1480ebuf[ebuflen - 1] = '\0';1481return NULL;1482}14831484// Parsing dll below1485// If we can read dll-info and find that dll was built1486// for an architecture other than Hotspot is running in1487// - then print to buffer "DLL was built for a different architecture"1488// else call os::lasterror to obtain system error message1489int fd = ::open(name, O_RDONLY | O_BINARY, 0);1490if (fd < 0) {1491return NULL;1492}14931494uint32_t signature_offset;1495uint16_t lib_arch = 0;1496bool failed_to_get_lib_arch =1497( // Go to position 3c in the dll1498(os::seek_to_file_offset(fd, IMAGE_FILE_PTR_TO_SIGNATURE) < 0)1499||1500// Read location of signature1501(sizeof(signature_offset) !=1502(os::read(fd, (void*)&signature_offset, sizeof(signature_offset))))1503||1504// Go to COFF File Header in dll1505// that is located after "signature" (4 bytes long)1506(os::seek_to_file_offset(fd,1507signature_offset + IMAGE_FILE_SIGNATURE_LENGTH) < 0)1508||1509// Read field that contains code of architecture1510// that dll was built for1511(sizeof(lib_arch) != (os::read(fd, (void*)&lib_arch, sizeof(lib_arch))))1512);15131514::close(fd);1515if (failed_to_get_lib_arch) {1516// file i/o error - report os::lasterror(...) msg1517return NULL;1518}15191520typedef struct {1521uint16_t arch_code;1522char* arch_name;1523} arch_t;15241525static const arch_t arch_array[] = {1526{IMAGE_FILE_MACHINE_I386, (char*)"IA 32"},1527{IMAGE_FILE_MACHINE_AMD64, (char*)"AMD 64"},1528{IMAGE_FILE_MACHINE_ARM64, (char*)"ARM 64"}1529};1530#if (defined _M_ARM64)1531static const uint16_t running_arch = IMAGE_FILE_MACHINE_ARM64;1532#elif (defined _M_AMD64)1533static const uint16_t running_arch = IMAGE_FILE_MACHINE_AMD64;1534#elif (defined _M_IX86)1535static const uint16_t running_arch = IMAGE_FILE_MACHINE_I386;1536#else1537#error Method os::dll_load requires that one of following \1538is defined :_M_AMD64 or _M_IX86 or _M_ARM641539#endif154015411542// Obtain a string for printf operation1543// lib_arch_str shall contain string what platform this .dll was built for1544// running_arch_str shall string contain what platform Hotspot was built for1545char *running_arch_str = NULL, *lib_arch_str = NULL;1546for (unsigned int i = 0; i < ARRAY_SIZE(arch_array); i++) {1547if (lib_arch == arch_array[i].arch_code) {1548lib_arch_str = arch_array[i].arch_name;1549}1550if (running_arch == arch_array[i].arch_code) {1551running_arch_str = arch_array[i].arch_name;1552}1553}15541555assert(running_arch_str,1556"Didn't find running architecture code in arch_array");15571558// If the architecture is right1559// but some other error took place - report os::lasterror(...) msg1560if (lib_arch == running_arch) {1561return NULL;1562}15631564if (lib_arch_str != NULL) {1565::_snprintf(ebuf, ebuflen - 1,1566"Can't load %s-bit .dll on a %s-bit platform",1567lib_arch_str, running_arch_str);1568} else {1569// don't know what architecture this dll was build for1570::_snprintf(ebuf, ebuflen - 1,1571"Can't load this .dll (machine code=0x%x) on a %s-bit platform",1572lib_arch, running_arch_str);1573}15741575return NULL;1576}15771578void os::print_dll_info(outputStream *st) {1579st->print_cr("Dynamic libraries:");1580get_loaded_modules_info(_print_module, (void *)st);1581}15821583int os::get_loaded_modules_info(os::LoadedModulesCallbackFunc callback, void *param) {1584HANDLE hProcess;15851586# define MAX_NUM_MODULES 1281587HMODULE modules[MAX_NUM_MODULES];1588static char filename[MAX_PATH];1589int result = 0;15901591int pid = os::current_process_id();1592hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,1593FALSE, pid);1594if (hProcess == NULL) return 0;15951596DWORD size_needed;1597if (!EnumProcessModules(hProcess, modules, sizeof(modules), &size_needed)) {1598CloseHandle(hProcess);1599return 0;1600}16011602// number of modules that are currently loaded1603int num_modules = size_needed / sizeof(HMODULE);16041605for (int i = 0; i < MIN2(num_modules, MAX_NUM_MODULES); i++) {1606// Get Full pathname:1607if (!GetModuleFileNameEx(hProcess, modules[i], filename, sizeof(filename))) {1608filename[0] = '\0';1609}16101611MODULEINFO modinfo;1612if (!GetModuleInformation(hProcess, modules[i], &modinfo, sizeof(modinfo))) {1613modinfo.lpBaseOfDll = NULL;1614modinfo.SizeOfImage = 0;1615}16161617// Invoke callback function1618result = callback(filename, (address)modinfo.lpBaseOfDll,1619(address)((u8)modinfo.lpBaseOfDll + (u8)modinfo.SizeOfImage), param);1620if (result) break;1621}16221623CloseHandle(hProcess);1624return result;1625}16261627bool os::get_host_name(char* buf, size_t buflen) {1628DWORD size = (DWORD)buflen;1629return (GetComputerNameEx(ComputerNameDnsHostname, buf, &size) == TRUE);1630}16311632void os::get_summary_os_info(char* buf, size_t buflen) {1633stringStream sst(buf, buflen);1634os::win32::print_windows_version(&sst);1635// chop off newline character1636char* nl = strchr(buf, '\n');1637if (nl != NULL) *nl = '\0';1638}16391640int os::vsnprintf(char* buf, size_t len, const char* fmt, va_list args) {1641#if _MSC_VER >= 19001642// Starting with Visual Studio 2015, vsnprint is C99 compliant.1643int result = ::vsnprintf(buf, len, fmt, args);1644// If an encoding error occurred (result < 0) then it's not clear1645// whether the buffer is NUL terminated, so ensure it is.1646if ((result < 0) && (len > 0)) {1647buf[len - 1] = '\0';1648}1649return result;1650#else1651// Before Visual Studio 2015, vsnprintf is not C99 compliant, so use1652// _vsnprintf, whose behavior seems to be *mostly* consistent across1653// versions. However, when len == 0, avoid _vsnprintf too, and just1654// go straight to _vscprintf. The output is going to be truncated in1655// that case, except in the unusual case of empty output. More1656// importantly, the documentation for various versions of Visual Studio1657// are inconsistent about the behavior of _vsnprintf when len == 0,1658// including it possibly being an error.1659int result = -1;1660if (len > 0) {1661result = _vsnprintf(buf, len, fmt, args);1662// If output (including NUL terminator) is truncated, the buffer1663// won't be NUL terminated. Add the trailing NUL specified by C99.1664if ((result < 0) || ((size_t)result >= len)) {1665buf[len - 1] = '\0';1666}1667}1668if (result < 0) {1669result = _vscprintf(fmt, args);1670}1671return result;1672#endif // _MSC_VER dispatch1673}16741675static inline time_t get_mtime(const char* filename) {1676struct stat st;1677int ret = os::stat(filename, &st);1678assert(ret == 0, "failed to stat() file '%s': %s", filename, os::strerror(errno));1679return st.st_mtime;1680}16811682int os::compare_file_modified_times(const char* file1, const char* file2) {1683time_t t1 = get_mtime(file1);1684time_t t2 = get_mtime(file2);1685return t1 - t2;1686}16871688void os::print_os_info_brief(outputStream* st) {1689os::print_os_info(st);1690}16911692void os::win32::print_uptime_info(outputStream* st) {1693unsigned long long ticks = GetTickCount64();1694os::print_dhm(st, "OS uptime:", ticks/1000);1695}16961697void os::print_os_info(outputStream* st) {1698#ifdef ASSERT1699char buffer[1024];1700st->print("HostName: ");1701if (get_host_name(buffer, sizeof(buffer))) {1702st->print_cr(buffer);1703} else {1704st->print_cr("N/A");1705}1706#endif1707st->print_cr("OS:");1708os::win32::print_windows_version(st);17091710os::win32::print_uptime_info(st);17111712VM_Version::print_platform_virtualization_info(st);1713}17141715void os::win32::print_windows_version(outputStream* st) {1716OSVERSIONINFOEX osvi;1717VS_FIXEDFILEINFO *file_info;1718TCHAR kernel32_path[MAX_PATH];1719UINT len, ret;17201721// Use the GetVersionEx information to see if we're on a server or1722// workstation edition of Windows. Starting with Windows 8.1 we can't1723// trust the OS version information returned by this API.1724ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));1725osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);1726if (!GetVersionEx((OSVERSIONINFO *)&osvi)) {1727st->print_cr("Call to GetVersionEx failed");1728return;1729}1730bool is_workstation = (osvi.wProductType == VER_NT_WORKSTATION);17311732// Get the full path to \Windows\System32\kernel32.dll and use that for1733// determining what version of Windows we're running on.1734len = MAX_PATH - (UINT)strlen("\\kernel32.dll") - 1;1735ret = GetSystemDirectory(kernel32_path, len);1736if (ret == 0 || ret > len) {1737st->print_cr("Call to GetSystemDirectory failed");1738return;1739}1740strncat(kernel32_path, "\\kernel32.dll", MAX_PATH - ret);17411742DWORD version_size = GetFileVersionInfoSize(kernel32_path, NULL);1743if (version_size == 0) {1744st->print_cr("Call to GetFileVersionInfoSize failed");1745return;1746}17471748LPTSTR version_info = (LPTSTR)os::malloc(version_size, mtInternal);1749if (version_info == NULL) {1750st->print_cr("Failed to allocate version_info");1751return;1752}17531754if (!GetFileVersionInfo(kernel32_path, NULL, version_size, version_info)) {1755os::free(version_info);1756st->print_cr("Call to GetFileVersionInfo failed");1757return;1758}17591760if (!VerQueryValue(version_info, TEXT("\\"), (LPVOID*)&file_info, &len)) {1761os::free(version_info);1762st->print_cr("Call to VerQueryValue failed");1763return;1764}17651766int major_version = HIWORD(file_info->dwProductVersionMS);1767int minor_version = LOWORD(file_info->dwProductVersionMS);1768int build_number = HIWORD(file_info->dwProductVersionLS);1769int build_minor = LOWORD(file_info->dwProductVersionLS);1770int os_vers = major_version * 1000 + minor_version;1771os::free(version_info);17721773st->print(" Windows ");1774switch (os_vers) {17751776case 6000:1777if (is_workstation) {1778st->print("Vista");1779} else {1780st->print("Server 2008");1781}1782break;17831784case 6001:1785if (is_workstation) {1786st->print("7");1787} else {1788st->print("Server 2008 R2");1789}1790break;17911792case 6002:1793if (is_workstation) {1794st->print("8");1795} else {1796st->print("Server 2012");1797}1798break;17991800case 6003:1801if (is_workstation) {1802st->print("8.1");1803} else {1804st->print("Server 2012 R2");1805}1806break;18071808case 10000:1809if (is_workstation) {1810st->print("10");1811} else {1812// distinguish Windows Server 2016 and 2019 by build number1813// Windows server 2019 GA 10/2018 build number is 177631814if (build_number > 17762) {1815st->print("Server 2019");1816} else {1817st->print("Server 2016");1818}1819}1820break;18211822default:1823// Unrecognized windows, print out its major and minor versions1824st->print("%d.%d", major_version, minor_version);1825break;1826}18271828// Retrieve SYSTEM_INFO from GetNativeSystemInfo call so that we could1829// find out whether we are running on 64 bit processor or not1830SYSTEM_INFO si;1831ZeroMemory(&si, sizeof(SYSTEM_INFO));1832GetNativeSystemInfo(&si);1833if ((si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) ||1834(si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_ARM64)) {1835st->print(" , 64 bit");1836}18371838st->print(" Build %d", build_number);1839st->print(" (%d.%d.%d.%d)", major_version, minor_version, build_number, build_minor);1840st->cr();1841}18421843void os::pd_print_cpu_info(outputStream* st, char* buf, size_t buflen) {1844// Nothing to do for now.1845}18461847void os::get_summary_cpu_info(char* buf, size_t buflen) {1848HKEY key;1849DWORD status = RegOpenKey(HKEY_LOCAL_MACHINE,1850"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", &key);1851if (status == ERROR_SUCCESS) {1852DWORD size = (DWORD)buflen;1853status = RegQueryValueEx(key, "ProcessorNameString", NULL, NULL, (byte*)buf, &size);1854if (status != ERROR_SUCCESS) {1855strncpy(buf, "## __CPU__", buflen);1856}1857RegCloseKey(key);1858} else {1859// Put generic cpu info to return1860strncpy(buf, "## __CPU__", buflen);1861}1862}18631864void os::print_memory_info(outputStream* st) {1865st->print("Memory:");1866st->print(" %dk page", os::vm_page_size()>>10);18671868// Use GlobalMemoryStatusEx() because GlobalMemoryStatus() may return incorrect1869// value if total memory is larger than 4GB1870MEMORYSTATUSEX ms;1871ms.dwLength = sizeof(ms);1872int r1 = GlobalMemoryStatusEx(&ms);18731874if (r1 != 0) {1875st->print(", system-wide physical " INT64_FORMAT "M ",1876(int64_t) ms.ullTotalPhys >> 20);1877st->print("(" INT64_FORMAT "M free)\n", (int64_t) ms.ullAvailPhys >> 20);18781879st->print("TotalPageFile size " INT64_FORMAT "M ",1880(int64_t) ms.ullTotalPageFile >> 20);1881st->print("(AvailPageFile size " INT64_FORMAT "M)",1882(int64_t) ms.ullAvailPageFile >> 20);18831884// on 32bit Total/AvailVirtual are interesting (show us how close we get to 2-4 GB per process borders)1885#if defined(_M_IX86)1886st->print(", user-mode portion of virtual address-space " INT64_FORMAT "M ",1887(int64_t) ms.ullTotalVirtual >> 20);1888st->print("(" INT64_FORMAT "M free)", (int64_t) ms.ullAvailVirtual >> 20);1889#endif1890} else {1891st->print(", GlobalMemoryStatusEx did not succeed so we miss some memory values.");1892}18931894// extended memory statistics for a process1895PROCESS_MEMORY_COUNTERS_EX pmex;1896ZeroMemory(&pmex, sizeof(PROCESS_MEMORY_COUNTERS_EX));1897pmex.cb = sizeof(pmex);1898int r2 = GetProcessMemoryInfo(GetCurrentProcess(), (PROCESS_MEMORY_COUNTERS*) &pmex, sizeof(pmex));18991900if (r2 != 0) {1901st->print("\ncurrent process WorkingSet (physical memory assigned to process): " INT64_FORMAT "M, ",1902(int64_t) pmex.WorkingSetSize >> 20);1903st->print("peak: " INT64_FORMAT "M\n", (int64_t) pmex.PeakWorkingSetSize >> 20);19041905st->print("current process commit charge (\"private bytes\"): " INT64_FORMAT "M, ",1906(int64_t) pmex.PrivateUsage >> 20);1907st->print("peak: " INT64_FORMAT "M", (int64_t) pmex.PeakPagefileUsage >> 20);1908} else {1909st->print("\nGetProcessMemoryInfo did not succeed so we miss some memory values.");1910}19111912st->cr();1913}19141915bool os::signal_sent_by_kill(const void* siginfo) {1916// TODO: Is this possible?1917return false;1918}19191920void os::print_siginfo(outputStream *st, const void* siginfo) {1921const EXCEPTION_RECORD* const er = (EXCEPTION_RECORD*)siginfo;1922st->print("siginfo:");19231924char tmp[64];1925if (os::exception_name(er->ExceptionCode, tmp, sizeof(tmp)) == NULL) {1926strcpy(tmp, "EXCEPTION_??");1927}1928st->print(" %s (0x%x)", tmp, er->ExceptionCode);19291930if ((er->ExceptionCode == EXCEPTION_ACCESS_VIOLATION ||1931er->ExceptionCode == EXCEPTION_IN_PAGE_ERROR) &&1932er->NumberParameters >= 2) {1933switch (er->ExceptionInformation[0]) {1934case 0: st->print(", reading address"); break;1935case 1: st->print(", writing address"); break;1936case 8: st->print(", data execution prevention violation at address"); break;1937default: st->print(", ExceptionInformation=" INTPTR_FORMAT,1938er->ExceptionInformation[0]);1939}1940st->print(" " INTPTR_FORMAT, er->ExceptionInformation[1]);1941} else {1942int num = er->NumberParameters;1943if (num > 0) {1944st->print(", ExceptionInformation=");1945for (int i = 0; i < num; i++) {1946st->print(INTPTR_FORMAT " ", er->ExceptionInformation[i]);1947}1948}1949}1950st->cr();1951}19521953bool os::signal_thread(Thread* thread, int sig, const char* reason) {1954// TODO: Can we kill thread?1955return false;1956}19571958void os::print_signal_handlers(outputStream* st, char* buf, size_t buflen) {1959// do nothing1960}19611962static char saved_jvm_path[MAX_PATH] = {0};19631964// Find the full path to the current module, jvm.dll1965void os::jvm_path(char *buf, jint buflen) {1966// Error checking.1967if (buflen < MAX_PATH) {1968assert(false, "must use a large-enough buffer");1969buf[0] = '\0';1970return;1971}1972// Lazy resolve the path to current module.1973if (saved_jvm_path[0] != 0) {1974strcpy(buf, saved_jvm_path);1975return;1976}19771978buf[0] = '\0';1979if (Arguments::sun_java_launcher_is_altjvm()) {1980// Support for the java launcher's '-XXaltjvm=<path>' option. Check1981// for a JAVA_HOME environment variable and fix up the path so it1982// looks like jvm.dll is installed there (append a fake suffix1983// hotspot/jvm.dll).1984char* java_home_var = ::getenv("JAVA_HOME");1985if (java_home_var != NULL && java_home_var[0] != 0 &&1986strlen(java_home_var) < (size_t)buflen) {1987strncpy(buf, java_home_var, buflen);19881989// determine if this is a legacy image or modules image1990// modules image doesn't have "jre" subdirectory1991size_t len = strlen(buf);1992char* jrebin_p = buf + len;1993jio_snprintf(jrebin_p, buflen-len, "\\jre\\bin\\");1994if (0 != _access(buf, 0)) {1995jio_snprintf(jrebin_p, buflen-len, "\\bin\\");1996}1997len = strlen(buf);1998jio_snprintf(buf + len, buflen-len, "hotspot\\jvm.dll");1999}2000}20012002if (buf[0] == '\0') {2003GetModuleFileName(vm_lib_handle, buf, buflen);2004}2005strncpy(saved_jvm_path, buf, MAX_PATH);2006saved_jvm_path[MAX_PATH - 1] = '\0';2007}200820092010void os::print_jni_name_prefix_on(outputStream* st, int args_size) {2011#ifndef _WIN642012st->print("_");2013#endif2014}201520162017void os::print_jni_name_suffix_on(outputStream* st, int args_size) {2018#ifndef _WIN642019st->print("@%d", args_size * sizeof(int));2020#endif2021}20222023// This method is a copy of JDK's sysGetLastErrorString2024// from src/windows/hpi/src/system_md.c20252026size_t os::lasterror(char* buf, size_t len) {2027DWORD errval;20282029if ((errval = GetLastError()) != 0) {2030// DOS error2031size_t n = (size_t)FormatMessage(2032FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,2033NULL,2034errval,20350,2036buf,2037(DWORD)len,2038NULL);2039if (n > 3) {2040// Drop final '.', CR, LF2041if (buf[n - 1] == '\n') n--;2042if (buf[n - 1] == '\r') n--;2043if (buf[n - 1] == '.') n--;2044buf[n] = '\0';2045}2046return n;2047}20482049if (errno != 0) {2050// C runtime error that has no corresponding DOS error code2051const char* s = os::strerror(errno);2052size_t n = strlen(s);2053if (n >= len) n = len - 1;2054strncpy(buf, s, n);2055buf[n] = '\0';2056return n;2057}20582059return 0;2060}20612062int os::get_last_error() {2063DWORD error = GetLastError();2064if (error == 0) {2065error = errno;2066}2067return (int)error;2068}20692070// sun.misc.Signal2071// NOTE that this is a workaround for an apparent kernel bug where if2072// a signal handler for SIGBREAK is installed then that signal handler2073// takes priority over the console control handler for CTRL_CLOSE_EVENT.2074// See bug 4416763.2075static void (*sigbreakHandler)(int) = NULL;20762077static void UserHandler(int sig, void *siginfo, void *context) {2078os::signal_notify(sig);2079// We need to reinstate the signal handler each time...2080os::signal(sig, (void*)UserHandler);2081}20822083void* os::user_handler() {2084return (void*) UserHandler;2085}20862087void* os::signal(int signal_number, void* handler) {2088if ((signal_number == SIGBREAK) && (!ReduceSignalUsage)) {2089void (*oldHandler)(int) = sigbreakHandler;2090sigbreakHandler = (void (*)(int)) handler;2091return (void*) oldHandler;2092} else {2093return (void*)::signal(signal_number, (void (*)(int))handler);2094}2095}20962097void os::signal_raise(int signal_number) {2098raise(signal_number);2099}21002101// The Win32 C runtime library maps all console control events other than ^C2102// into SIGBREAK, which makes it impossible to distinguish ^BREAK from close,2103// logoff, and shutdown events. We therefore install our own console handler2104// that raises SIGTERM for the latter cases.2105//2106static BOOL WINAPI consoleHandler(DWORD event) {2107switch (event) {2108case CTRL_C_EVENT:2109if (VMError::is_error_reported()) {2110// Ctrl-C is pressed during error reporting, likely because the error2111// handler fails to abort. Let VM die immediately.2112os::die();2113}21142115os::signal_raise(SIGINT);2116return TRUE;2117break;2118case CTRL_BREAK_EVENT:2119if (sigbreakHandler != NULL) {2120(*sigbreakHandler)(SIGBREAK);2121}2122return TRUE;2123break;2124case CTRL_LOGOFF_EVENT: {2125// Don't terminate JVM if it is running in a non-interactive session,2126// such as a service process.2127USEROBJECTFLAGS flags;2128HANDLE handle = GetProcessWindowStation();2129if (handle != NULL &&2130GetUserObjectInformation(handle, UOI_FLAGS, &flags,2131sizeof(USEROBJECTFLAGS), NULL)) {2132// If it is a non-interactive session, let next handler to deal2133// with it.2134if ((flags.dwFlags & WSF_VISIBLE) == 0) {2135return FALSE;2136}2137}2138}2139case CTRL_CLOSE_EVENT:2140case CTRL_SHUTDOWN_EVENT:2141os::signal_raise(SIGTERM);2142return TRUE;2143break;2144default:2145break;2146}2147return FALSE;2148}21492150// The following code is moved from os.cpp for making this2151// code platform specific, which it is by its very nature.21522153// Return maximum OS signal used + 1 for internal use only2154// Used as exit signal for signal_thread2155int os::sigexitnum_pd() {2156return NSIG;2157}21582159// a counter for each possible signal value, including signal_thread exit signal2160static volatile jint pending_signals[NSIG+1] = { 0 };2161static Semaphore* sig_sem = NULL;21622163static void jdk_misc_signal_init() {2164// Initialize signal structures2165memset((void*)pending_signals, 0, sizeof(pending_signals));21662167// Initialize signal semaphore2168sig_sem = new Semaphore();21692170// Programs embedding the VM do not want it to attempt to receive2171// events like CTRL_LOGOFF_EVENT, which are used to implement the2172// shutdown hooks mechanism introduced in 1.3. For example, when2173// the VM is run as part of a Windows NT service (i.e., a servlet2174// engine in a web server), the correct behavior is for any console2175// control handler to return FALSE, not TRUE, because the OS's2176// "final" handler for such events allows the process to continue if2177// it is a service (while terminating it if it is not a service).2178// To make this behavior uniform and the mechanism simpler, we2179// completely disable the VM's usage of these console events if -Xrs2180// (=ReduceSignalUsage) is specified. This means, for example, that2181// the CTRL-BREAK thread dump mechanism is also disabled in this2182// case. See bugs 4323062, 4345157, and related bugs.21832184// Add a CTRL-C handler2185SetConsoleCtrlHandler(consoleHandler, TRUE);2186}21872188void os::signal_notify(int sig) {2189if (sig_sem != NULL) {2190Atomic::inc(&pending_signals[sig]);2191sig_sem->signal();2192} else {2193// Signal thread is not created with ReduceSignalUsage and jdk_misc_signal_init2194// initialization isn't called.2195assert(ReduceSignalUsage, "signal semaphore should be created");2196}2197}21982199static int check_pending_signals() {2200while (true) {2201for (int i = 0; i < NSIG + 1; i++) {2202jint n = pending_signals[i];2203if (n > 0 && n == Atomic::cmpxchg(&pending_signals[i], n, n - 1)) {2204return i;2205}2206}2207sig_sem->wait_with_safepoint_check(JavaThread::current());2208}2209ShouldNotReachHere();2210return 0; // Satisfy compiler2211}22122213int os::signal_wait() {2214return check_pending_signals();2215}22162217// Implicit OS exception handling22182219LONG Handle_Exception(struct _EXCEPTION_POINTERS* exceptionInfo,2220address handler) {2221Thread* thread = Thread::current_or_null();22222223#if defined(_M_ARM64)2224#define PC_NAME Pc2225#elif defined(_M_AMD64)2226#define PC_NAME Rip2227#elif defined(_M_IX86)2228#define PC_NAME Eip2229#else2230#error unknown architecture2231#endif22322233// Save pc in thread2234if (thread != nullptr && thread->is_Java_thread()) {2235thread->as_Java_thread()->set_saved_exception_pc((address)(DWORD_PTR)exceptionInfo->ContextRecord->PC_NAME);2236}22372238// Set pc to handler2239exceptionInfo->ContextRecord->PC_NAME = (DWORD64)handler;22402241// Continue the execution2242return EXCEPTION_CONTINUE_EXECUTION;2243}224422452246// Used for PostMortemDump2247extern "C" void safepoints();2248extern "C" void find(int x);2249extern "C" void events();22502251// According to Windows API documentation, an illegal instruction sequence should generate2252// the 0xC000001C exception code. However, real world experience shows that occasionnaly2253// the execution of an illegal instruction can generate the exception code 0xC000001E. This2254// seems to be an undocumented feature of Win NT 4.0 (and probably other Windows systems).22552256#define EXCEPTION_ILLEGAL_INSTRUCTION_2 0xC000001E22572258// From "Execution Protection in the Windows Operating System" draft 0.352259// Once a system header becomes available, the "real" define should be2260// included or copied here.2261#define EXCEPTION_INFO_EXEC_VIOLATION 0x0822622263// Windows Vista/2008 heap corruption check2264#define EXCEPTION_HEAP_CORRUPTION 0xC000037422652266// All Visual C++ exceptions thrown from code generated by the Microsoft Visual2267// C++ compiler contain this error code. Because this is a compiler-generated2268// error, the code is not listed in the Win32 API header files.2269// The code is actually a cryptic mnemonic device, with the initial "E"2270// standing for "exception" and the final 3 bytes (0x6D7363) representing the2271// ASCII values of "msc".22722273#define EXCEPTION_UNCAUGHT_CXX_EXCEPTION 0xE06D736322742275#define def_excpt(val) { #val, (val) }22762277static const struct { const char* name; uint number; } exceptlabels[] = {2278def_excpt(EXCEPTION_ACCESS_VIOLATION),2279def_excpt(EXCEPTION_DATATYPE_MISALIGNMENT),2280def_excpt(EXCEPTION_BREAKPOINT),2281def_excpt(EXCEPTION_SINGLE_STEP),2282def_excpt(EXCEPTION_ARRAY_BOUNDS_EXCEEDED),2283def_excpt(EXCEPTION_FLT_DENORMAL_OPERAND),2284def_excpt(EXCEPTION_FLT_DIVIDE_BY_ZERO),2285def_excpt(EXCEPTION_FLT_INEXACT_RESULT),2286def_excpt(EXCEPTION_FLT_INVALID_OPERATION),2287def_excpt(EXCEPTION_FLT_OVERFLOW),2288def_excpt(EXCEPTION_FLT_STACK_CHECK),2289def_excpt(EXCEPTION_FLT_UNDERFLOW),2290def_excpt(EXCEPTION_INT_DIVIDE_BY_ZERO),2291def_excpt(EXCEPTION_INT_OVERFLOW),2292def_excpt(EXCEPTION_PRIV_INSTRUCTION),2293def_excpt(EXCEPTION_IN_PAGE_ERROR),2294def_excpt(EXCEPTION_ILLEGAL_INSTRUCTION),2295def_excpt(EXCEPTION_ILLEGAL_INSTRUCTION_2),2296def_excpt(EXCEPTION_NONCONTINUABLE_EXCEPTION),2297def_excpt(EXCEPTION_STACK_OVERFLOW),2298def_excpt(EXCEPTION_INVALID_DISPOSITION),2299def_excpt(EXCEPTION_GUARD_PAGE),2300def_excpt(EXCEPTION_INVALID_HANDLE),2301def_excpt(EXCEPTION_UNCAUGHT_CXX_EXCEPTION),2302def_excpt(EXCEPTION_HEAP_CORRUPTION)2303};23042305#undef def_excpt23062307const char* os::exception_name(int exception_code, char *buf, size_t size) {2308uint code = static_cast<uint>(exception_code);2309for (uint i = 0; i < ARRAY_SIZE(exceptlabels); ++i) {2310if (exceptlabels[i].number == code) {2311jio_snprintf(buf, size, "%s", exceptlabels[i].name);2312return buf;2313}2314}23152316return NULL;2317}23182319//-----------------------------------------------------------------------------2320LONG Handle_IDiv_Exception(struct _EXCEPTION_POINTERS* exceptionInfo) {2321// handle exception caused by idiv; should only happen for -MinInt/-12322// (division by zero is handled explicitly)2323#if defined(_M_ARM64)2324PCONTEXT ctx = exceptionInfo->ContextRecord;2325address pc = (address)ctx->Sp;2326assert(pc[0] == 0x83, "not an sdiv opcode"); //Fixme did i get the right opcode?2327assert(ctx->X4 == min_jint, "unexpected idiv exception");2328// set correct result values and continue after idiv instruction2329ctx->Pc = (uint64_t)pc + 4; // idiv reg, reg, reg is 4 bytes2330ctx->X4 = (uint64_t)min_jint; // result2331ctx->X5 = (uint64_t)0; // remainder2332// Continue the execution2333#elif defined(_M_AMD64)2334PCONTEXT ctx = exceptionInfo->ContextRecord;2335address pc = (address)ctx->Rip;2336assert(pc[0] >= Assembler::REX && pc[0] <= Assembler::REX_WRXB && pc[1] == 0xF7 || pc[0] == 0xF7, "not an idiv opcode");2337assert(pc[0] >= Assembler::REX && pc[0] <= Assembler::REX_WRXB && (pc[2] & ~0x7) == 0xF8 || (pc[1] & ~0x7) == 0xF8, "cannot handle non-register operands");2338if (pc[0] == 0xF7) {2339// set correct result values and continue after idiv instruction2340ctx->Rip = (DWORD64)pc + 2; // idiv reg, reg is 2 bytes2341} else {2342ctx->Rip = (DWORD64)pc + 3; // REX idiv reg, reg is 3 bytes2343}2344// Do not set ctx->Rax as it already contains the correct value (either 32 or 64 bit, depending on the operation)2345// this is the case because the exception only happens for -MinValue/-1 and -MinValue is always in rax because of the2346// idiv opcode (0xF7).2347ctx->Rdx = (DWORD)0; // remainder2348// Continue the execution2349#else2350PCONTEXT ctx = exceptionInfo->ContextRecord;2351address pc = (address)ctx->Eip;2352assert(pc[0] == 0xF7, "not an idiv opcode");2353assert((pc[1] & ~0x7) == 0xF8, "cannot handle non-register operands");2354assert(ctx->Eax == min_jint, "unexpected idiv exception");2355// set correct result values and continue after idiv instruction2356ctx->Eip = (DWORD)pc + 2; // idiv reg, reg is 2 bytes2357ctx->Eax = (DWORD)min_jint; // result2358ctx->Edx = (DWORD)0; // remainder2359// Continue the execution2360#endif2361return EXCEPTION_CONTINUE_EXECUTION;2362}23632364#if defined(_M_AMD64) || defined(_M_IX86)2365//-----------------------------------------------------------------------------2366LONG WINAPI Handle_FLT_Exception(struct _EXCEPTION_POINTERS* exceptionInfo) {2367PCONTEXT ctx = exceptionInfo->ContextRecord;2368#ifndef _WIN642369// handle exception caused by native method modifying control word2370DWORD exception_code = exceptionInfo->ExceptionRecord->ExceptionCode;23712372switch (exception_code) {2373case EXCEPTION_FLT_DENORMAL_OPERAND:2374case EXCEPTION_FLT_DIVIDE_BY_ZERO:2375case EXCEPTION_FLT_INEXACT_RESULT:2376case EXCEPTION_FLT_INVALID_OPERATION:2377case EXCEPTION_FLT_OVERFLOW:2378case EXCEPTION_FLT_STACK_CHECK:2379case EXCEPTION_FLT_UNDERFLOW:2380jint fp_control_word = (* (jint*) StubRoutines::addr_fpu_cntrl_wrd_std());2381if (fp_control_word != ctx->FloatSave.ControlWord) {2382// Restore FPCW and mask out FLT exceptions2383ctx->FloatSave.ControlWord = fp_control_word | 0xffffffc0;2384// Mask out pending FLT exceptions2385ctx->FloatSave.StatusWord &= 0xffffff00;2386return EXCEPTION_CONTINUE_EXECUTION;2387}2388}23892390if (prev_uef_handler != NULL) {2391// We didn't handle this exception so pass it to the previous2392// UnhandledExceptionFilter.2393return (prev_uef_handler)(exceptionInfo);2394}2395#else // !_WIN642396// On Windows, the mxcsr control bits are non-volatile across calls2397// See also CR 61923332398//2399jint MxCsr = INITIAL_MXCSR;2400// we can't use StubRoutines::x86::addr_mxcsr_std()2401// because in Win64 mxcsr is not saved there2402if (MxCsr != ctx->MxCsr) {2403ctx->MxCsr = MxCsr;2404return EXCEPTION_CONTINUE_EXECUTION;2405}2406#endif // !_WIN6424072408return EXCEPTION_CONTINUE_SEARCH;2409}2410#endif24112412static inline void report_error(Thread* t, DWORD exception_code,2413address addr, void* siginfo, void* context) {2414VMError::report_and_die(t, exception_code, addr, siginfo, context);24152416// If UseOSErrorReporting, this will return here and save the error file2417// somewhere where we can find it in the minidump.2418}24192420//-----------------------------------------------------------------------------2421JNIEXPORT2422LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {2423if (InterceptOSException) return EXCEPTION_CONTINUE_SEARCH;2424PEXCEPTION_RECORD exception_record = exceptionInfo->ExceptionRecord;2425DWORD exception_code = exception_record->ExceptionCode;2426#if defined(_M_ARM64)2427address pc = (address) exceptionInfo->ContextRecord->Pc;2428#elif defined(_M_AMD64)2429address pc = (address) exceptionInfo->ContextRecord->Rip;2430#else2431address pc = (address) exceptionInfo->ContextRecord->Eip;2432#endif2433Thread* t = Thread::current_or_null_safe();24342435// Handle SafeFetch32 and SafeFetchN exceptions.2436if (StubRoutines::is_safefetch_fault(pc)) {2437return Handle_Exception(exceptionInfo, StubRoutines::continuation_for_safefetch_fault(pc));2438}24392440#ifndef _WIN642441// Execution protection violation - win32 running on AMD64 only2442// Handled first to avoid misdiagnosis as a "normal" access violation;2443// This is safe to do because we have a new/unique ExceptionInformation2444// code for this condition.2445if (exception_code == EXCEPTION_ACCESS_VIOLATION) {2446int exception_subcode = (int) exception_record->ExceptionInformation[0];2447address addr = (address) exception_record->ExceptionInformation[1];24482449if (exception_subcode == EXCEPTION_INFO_EXEC_VIOLATION) {2450int page_size = os::vm_page_size();24512452// Make sure the pc and the faulting address are sane.2453//2454// If an instruction spans a page boundary, and the page containing2455// the beginning of the instruction is executable but the following2456// page is not, the pc and the faulting address might be slightly2457// different - we still want to unguard the 2nd page in this case.2458//2459// 15 bytes seems to be a (very) safe value for max instruction size.2460bool pc_is_near_addr =2461(pointer_delta((void*) addr, (void*) pc, sizeof(char)) < 15);2462bool instr_spans_page_boundary =2463(align_down((intptr_t) pc ^ (intptr_t) addr,2464(intptr_t) page_size) > 0);24652466if (pc == addr || (pc_is_near_addr && instr_spans_page_boundary)) {2467static volatile address last_addr =2468(address) os::non_memory_address_word();24692470// In conservative mode, don't unguard unless the address is in the VM2471if (UnguardOnExecutionViolation > 0 && addr != last_addr &&2472(UnguardOnExecutionViolation > 1 || os::address_is_in_vm(addr))) {24732474// Set memory to RWX and retry2475address page_start = align_down(addr, page_size);2476bool res = os::protect_memory((char*) page_start, page_size,2477os::MEM_PROT_RWX);24782479log_debug(os)("Execution protection violation "2480"at " INTPTR_FORMAT2481", unguarding " INTPTR_FORMAT ": %s", p2i(addr),2482p2i(page_start), (res ? "success" : os::strerror(errno)));24832484// Set last_addr so if we fault again at the same address, we don't2485// end up in an endless loop.2486//2487// There are two potential complications here. Two threads trapping2488// at the same address at the same time could cause one of the2489// threads to think it already unguarded, and abort the VM. Likely2490// very rare.2491//2492// The other race involves two threads alternately trapping at2493// different addresses and failing to unguard the page, resulting in2494// an endless loop. This condition is probably even more unlikely2495// than the first.2496//2497// Although both cases could be avoided by using locks or thread2498// local last_addr, these solutions are unnecessary complication:2499// this handler is a best-effort safety net, not a complete solution.2500// It is disabled by default and should only be used as a workaround2501// in case we missed any no-execute-unsafe VM code.25022503last_addr = addr;25042505return EXCEPTION_CONTINUE_EXECUTION;2506}2507}25082509// Last unguard failed or not unguarding2510tty->print_raw_cr("Execution protection violation");2511#if !defined(USE_VECTORED_EXCEPTION_HANDLING)2512report_error(t, exception_code, addr, exception_record,2513exceptionInfo->ContextRecord);2514#endif2515return EXCEPTION_CONTINUE_SEARCH;2516}2517}2518#endif // _WIN6425192520#if defined(_M_AMD64) || defined(_M_IX86)2521if ((exception_code == EXCEPTION_ACCESS_VIOLATION) &&2522VM_Version::is_cpuinfo_segv_addr(pc)) {2523// Verify that OS save/restore AVX registers.2524return Handle_Exception(exceptionInfo, VM_Version::cpuinfo_cont_addr());2525}2526#endif25272528if (t != NULL && t->is_Java_thread()) {2529JavaThread* thread = t->as_Java_thread();2530bool in_java = thread->thread_state() == _thread_in_Java;2531bool in_native = thread->thread_state() == _thread_in_native;2532bool in_vm = thread->thread_state() == _thread_in_vm;25332534// Handle potential stack overflows up front.2535if (exception_code == EXCEPTION_STACK_OVERFLOW) {2536StackOverflow* overflow_state = thread->stack_overflow_state();2537if (overflow_state->stack_guards_enabled()) {2538if (in_java) {2539frame fr;2540if (os::win32::get_frame_at_stack_banging_point(thread, exceptionInfo, pc, &fr)) {2541assert(fr.is_java_frame(), "Must be a Java frame");2542SharedRuntime::look_for_reserved_stack_annotated_method(thread, fr);2543}2544}2545// Yellow zone violation. The o/s has unprotected the first yellow2546// zone page for us. Note: must call disable_stack_yellow_zone to2547// update the enabled status, even if the zone contains only one page.2548assert(!in_vm, "Undersized StackShadowPages");2549overflow_state->disable_stack_yellow_reserved_zone();2550// If not in java code, return and hope for the best.2551return in_java2552? Handle_Exception(exceptionInfo, SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::STACK_OVERFLOW))2553: EXCEPTION_CONTINUE_EXECUTION;2554} else {2555// Fatal red zone violation.2556overflow_state->disable_stack_red_zone();2557tty->print_raw_cr("An unrecoverable stack overflow has occurred.");2558#if !defined(USE_VECTORED_EXCEPTION_HANDLING)2559report_error(t, exception_code, pc, exception_record,2560exceptionInfo->ContextRecord);2561#endif2562return EXCEPTION_CONTINUE_SEARCH;2563}2564} else if (exception_code == EXCEPTION_ACCESS_VIOLATION) {2565if (in_java) {2566// Either stack overflow or null pointer exception.2567address addr = (address) exception_record->ExceptionInformation[1];2568address stack_end = thread->stack_end();2569if (addr < stack_end && addr >= stack_end - os::vm_page_size()) {2570// Stack overflow.2571assert(!os::uses_stack_guard_pages(),2572"should be caught by red zone code above.");2573return Handle_Exception(exceptionInfo,2574SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::STACK_OVERFLOW));2575}2576// Check for safepoint polling and implicit null2577// We only expect null pointers in the stubs (vtable)2578// the rest are checked explicitly now.2579CodeBlob* cb = CodeCache::find_blob(pc);2580if (cb != NULL) {2581if (SafepointMechanism::is_poll_address(addr)) {2582address stub = SharedRuntime::get_poll_stub(pc);2583return Handle_Exception(exceptionInfo, stub);2584}2585}2586#ifdef _WIN642587// If it's a legal stack address map the entire region in2588if (thread->is_in_usable_stack(addr)) {2589addr = (address)((uintptr_t)addr &2590(~((uintptr_t)os::vm_page_size() - (uintptr_t)1)));2591os::commit_memory((char *)addr, thread->stack_base() - addr,2592!ExecMem);2593return EXCEPTION_CONTINUE_EXECUTION;2594}2595#endif2596// Null pointer exception.2597if (MacroAssembler::uses_implicit_null_check((void*)addr)) {2598address stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL);2599if (stub != NULL) return Handle_Exception(exceptionInfo, stub);2600}2601report_error(t, exception_code, pc, exception_record,2602exceptionInfo->ContextRecord);2603return EXCEPTION_CONTINUE_SEARCH;2604}26052606#ifdef _WIN642607// Special care for fast JNI field accessors.2608// jni_fast_Get<Primitive>Field can trap at certain pc's if a GC kicks2609// in and the heap gets shrunk before the field access.2610address slowcase_pc = JNI_FastGetField::find_slowcase_pc(pc);2611if (slowcase_pc != (address)-1) {2612return Handle_Exception(exceptionInfo, slowcase_pc);2613}2614#endif26152616// Stack overflow or null pointer exception in native code.2617#if !defined(USE_VECTORED_EXCEPTION_HANDLING)2618report_error(t, exception_code, pc, exception_record,2619exceptionInfo->ContextRecord);2620#endif2621return EXCEPTION_CONTINUE_SEARCH;2622} // /EXCEPTION_ACCESS_VIOLATION2623// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -26242625if (exception_code == EXCEPTION_IN_PAGE_ERROR) {2626CompiledMethod* nm = NULL;2627if (in_java) {2628CodeBlob* cb = CodeCache::find_blob_unsafe(pc);2629nm = (cb != NULL) ? cb->as_compiled_method_or_null() : NULL;2630}26312632bool is_unsafe_arraycopy = (in_native || in_java) && UnsafeCopyMemory::contains_pc(pc);2633if (((in_vm || in_native || is_unsafe_arraycopy) && thread->doing_unsafe_access()) ||2634(nm != NULL && nm->has_unsafe_access())) {2635address next_pc = Assembler::locate_next_instruction(pc);2636if (is_unsafe_arraycopy) {2637next_pc = UnsafeCopyMemory::page_error_continue_pc(pc);2638}2639return Handle_Exception(exceptionInfo, SharedRuntime::handle_unsafe_access(thread, next_pc));2640}2641}26422643#ifdef _M_ARM642644if (in_java &&2645(exception_code == EXCEPTION_ILLEGAL_INSTRUCTION ||2646exception_code == EXCEPTION_ILLEGAL_INSTRUCTION_2)) {2647if (nativeInstruction_at(pc)->is_sigill_zombie_not_entrant()) {2648if (TraceTraps) {2649tty->print_cr("trap: zombie_not_entrant");2650}2651return Handle_Exception(exceptionInfo, SharedRuntime::get_handle_wrong_method_stub());2652}2653}2654#endif26552656if (in_java) {2657switch (exception_code) {2658case EXCEPTION_INT_DIVIDE_BY_ZERO:2659return Handle_Exception(exceptionInfo, SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_DIVIDE_BY_ZERO));26602661case EXCEPTION_INT_OVERFLOW:2662return Handle_IDiv_Exception(exceptionInfo);26632664} // switch2665}26662667#if defined(_M_AMD64) || defined(_M_IX86)2668if ((in_java || in_native) && exception_code != EXCEPTION_UNCAUGHT_CXX_EXCEPTION) {2669LONG result=Handle_FLT_Exception(exceptionInfo);2670if (result==EXCEPTION_CONTINUE_EXECUTION) return result;2671}2672#endif2673}26742675#if !defined(USE_VECTORED_EXCEPTION_HANDLING)2676if (exception_code != EXCEPTION_BREAKPOINT) {2677report_error(t, exception_code, pc, exception_record,2678exceptionInfo->ContextRecord);2679}2680#endif2681return EXCEPTION_CONTINUE_SEARCH;2682}26832684#if defined(USE_VECTORED_EXCEPTION_HANDLING)2685LONG WINAPI topLevelVectoredExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {2686PEXCEPTION_RECORD exceptionRecord = exceptionInfo->ExceptionRecord;2687#if defined(_M_ARM64)2688address pc = (address) exceptionInfo->ContextRecord->Pc;2689#elif defined(_M_AMD64)2690address pc = (address) exceptionInfo->ContextRecord->Rip;2691#else2692address pc = (address) exceptionInfo->ContextRecord->Eip;2693#endif26942695// Fast path for code part of the code cache2696if (CodeCache::low_bound() <= pc && pc < CodeCache::high_bound()) {2697return topLevelExceptionFilter(exceptionInfo);2698}26992700// If the exception occurred in the codeCache, pass control2701// to our normal exception handler.2702CodeBlob* cb = CodeCache::find_blob(pc);2703if (cb != NULL) {2704return topLevelExceptionFilter(exceptionInfo);2705}27062707return EXCEPTION_CONTINUE_SEARCH;2708}2709#endif27102711#if defined(USE_VECTORED_EXCEPTION_HANDLING)2712LONG WINAPI topLevelUnhandledExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {2713if (InterceptOSException) goto exit;2714DWORD exception_code = exceptionInfo->ExceptionRecord->ExceptionCode;2715#if defined(_M_ARM64)2716address pc = (address)exceptionInfo->ContextRecord->Pc;2717#elif defined(_M_AMD64)2718address pc = (address) exceptionInfo->ContextRecord->Rip;2719#else2720address pc = (address) exceptionInfo->ContextRecord->Eip;2721#endif2722Thread* t = Thread::current_or_null_safe();27232724if (exception_code != EXCEPTION_BREAKPOINT) {2725report_error(t, exception_code, pc, exceptionInfo->ExceptionRecord,2726exceptionInfo->ContextRecord);2727}2728exit:2729return previousUnhandledExceptionFilter ? previousUnhandledExceptionFilter(exceptionInfo) : EXCEPTION_CONTINUE_SEARCH;2730}2731#endif27322733#ifndef _WIN642734// Special care for fast JNI accessors.2735// jni_fast_Get<Primitive>Field can trap at certain pc's if a GC kicks in and2736// the heap gets shrunk before the field access.2737// Need to install our own structured exception handler since native code may2738// install its own.2739LONG WINAPI fastJNIAccessorExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {2740DWORD exception_code = exceptionInfo->ExceptionRecord->ExceptionCode;2741if (exception_code == EXCEPTION_ACCESS_VIOLATION) {2742address pc = (address) exceptionInfo->ContextRecord->Eip;2743address addr = JNI_FastGetField::find_slowcase_pc(pc);2744if (addr != (address)-1) {2745return Handle_Exception(exceptionInfo, addr);2746}2747}2748return EXCEPTION_CONTINUE_SEARCH;2749}27502751#define DEFINE_FAST_GETFIELD(Return, Fieldname, Result) \2752Return JNICALL jni_fast_Get##Result##Field_wrapper(JNIEnv *env, \2753jobject obj, \2754jfieldID fieldID) { \2755__try { \2756return (*JNI_FastGetField::jni_fast_Get##Result##Field_fp)(env, \2757obj, \2758fieldID); \2759} __except(fastJNIAccessorExceptionFilter((_EXCEPTION_POINTERS*) \2760_exception_info())) { \2761} \2762return 0; \2763}27642765DEFINE_FAST_GETFIELD(jboolean, bool, Boolean)2766DEFINE_FAST_GETFIELD(jbyte, byte, Byte)2767DEFINE_FAST_GETFIELD(jchar, char, Char)2768DEFINE_FAST_GETFIELD(jshort, short, Short)2769DEFINE_FAST_GETFIELD(jint, int, Int)2770DEFINE_FAST_GETFIELD(jlong, long, Long)2771DEFINE_FAST_GETFIELD(jfloat, float, Float)2772DEFINE_FAST_GETFIELD(jdouble, double, Double)27732774address os::win32::fast_jni_accessor_wrapper(BasicType type) {2775switch (type) {2776case T_BOOLEAN: return (address)jni_fast_GetBooleanField_wrapper;2777case T_BYTE: return (address)jni_fast_GetByteField_wrapper;2778case T_CHAR: return (address)jni_fast_GetCharField_wrapper;2779case T_SHORT: return (address)jni_fast_GetShortField_wrapper;2780case T_INT: return (address)jni_fast_GetIntField_wrapper;2781case T_LONG: return (address)jni_fast_GetLongField_wrapper;2782case T_FLOAT: return (address)jni_fast_GetFloatField_wrapper;2783case T_DOUBLE: return (address)jni_fast_GetDoubleField_wrapper;2784default: ShouldNotReachHere();2785}2786return (address)-1;2787}2788#endif27892790// Virtual Memory27912792int os::vm_page_size() { return os::win32::vm_page_size(); }2793int os::vm_allocation_granularity() {2794return os::win32::vm_allocation_granularity();2795}27962797// Windows large page support is available on Windows 2003. In order to use2798// large page memory, the administrator must first assign additional privilege2799// to the user:2800// + select Control Panel -> Administrative Tools -> Local Security Policy2801// + select Local Policies -> User Rights Assignment2802// + double click "Lock pages in memory", add users and/or groups2803// + reboot2804// Note the above steps are needed for administrator as well, as administrators2805// by default do not have the privilege to lock pages in memory.2806//2807// Note about Windows 2003: although the API supports committing large page2808// memory on a page-by-page basis and VirtualAlloc() returns success under this2809// scenario, I found through experiment it only uses large page if the entire2810// memory region is reserved and committed in a single VirtualAlloc() call.2811// This makes Windows large page support more or less like Solaris ISM, in2812// that the entire heap must be committed upfront. This probably will change2813// in the future, if so the code below needs to be revisited.28142815#ifndef MEM_LARGE_PAGES2816#define MEM_LARGE_PAGES 0x200000002817#endif28182819// Container for NUMA node list info2820class NUMANodeListHolder {2821private:2822int *_numa_used_node_list; // allocated below2823int _numa_used_node_count;28242825void free_node_list() {2826FREE_C_HEAP_ARRAY(int, _numa_used_node_list);2827}28282829public:2830NUMANodeListHolder() {2831_numa_used_node_count = 0;2832_numa_used_node_list = NULL;2833// do rest of initialization in build routine (after function pointers are set up)2834}28352836~NUMANodeListHolder() {2837free_node_list();2838}28392840bool build() {2841DWORD_PTR proc_aff_mask;2842DWORD_PTR sys_aff_mask;2843if (!GetProcessAffinityMask(GetCurrentProcess(), &proc_aff_mask, &sys_aff_mask)) return false;2844ULONG highest_node_number;2845if (!GetNumaHighestNodeNumber(&highest_node_number)) return false;2846free_node_list();2847_numa_used_node_list = NEW_C_HEAP_ARRAY(int, highest_node_number + 1, mtInternal);2848for (unsigned int i = 0; i <= highest_node_number; i++) {2849ULONGLONG proc_mask_numa_node;2850if (!GetNumaNodeProcessorMask(i, &proc_mask_numa_node)) return false;2851if ((proc_aff_mask & proc_mask_numa_node)!=0) {2852_numa_used_node_list[_numa_used_node_count++] = i;2853}2854}2855return (_numa_used_node_count > 1);2856}28572858int get_count() { return _numa_used_node_count; }2859int get_node_list_entry(int n) {2860// for indexes out of range, returns -12861return (n < _numa_used_node_count ? _numa_used_node_list[n] : -1);2862}28632864} numa_node_list_holder;28652866static size_t _large_page_size = 0;28672868static bool request_lock_memory_privilege() {2869HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE,2870os::current_process_id());28712872bool success = false;2873HANDLE hToken = NULL;2874LUID luid;2875if (hProcess != NULL &&2876OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES, &hToken) &&2877LookupPrivilegeValue(NULL, "SeLockMemoryPrivilege", &luid)) {28782879TOKEN_PRIVILEGES tp;2880tp.PrivilegeCount = 1;2881tp.Privileges[0].Luid = luid;2882tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;28832884// AdjustTokenPrivileges() may return TRUE even when it couldn't change the2885// privilege. Check GetLastError() too. See MSDN document.2886if (AdjustTokenPrivileges(hToken, false, &tp, sizeof(tp), NULL, NULL) &&2887(GetLastError() == ERROR_SUCCESS)) {2888success = true;2889}2890}28912892// Cleanup2893if (hProcess != NULL) {2894CloseHandle(hProcess);2895}2896if (hToken != NULL) {2897CloseHandle(hToken);2898}28992900return success;2901}29022903static bool numa_interleaving_init() {2904bool success = false;29052906// print a warning if UseNUMAInterleaving flag is specified on command line2907bool warn_on_failure = !FLAG_IS_DEFAULT(UseNUMAInterleaving);29082909#define WARN(msg) if (warn_on_failure) { warning(msg); }29102911// NUMAInterleaveGranularity cannot be less than vm_allocation_granularity (or _large_page_size if using large pages)2912size_t min_interleave_granularity = UseLargePages ? _large_page_size : os::vm_allocation_granularity();2913NUMAInterleaveGranularity = align_up(NUMAInterleaveGranularity, min_interleave_granularity);29142915if (!numa_node_list_holder.build()) {2916WARN("Process does not cover multiple NUMA nodes.");2917WARN("...Ignoring UseNUMAInterleaving flag.");2918return false;2919}29202921if (log_is_enabled(Debug, os, cpu)) {2922Log(os, cpu) log;2923log.debug("NUMA UsedNodeCount=%d, namely ", numa_node_list_holder.get_count());2924for (int i = 0; i < numa_node_list_holder.get_count(); i++) {2925log.debug(" %d ", numa_node_list_holder.get_node_list_entry(i));2926}2927}29282929#undef WARN29302931return true;2932}29332934// this routine is used whenever we need to reserve a contiguous VA range2935// but we need to make separate VirtualAlloc calls for each piece of the range2936// Reasons for doing this:2937// * UseLargePagesIndividualAllocation was set (normally only needed on WS2003 but possible to be set otherwise)2938// * UseNUMAInterleaving requires a separate node for each piece2939static char* allocate_pages_individually(size_t bytes, char* addr, DWORD flags,2940DWORD prot,2941bool should_inject_error = false) {2942char * p_buf;2943// note: at setup time we guaranteed that NUMAInterleaveGranularity was aligned up to a page size2944size_t page_size = UseLargePages ? _large_page_size : os::vm_allocation_granularity();2945size_t chunk_size = UseNUMAInterleaving ? NUMAInterleaveGranularity : page_size;29462947// first reserve enough address space in advance since we want to be2948// able to break a single contiguous virtual address range into multiple2949// large page commits but WS2003 does not allow reserving large page space2950// so we just use 4K pages for reserve, this gives us a legal contiguous2951// address space. then we will deallocate that reservation, and re alloc2952// using large pages2953const size_t size_of_reserve = bytes + chunk_size;2954if (bytes > size_of_reserve) {2955// Overflowed.2956return NULL;2957}2958p_buf = (char *) virtualAlloc(addr,2959size_of_reserve, // size of Reserve2960MEM_RESERVE,2961PAGE_READWRITE);2962// If reservation failed, return NULL2963if (p_buf == NULL) return NULL;2964MemTracker::record_virtual_memory_reserve((address)p_buf, size_of_reserve, CALLER_PC);2965os::release_memory(p_buf, bytes + chunk_size);29662967// we still need to round up to a page boundary (in case we are using large pages)2968// but not to a chunk boundary (in case InterleavingGranularity doesn't align with page size)2969// instead we handle this in the bytes_to_rq computation below2970p_buf = align_up(p_buf, page_size);29712972// now go through and allocate one chunk at a time until all bytes are2973// allocated2974size_t bytes_remaining = bytes;2975// An overflow of align_up() would have been caught above2976// in the calculation of size_of_reserve.2977char * next_alloc_addr = p_buf;2978HANDLE hProc = GetCurrentProcess();29792980#ifdef ASSERT2981// Variable for the failure injection2982int ran_num = os::random();2983size_t fail_after = ran_num % bytes;2984#endif29852986int count=0;2987while (bytes_remaining) {2988// select bytes_to_rq to get to the next chunk_size boundary29892990size_t bytes_to_rq = MIN2(bytes_remaining, chunk_size - ((size_t)next_alloc_addr % chunk_size));2991// Note allocate and commit2992char * p_new;29932994#ifdef ASSERT2995bool inject_error_now = should_inject_error && (bytes_remaining <= fail_after);2996#else2997const bool inject_error_now = false;2998#endif29993000if (inject_error_now) {3001p_new = NULL;3002} else {3003if (!UseNUMAInterleaving) {3004p_new = (char *) virtualAlloc(next_alloc_addr,3005bytes_to_rq,3006flags,3007prot);3008} else {3009// get the next node to use from the used_node_list3010assert(numa_node_list_holder.get_count() > 0, "Multiple NUMA nodes expected");3011DWORD node = numa_node_list_holder.get_node_list_entry(count % numa_node_list_holder.get_count());3012p_new = (char *)virtualAllocExNuma(hProc, next_alloc_addr, bytes_to_rq, flags, prot, node);3013}3014}30153016if (p_new == NULL) {3017// Free any allocated pages3018if (next_alloc_addr > p_buf) {3019// Some memory was committed so release it.3020size_t bytes_to_release = bytes - bytes_remaining;3021// NMT has yet to record any individual blocks, so it3022// need to create a dummy 'reserve' record to match3023// the release.3024MemTracker::record_virtual_memory_reserve((address)p_buf,3025bytes_to_release, CALLER_PC);3026os::release_memory(p_buf, bytes_to_release);3027}3028#ifdef ASSERT3029if (should_inject_error) {3030log_develop_debug(pagesize)("Reserving pages individually failed.");3031}3032#endif3033return NULL;3034}30353036bytes_remaining -= bytes_to_rq;3037next_alloc_addr += bytes_to_rq;3038count++;3039}3040// Although the memory is allocated individually, it is returned as one.3041// NMT records it as one block.3042if ((flags & MEM_COMMIT) != 0) {3043MemTracker::record_virtual_memory_reserve_and_commit((address)p_buf, bytes, CALLER_PC);3044} else {3045MemTracker::record_virtual_memory_reserve((address)p_buf, bytes, CALLER_PC);3046}30473048// made it this far, success3049return p_buf;3050}30513052static size_t large_page_init_decide_size() {3053// print a warning if any large page related flag is specified on command line3054bool warn_on_failure = !FLAG_IS_DEFAULT(UseLargePages) ||3055!FLAG_IS_DEFAULT(LargePageSizeInBytes);30563057#define WARN(msg) if (warn_on_failure) { warning(msg); }30583059if (!request_lock_memory_privilege()) {3060WARN("JVM cannot use large page memory because it does not have enough privilege to lock pages in memory.");3061return 0;3062}30633064size_t size = GetLargePageMinimum();3065if (size == 0) {3066WARN("Large page is not supported by the processor.");3067return 0;3068}30693070#if defined(IA32) || defined(AMD64)3071if (size > 4*M || LargePageSizeInBytes > 4*M) {3072WARN("JVM cannot use large pages bigger than 4mb.");3073return 0;3074}3075#endif30763077if (LargePageSizeInBytes > 0 && LargePageSizeInBytes % size == 0) {3078size = LargePageSizeInBytes;3079}30803081#undef WARN30823083return size;3084}30853086void os::large_page_init() {3087if (!UseLargePages) {3088return;3089}30903091_large_page_size = large_page_init_decide_size();3092const size_t default_page_size = (size_t) vm_page_size();3093if (_large_page_size > default_page_size) {3094_page_sizes.add(_large_page_size);3095}30963097UseLargePages = _large_page_size != 0;3098}30993100int os::create_file_for_heap(const char* dir) {31013102const char name_template[] = "/jvmheap.XXXXXX";31033104size_t fullname_len = strlen(dir) + strlen(name_template);3105char *fullname = (char*)os::malloc(fullname_len + 1, mtInternal);3106if (fullname == NULL) {3107vm_exit_during_initialization(err_msg("Malloc failed during creation of backing file for heap (%s)", os::strerror(errno)));3108return -1;3109}3110int n = snprintf(fullname, fullname_len + 1, "%s%s", dir, name_template);3111assert((size_t)n == fullname_len, "Unexpected number of characters in string");31123113os::native_path(fullname);31143115char *path = _mktemp(fullname);3116if (path == NULL) {3117warning("_mktemp could not create file name from template %s (%s)", fullname, os::strerror(errno));3118os::free(fullname);3119return -1;3120}31213122int fd = _open(path, O_RDWR | O_CREAT | O_TEMPORARY | O_EXCL, S_IWRITE | S_IREAD);31233124os::free(fullname);3125if (fd < 0) {3126warning("Problem opening file for heap (%s)", os::strerror(errno));3127return -1;3128}3129return fd;3130}31313132// If 'base' is not NULL, function will return NULL if it cannot get 'base'3133char* os::map_memory_to_file(char* base, size_t size, int fd) {3134assert(fd != -1, "File descriptor is not valid");31353136HANDLE fh = (HANDLE)_get_osfhandle(fd);3137#ifdef _LP643138HANDLE fileMapping = CreateFileMapping(fh, NULL, PAGE_READWRITE,3139(DWORD)(size >> 32), (DWORD)(size & 0xFFFFFFFF), NULL);3140#else3141HANDLE fileMapping = CreateFileMapping(fh, NULL, PAGE_READWRITE,31420, (DWORD)size, NULL);3143#endif3144if (fileMapping == NULL) {3145if (GetLastError() == ERROR_DISK_FULL) {3146vm_exit_during_initialization(err_msg("Could not allocate sufficient disk space for Java heap"));3147}3148else {3149vm_exit_during_initialization(err_msg("Error in mapping Java heap at the given filesystem directory"));3150}31513152return NULL;3153}31543155LPVOID addr = mapViewOfFileEx(fileMapping, FILE_MAP_WRITE, 0, 0, size, base);31563157CloseHandle(fileMapping);31583159return (char*)addr;3160}31613162char* os::replace_existing_mapping_with_file_mapping(char* base, size_t size, int fd) {3163assert(fd != -1, "File descriptor is not valid");3164assert(base != NULL, "Base address cannot be NULL");31653166release_memory(base, size);3167return map_memory_to_file(base, size, fd);3168}31693170// Multiple threads can race in this code but it's not possible to unmap small sections of3171// virtual space to get requested alignment, like posix-like os's.3172// Windows prevents multiple thread from remapping over each other so this loop is thread-safe.3173static char* map_or_reserve_memory_aligned(size_t size, size_t alignment, int file_desc) {3174assert((alignment & (os::vm_allocation_granularity() - 1)) == 0,3175"Alignment must be a multiple of allocation granularity (page size)");3176assert((size & (alignment -1)) == 0, "size must be 'alignment' aligned");31773178size_t extra_size = size + alignment;3179assert(extra_size >= size, "overflow, size is too large to allow alignment");31803181char* aligned_base = NULL;3182static const int max_attempts = 20;31833184for (int attempt = 0; attempt < max_attempts && aligned_base == NULL; attempt ++) {3185char* extra_base = file_desc != -1 ? os::map_memory_to_file(extra_size, file_desc) :3186os::reserve_memory(extra_size);3187if (extra_base == NULL) {3188return NULL;3189}3190// Do manual alignment3191aligned_base = align_up(extra_base, alignment);31923193bool rc = (file_desc != -1) ? os::unmap_memory(extra_base, extra_size) :3194os::release_memory(extra_base, extra_size);3195assert(rc, "release failed");3196if (!rc) {3197return NULL;3198}31993200// Attempt to map, into the just vacated space, the slightly smaller aligned area.3201// Which may fail, hence the loop.3202aligned_base = file_desc != -1 ? os::attempt_map_memory_to_file_at(aligned_base, size, file_desc) :3203os::attempt_reserve_memory_at(aligned_base, size);3204}32053206assert(aligned_base != NULL, "Did not manage to re-map after %d attempts?", max_attempts);32073208return aligned_base;3209}32103211char* os::reserve_memory_aligned(size_t size, size_t alignment, bool exec) {3212// exec can be ignored3213return map_or_reserve_memory_aligned(size, alignment, -1 /* file_desc */);3214}32153216char* os::map_memory_to_file_aligned(size_t size, size_t alignment, int fd) {3217return map_or_reserve_memory_aligned(size, alignment, fd);3218}32193220char* os::pd_reserve_memory(size_t bytes, bool exec) {3221return pd_attempt_reserve_memory_at(NULL /* addr */, bytes, exec);3222}32233224// Reserve memory at an arbitrary address, only if that area is3225// available (and not reserved for something else).3226char* os::pd_attempt_reserve_memory_at(char* addr, size_t bytes, bool exec) {3227assert((size_t)addr % os::vm_allocation_granularity() == 0,3228"reserve alignment");3229assert(bytes % os::vm_page_size() == 0, "reserve page size");3230char* res;3231// note that if UseLargePages is on, all the areas that require interleaving3232// will go thru reserve_memory_special rather than thru here.3233bool use_individual = (UseNUMAInterleaving && !UseLargePages);3234if (!use_individual) {3235res = (char*)virtualAlloc(addr, bytes, MEM_RESERVE, PAGE_READWRITE);3236} else {3237elapsedTimer reserveTimer;3238if (Verbose && PrintMiscellaneous) reserveTimer.start();3239// in numa interleaving, we have to allocate pages individually3240// (well really chunks of NUMAInterleaveGranularity size)3241res = allocate_pages_individually(bytes, addr, MEM_RESERVE, PAGE_READWRITE);3242if (res == NULL) {3243warning("NUMA page allocation failed");3244}3245if (Verbose && PrintMiscellaneous) {3246reserveTimer.stop();3247tty->print_cr("reserve_memory of %Ix bytes took " JLONG_FORMAT " ms (" JLONG_FORMAT " ticks)", bytes,3248reserveTimer.milliseconds(), reserveTimer.ticks());3249}3250}3251assert(res == NULL || addr == NULL || addr == res,3252"Unexpected address from reserve.");32533254return res;3255}32563257char* os::pd_attempt_map_memory_to_file_at(char* requested_addr, size_t bytes, int file_desc) {3258assert(file_desc >= 0, "file_desc is not valid");3259return map_memory_to_file(requested_addr, bytes, file_desc);3260}32613262size_t os::large_page_size() {3263return _large_page_size;3264}32653266bool os::can_commit_large_page_memory() {3267// Windows only uses large page memory when the entire region is reserved3268// and committed in a single VirtualAlloc() call. This may change in the3269// future, but with Windows 2003 it's not possible to commit on demand.3270return false;3271}32723273bool os::can_execute_large_page_memory() {3274return true;3275}32763277static char* reserve_large_pages_individually(size_t size, char* req_addr, bool exec) {3278log_debug(pagesize)("Reserving large pages individually.");32793280const DWORD prot = exec ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE;3281const DWORD flags = MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES;32823283char * p_buf = allocate_pages_individually(size, req_addr, flags, prot, LargePagesIndividualAllocationInjectError);3284if (p_buf == NULL) {3285// give an appropriate warning message3286if (UseNUMAInterleaving) {3287warning("NUMA large page allocation failed, UseLargePages flag ignored");3288}3289if (UseLargePagesIndividualAllocation) {3290warning("Individually allocated large pages failed, "3291"use -XX:-UseLargePagesIndividualAllocation to turn off");3292}3293return NULL;3294}3295return p_buf;3296}32973298static char* reserve_large_pages_single_range(size_t size, char* req_addr, bool exec) {3299log_debug(pagesize)("Reserving large pages in a single large chunk.");33003301const DWORD prot = exec ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE;3302const DWORD flags = MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES;33033304return (char *) virtualAlloc(req_addr, size, flags, prot);3305}33063307static char* reserve_large_pages(size_t size, char* req_addr, bool exec) {3308// with large pages, there are two cases where we need to use Individual Allocation3309// 1) the UseLargePagesIndividualAllocation flag is set (set by default on WS2003)3310// 2) NUMA Interleaving is enabled, in which case we use a different node for each page3311if (UseLargePagesIndividualAllocation || UseNUMAInterleaving) {3312return reserve_large_pages_individually(size, req_addr, exec);3313}3314return reserve_large_pages_single_range(size, req_addr, exec);3315}33163317static char* find_aligned_address(size_t size, size_t alignment) {3318// Temporary reserve memory large enough to ensure we can get the requested3319// alignment and still fit the reservation.3320char* addr = (char*) virtualAlloc(NULL, size + alignment, MEM_RESERVE, PAGE_NOACCESS);3321// Align the address to the requested alignment.3322char* aligned_addr = align_up(addr, alignment);3323// Free the temporary reservation.3324virtualFree(addr, 0, MEM_RELEASE);33253326return aligned_addr;3327}33283329static char* reserve_large_pages_aligned(size_t size, size_t alignment, bool exec) {3330log_debug(pagesize)("Reserving large pages at an aligned address, alignment=" SIZE_FORMAT "%s",3331byte_size_in_exact_unit(alignment), exact_unit_for_byte_size(alignment));33323333// Will try to find a suitable address at most 20 times. The reason we need to try3334// multiple times is that between finding the aligned address and trying to commit3335// the large pages another thread might have reserved an overlapping region.3336const int attempts_limit = 20;3337for (int attempts = 0; attempts < attempts_limit; attempts++) {3338// Find aligned address.3339char* aligned_address = find_aligned_address(size, alignment);33403341// Try to do the large page reservation using the aligned address.3342aligned_address = reserve_large_pages(size, aligned_address, exec);3343if (aligned_address != NULL) {3344// Reservation at the aligned address succeeded.3345guarantee(is_aligned(aligned_address, alignment), "Must be aligned");3346return aligned_address;3347}3348}33493350log_debug(pagesize)("Failed reserving large pages at aligned address");3351return NULL;3352}33533354char* os::pd_reserve_memory_special(size_t bytes, size_t alignment, size_t page_size, char* addr,3355bool exec) {3356assert(UseLargePages, "only for large pages");3357assert(page_size == os::large_page_size(), "Currently only support one large page size on Windows");3358assert(is_aligned(addr, alignment), "Must be");3359assert(is_aligned(addr, page_size), "Must be");33603361if (!is_aligned(bytes, page_size)) {3362// Fallback to small pages, Windows does not support mixed mappings.3363return NULL;3364}33653366// The requested alignment can be larger than the page size, for example with G13367// the alignment is bound to the heap region size. So this reservation needs to3368// ensure that the requested alignment is met. When there is a requested address3369// this solves it self, since it must be properly aligned already.3370if (addr == NULL && alignment > page_size) {3371return reserve_large_pages_aligned(bytes, alignment, exec);3372}33733374// No additional requirements, just reserve the large pages.3375return reserve_large_pages(bytes, addr, exec);3376}33773378bool os::pd_release_memory_special(char* base, size_t bytes) {3379assert(base != NULL, "Sanity check");3380return pd_release_memory(base, bytes);3381}33823383void os::print_statistics() {3384}33853386static void warn_fail_commit_memory(char* addr, size_t bytes, bool exec) {3387int err = os::get_last_error();3388char buf[256];3389size_t buf_len = os::lasterror(buf, sizeof(buf));3390warning("INFO: os::commit_memory(" PTR_FORMAT ", " SIZE_FORMAT3391", %d) failed; error='%s' (DOS error/errno=%d)", addr, bytes,3392exec, buf_len != 0 ? buf : "<no_error_string>", err);3393}33943395bool os::pd_commit_memory(char* addr, size_t bytes, bool exec) {3396if (bytes == 0) {3397// Don't bother the OS with noops.3398return true;3399}3400assert((size_t) addr % os::vm_page_size() == 0, "commit on page boundaries");3401assert(bytes % os::vm_page_size() == 0, "commit in page-sized chunks");3402// Don't attempt to print anything if the OS call fails. We're3403// probably low on resources, so the print itself may cause crashes.34043405// unless we have NUMAInterleaving enabled, the range of a commit3406// is always within a reserve covered by a single VirtualAlloc3407// in that case we can just do a single commit for the requested size3408if (!UseNUMAInterleaving) {3409if (virtualAlloc(addr, bytes, MEM_COMMIT, PAGE_READWRITE) == NULL) {3410NOT_PRODUCT(warn_fail_commit_memory(addr, bytes, exec);)3411return false;3412}3413if (exec) {3414DWORD oldprot;3415// Windows doc says to use VirtualProtect to get execute permissions3416if (!VirtualProtect(addr, bytes, PAGE_EXECUTE_READWRITE, &oldprot)) {3417NOT_PRODUCT(warn_fail_commit_memory(addr, bytes, exec);)3418return false;3419}3420}3421return true;3422} else {34233424// when NUMAInterleaving is enabled, the commit might cover a range that3425// came from multiple VirtualAlloc reserves (using allocate_pages_individually).3426// VirtualQuery can help us determine that. The RegionSize that VirtualQuery3427// returns represents the number of bytes that can be committed in one step.3428size_t bytes_remaining = bytes;3429char * next_alloc_addr = addr;3430while (bytes_remaining > 0) {3431MEMORY_BASIC_INFORMATION alloc_info;3432VirtualQuery(next_alloc_addr, &alloc_info, sizeof(alloc_info));3433size_t bytes_to_rq = MIN2(bytes_remaining, (size_t)alloc_info.RegionSize);3434if (virtualAlloc(next_alloc_addr, bytes_to_rq, MEM_COMMIT,3435PAGE_READWRITE) == NULL) {3436NOT_PRODUCT(warn_fail_commit_memory(next_alloc_addr, bytes_to_rq,3437exec);)3438return false;3439}3440if (exec) {3441DWORD oldprot;3442if (!VirtualProtect(next_alloc_addr, bytes_to_rq,3443PAGE_EXECUTE_READWRITE, &oldprot)) {3444NOT_PRODUCT(warn_fail_commit_memory(next_alloc_addr, bytes_to_rq,3445exec);)3446return false;3447}3448}3449bytes_remaining -= bytes_to_rq;3450next_alloc_addr += bytes_to_rq;3451}3452}3453// if we made it this far, return true3454return true;3455}34563457bool os::pd_commit_memory(char* addr, size_t size, size_t alignment_hint,3458bool exec) {3459// alignment_hint is ignored on this OS3460return pd_commit_memory(addr, size, exec);3461}34623463void os::pd_commit_memory_or_exit(char* addr, size_t size, bool exec,3464const char* mesg) {3465assert(mesg != NULL, "mesg must be specified");3466if (!pd_commit_memory(addr, size, exec)) {3467warn_fail_commit_memory(addr, size, exec);3468vm_exit_out_of_memory(size, OOM_MMAP_ERROR, "%s", mesg);3469}3470}34713472void os::pd_commit_memory_or_exit(char* addr, size_t size,3473size_t alignment_hint, bool exec,3474const char* mesg) {3475// alignment_hint is ignored on this OS3476pd_commit_memory_or_exit(addr, size, exec, mesg);3477}34783479bool os::pd_uncommit_memory(char* addr, size_t bytes, bool exec) {3480if (bytes == 0) {3481// Don't bother the OS with noops.3482return true;3483}3484assert((size_t) addr % os::vm_page_size() == 0, "uncommit on page boundaries");3485assert(bytes % os::vm_page_size() == 0, "uncommit in page-sized chunks");3486return (virtualFree(addr, bytes, MEM_DECOMMIT) == TRUE);3487}34883489bool os::pd_release_memory(char* addr, size_t bytes) {3490// Given a range we are to release, we require a mapping to start at the beginning of that range;3491// if NUMA or LP we allow the range to contain multiple mappings, which have to cover the range3492// completely; otherwise the range must match an OS mapping exactly.3493address start = (address)addr;3494address end = start + bytes;3495os::win32::mapping_info_t mi;3496const bool multiple_mappings_allowed = UseLargePagesIndividualAllocation || UseNUMAInterleaving;3497address p = start;3498bool first_mapping = true;34993500do {3501// Find mapping and check it3502const char* err = NULL;3503if (!os::win32::find_mapping(p, &mi)) {3504err = "no mapping found";3505} else {3506if (first_mapping) {3507if (mi.base != start) {3508err = "base address mismatch";3509}3510if (multiple_mappings_allowed ? (mi.size > bytes) : (mi.size != bytes)) {3511err = "size mismatch";3512}3513} else {3514assert(p == mi.base && mi.size > 0, "Sanity");3515if (mi.base + mi.size > end) {3516err = "mapping overlaps end";3517}3518if (mi.size == 0) {3519err = "zero length mapping?"; // Should never happen; just to prevent endlessly looping in release.3520}3521}3522}3523// Handle mapping error. We assert in debug, unconditionally print a warning in release.3524if (err != NULL) {3525log_warning(os)("bad release: [" PTR_FORMAT "-" PTR_FORMAT "): %s", p2i(start), p2i(end), err);3526#ifdef ASSERT3527os::print_memory_mappings((char*)start, bytes, tty);3528assert(false, "bad release: [" PTR_FORMAT "-" PTR_FORMAT "): %s", p2i(start), p2i(end), err);3529#endif3530return false;3531}3532// Free this range3533if (virtualFree(p, 0, MEM_RELEASE) == FALSE) {3534return false;3535}3536first_mapping = false;3537p = mi.base + mi.size;3538} while (p < end);35393540return true;3541}35423543bool os::pd_create_stack_guard_pages(char* addr, size_t size) {3544return os::commit_memory(addr, size, !ExecMem);3545}35463547bool os::remove_stack_guard_pages(char* addr, size_t size) {3548return os::uncommit_memory(addr, size);3549}35503551static bool protect_pages_individually(char* addr, size_t bytes, unsigned int p, DWORD *old_status) {3552uint count = 0;3553bool ret = false;3554size_t bytes_remaining = bytes;3555char * next_protect_addr = addr;35563557// Use VirtualQuery() to get the chunk size.3558while (bytes_remaining) {3559MEMORY_BASIC_INFORMATION alloc_info;3560if (VirtualQuery(next_protect_addr, &alloc_info, sizeof(alloc_info)) == 0) {3561return false;3562}35633564size_t bytes_to_protect = MIN2(bytes_remaining, (size_t)alloc_info.RegionSize);3565// We used different API at allocate_pages_individually() based on UseNUMAInterleaving,3566// but we don't distinguish here as both cases are protected by same API.3567ret = VirtualProtect(next_protect_addr, bytes_to_protect, p, old_status) != 0;3568warning("Failed protecting pages individually for chunk #%u", count);3569if (!ret) {3570return false;3571}35723573bytes_remaining -= bytes_to_protect;3574next_protect_addr += bytes_to_protect;3575count++;3576}3577return ret;3578}35793580// Set protections specified3581bool os::protect_memory(char* addr, size_t bytes, ProtType prot,3582bool is_committed) {3583unsigned int p = 0;3584switch (prot) {3585case MEM_PROT_NONE: p = PAGE_NOACCESS; break;3586case MEM_PROT_READ: p = PAGE_READONLY; break;3587case MEM_PROT_RW: p = PAGE_READWRITE; break;3588case MEM_PROT_RWX: p = PAGE_EXECUTE_READWRITE; break;3589default:3590ShouldNotReachHere();3591}35923593DWORD old_status;35943595// Strange enough, but on Win32 one can change protection only for committed3596// memory, not a big deal anyway, as bytes less or equal than 64K3597if (!is_committed) {3598commit_memory_or_exit(addr, bytes, prot == MEM_PROT_RWX,3599"cannot commit protection page");3600}3601// One cannot use os::guard_memory() here, as on Win32 guard page3602// have different (one-shot) semantics, from MSDN on PAGE_GUARD:3603//3604// Pages in the region become guard pages. Any attempt to access a guard page3605// causes the system to raise a STATUS_GUARD_PAGE exception and turn off3606// the guard page status. Guard pages thus act as a one-time access alarm.3607bool ret;3608if (UseNUMAInterleaving) {3609// If UseNUMAInterleaving is enabled, the pages may have been allocated a chunk at a time,3610// so we must protect the chunks individually.3611ret = protect_pages_individually(addr, bytes, p, &old_status);3612} else {3613ret = VirtualProtect(addr, bytes, p, &old_status) != 0;3614}3615#ifdef ASSERT3616if (!ret) {3617int err = os::get_last_error();3618char buf[256];3619size_t buf_len = os::lasterror(buf, sizeof(buf));3620warning("INFO: os::protect_memory(" PTR_FORMAT ", " SIZE_FORMAT3621") failed; error='%s' (DOS error/errno=%d)", addr, bytes,3622buf_len != 0 ? buf : "<no_error_string>", err);3623}3624#endif3625return ret;3626}36273628bool os::guard_memory(char* addr, size_t bytes) {3629DWORD old_status;3630return VirtualProtect(addr, bytes, PAGE_READWRITE | PAGE_GUARD, &old_status) != 0;3631}36323633bool os::unguard_memory(char* addr, size_t bytes) {3634DWORD old_status;3635return VirtualProtect(addr, bytes, PAGE_READWRITE, &old_status) != 0;3636}36373638void os::pd_realign_memory(char *addr, size_t bytes, size_t alignment_hint) { }3639void os::pd_free_memory(char *addr, size_t bytes, size_t alignment_hint) { }3640void os::numa_make_global(char *addr, size_t bytes) { }3641void os::numa_make_local(char *addr, size_t bytes, int lgrp_hint) { }3642bool os::numa_topology_changed() { return false; }3643size_t os::numa_get_groups_num() { return MAX2(numa_node_list_holder.get_count(), 1); }3644int os::numa_get_group_id() { return 0; }3645size_t os::numa_get_leaf_groups(int *ids, size_t size) {3646if (numa_node_list_holder.get_count() == 0 && size > 0) {3647// Provide an answer for UMA systems3648ids[0] = 0;3649return 1;3650} else {3651// check for size bigger than actual groups_num3652size = MIN2(size, numa_get_groups_num());3653for (int i = 0; i < (int)size; i++) {3654ids[i] = numa_node_list_holder.get_node_list_entry(i);3655}3656return size;3657}3658}36593660int os::numa_get_group_id_for_address(const void* address) {3661return 0;3662}36633664bool os::get_page_info(char *start, page_info* info) {3665return false;3666}36673668char *os::scan_pages(char *start, char* end, page_info* page_expected,3669page_info* page_found) {3670return end;3671}36723673char* os::non_memory_address_word() {3674// Must never look like an address returned by reserve_memory,3675// even in its subfields (as defined by the CPU immediate fields,3676// if the CPU splits constants across multiple instructions).3677#ifdef _M_ARM643678// AArch64 has a maximum addressable space of 48-bits3679return (char*)((1ull << 48) - 1);3680#else3681return (char*)-1;3682#endif3683}36843685#define MAX_ERROR_COUNT 1003686#define SYS_THREAD_ERROR 0xffffffffUL36873688void os::pd_start_thread(Thread* thread) {3689DWORD ret = ResumeThread(thread->osthread()->thread_handle());3690// Returns previous suspend state:3691// 0: Thread was not suspended3692// 1: Thread is running now3693// >1: Thread is still suspended.3694assert(ret != SYS_THREAD_ERROR, "StartThread failed"); // should propagate back3695}369636973698// Short sleep, direct OS call.3699//3700// ms = 0, means allow others (if any) to run.3701//3702void os::naked_short_sleep(jlong ms) {3703assert(ms < 1000, "Un-interruptable sleep, short time use only");3704Sleep(ms);3705}37063707// Windows does not provide sleep functionality with nanosecond resolution, so we3708// try to approximate this with spinning combined with yielding if another thread3709// is ready to run on the current processor.3710void os::naked_short_nanosleep(jlong ns) {3711assert(ns > -1 && ns < NANOUNITS, "Un-interruptable sleep, short time use only");37123713int64_t start = os::javaTimeNanos();3714do {3715if (SwitchToThread() == 0) {3716// Nothing else is ready to run on this cpu, spin a little3717SpinPause();3718}3719} while (os::javaTimeNanos() - start < ns);3720}37213722// Sleep forever; naked call to OS-specific sleep; use with CAUTION3723void os::infinite_sleep() {3724while (true) { // sleep forever ...3725Sleep(100000); // ... 100 seconds at a time3726}3727}37283729typedef BOOL (WINAPI * STTSignature)(void);37303731void os::naked_yield() {3732// Consider passing back the return value from SwitchToThread().3733SwitchToThread();3734}37353736// Win32 only gives you access to seven real priorities at a time,3737// so we compress Java's ten down to seven. It would be better3738// if we dynamically adjusted relative priorities.37393740int os::java_to_os_priority[CriticalPriority + 1] = {3741THREAD_PRIORITY_IDLE, // 0 Entry should never be used3742THREAD_PRIORITY_LOWEST, // 1 MinPriority3743THREAD_PRIORITY_LOWEST, // 23744THREAD_PRIORITY_BELOW_NORMAL, // 33745THREAD_PRIORITY_BELOW_NORMAL, // 43746THREAD_PRIORITY_NORMAL, // 5 NormPriority3747THREAD_PRIORITY_NORMAL, // 63748THREAD_PRIORITY_ABOVE_NORMAL, // 73749THREAD_PRIORITY_ABOVE_NORMAL, // 83750THREAD_PRIORITY_HIGHEST, // 9 NearMaxPriority3751THREAD_PRIORITY_HIGHEST, // 10 MaxPriority3752THREAD_PRIORITY_HIGHEST // 11 CriticalPriority3753};37543755int prio_policy1[CriticalPriority + 1] = {3756THREAD_PRIORITY_IDLE, // 0 Entry should never be used3757THREAD_PRIORITY_LOWEST, // 1 MinPriority3758THREAD_PRIORITY_LOWEST, // 23759THREAD_PRIORITY_BELOW_NORMAL, // 33760THREAD_PRIORITY_BELOW_NORMAL, // 43761THREAD_PRIORITY_NORMAL, // 5 NormPriority3762THREAD_PRIORITY_ABOVE_NORMAL, // 63763THREAD_PRIORITY_ABOVE_NORMAL, // 73764THREAD_PRIORITY_HIGHEST, // 83765THREAD_PRIORITY_HIGHEST, // 9 NearMaxPriority3766THREAD_PRIORITY_TIME_CRITICAL, // 10 MaxPriority3767THREAD_PRIORITY_TIME_CRITICAL // 11 CriticalPriority3768};37693770static int prio_init() {3771// If ThreadPriorityPolicy is 1, switch tables3772if (ThreadPriorityPolicy == 1) {3773int i;3774for (i = 0; i < CriticalPriority + 1; i++) {3775os::java_to_os_priority[i] = prio_policy1[i];3776}3777}3778if (UseCriticalJavaThreadPriority) {3779os::java_to_os_priority[MaxPriority] = os::java_to_os_priority[CriticalPriority];3780}3781return 0;3782}37833784OSReturn os::set_native_priority(Thread* thread, int priority) {3785if (!UseThreadPriorities) return OS_OK;3786bool ret = SetThreadPriority(thread->osthread()->thread_handle(), priority) != 0;3787return ret ? OS_OK : OS_ERR;3788}37893790OSReturn os::get_native_priority(const Thread* const thread,3791int* priority_ptr) {3792if (!UseThreadPriorities) {3793*priority_ptr = java_to_os_priority[NormPriority];3794return OS_OK;3795}3796int os_prio = GetThreadPriority(thread->osthread()->thread_handle());3797if (os_prio == THREAD_PRIORITY_ERROR_RETURN) {3798assert(false, "GetThreadPriority failed");3799return OS_ERR;3800}3801*priority_ptr = os_prio;3802return OS_OK;3803}38043805// GetCurrentThreadId() returns DWORD3806intx os::current_thread_id() { return GetCurrentThreadId(); }38073808static int _initial_pid = 0;38093810int os::current_process_id() {3811return (_initial_pid ? _initial_pid : _getpid());3812}38133814int os::win32::_vm_page_size = 0;3815int os::win32::_vm_allocation_granularity = 0;3816int os::win32::_processor_type = 0;3817// Processor level is not available on non-NT systems, use vm_version instead3818int os::win32::_processor_level = 0;3819julong os::win32::_physical_memory = 0;3820size_t os::win32::_default_stack_size = 0;38213822intx os::win32::_os_thread_limit = 0;3823volatile intx os::win32::_os_thread_count = 0;38243825bool os::win32::_is_windows_server = false;38263827// 65732543828// Currently, the bug is observed across all the supported Windows releases,3829// including the latest one (as of this writing - Windows Server 2012 R2)3830bool os::win32::_has_exit_bug = true;38313832void os::win32::initialize_system_info() {3833SYSTEM_INFO si;3834GetSystemInfo(&si);3835_vm_page_size = si.dwPageSize;3836_vm_allocation_granularity = si.dwAllocationGranularity;3837_processor_type = si.dwProcessorType;3838_processor_level = si.wProcessorLevel;3839set_processor_count(si.dwNumberOfProcessors);38403841MEMORYSTATUSEX ms;3842ms.dwLength = sizeof(ms);38433844// also returns dwAvailPhys (free physical memory bytes), dwTotalVirtual, dwAvailVirtual,3845// dwMemoryLoad (% of memory in use)3846GlobalMemoryStatusEx(&ms);3847_physical_memory = ms.ullTotalPhys;38483849if (FLAG_IS_DEFAULT(MaxRAM)) {3850// Adjust MaxRAM according to the maximum virtual address space available.3851FLAG_SET_DEFAULT(MaxRAM, MIN2(MaxRAM, (uint64_t) ms.ullTotalVirtual));3852}38533854OSVERSIONINFOEX oi;3855oi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);3856GetVersionEx((OSVERSIONINFO*)&oi);3857switch (oi.dwPlatformId) {3858case VER_PLATFORM_WIN32_NT:3859{3860int os_vers = oi.dwMajorVersion * 1000 + oi.dwMinorVersion;3861if (oi.wProductType == VER_NT_DOMAIN_CONTROLLER ||3862oi.wProductType == VER_NT_SERVER) {3863_is_windows_server = true;3864}3865}3866break;3867default: fatal("Unknown platform");3868}38693870_default_stack_size = os::current_stack_size();3871assert(_default_stack_size > (size_t) _vm_page_size, "invalid stack size");3872assert((_default_stack_size & (_vm_page_size - 1)) == 0,3873"stack size not a multiple of page size");38743875initialize_performance_counter();3876}387738783879HINSTANCE os::win32::load_Windows_dll(const char* name, char *ebuf,3880int ebuflen) {3881char path[MAX_PATH];3882DWORD size;3883DWORD pathLen = (DWORD)sizeof(path);3884HINSTANCE result = NULL;38853886// only allow library name without path component3887assert(strchr(name, '\\') == NULL, "path not allowed");3888assert(strchr(name, ':') == NULL, "path not allowed");3889if (strchr(name, '\\') != NULL || strchr(name, ':') != NULL) {3890jio_snprintf(ebuf, ebuflen,3891"Invalid parameter while calling os::win32::load_windows_dll(): cannot take path: %s", name);3892return NULL;3893}38943895// search system directory3896if ((size = GetSystemDirectory(path, pathLen)) > 0) {3897if (size >= pathLen) {3898return NULL; // truncated3899}3900if (jio_snprintf(path + size, pathLen - size, "\\%s", name) == -1) {3901return NULL; // truncated3902}3903if ((result = (HINSTANCE)os::dll_load(path, ebuf, ebuflen)) != NULL) {3904return result;3905}3906}39073908// try Windows directory3909if ((size = GetWindowsDirectory(path, pathLen)) > 0) {3910if (size >= pathLen) {3911return NULL; // truncated3912}3913if (jio_snprintf(path + size, pathLen - size, "\\%s", name) == -1) {3914return NULL; // truncated3915}3916if ((result = (HINSTANCE)os::dll_load(path, ebuf, ebuflen)) != NULL) {3917return result;3918}3919}39203921jio_snprintf(ebuf, ebuflen,3922"os::win32::load_windows_dll() cannot load %s from system directories.", name);3923return NULL;3924}39253926#define MAXIMUM_THREADS_TO_KEEP (16 * MAXIMUM_WAIT_OBJECTS)3927#define EXIT_TIMEOUT 300000 /* 5 minutes */39283929static BOOL CALLBACK init_crit_sect_call(PINIT_ONCE, PVOID pcrit_sect, PVOID*) {3930InitializeCriticalSection((CRITICAL_SECTION*)pcrit_sect);3931return TRUE;3932}39333934int os::win32::exit_process_or_thread(Ept what, int exit_code) {3935// Basic approach:3936// - Each exiting thread registers its intent to exit and then does so.3937// - A thread trying to terminate the process must wait for all3938// threads currently exiting to complete their exit.39393940if (os::win32::has_exit_bug()) {3941// The array holds handles of the threads that have started exiting by calling3942// _endthreadex().3943// Should be large enough to avoid blocking the exiting thread due to lack of3944// a free slot.3945static HANDLE handles[MAXIMUM_THREADS_TO_KEEP];3946static int handle_count = 0;39473948static INIT_ONCE init_once_crit_sect = INIT_ONCE_STATIC_INIT;3949static CRITICAL_SECTION crit_sect;3950static volatile DWORD process_exiting = 0;3951int i, j;3952DWORD res;3953HANDLE hproc, hthr;39543955// We only attempt to register threads until a process exiting3956// thread manages to set the process_exiting flag. Any threads3957// that come through here after the process_exiting flag is set3958// are unregistered and will be caught in the SuspendThread()3959// infinite loop below.3960bool registered = false;39613962// The first thread that reached this point, initializes the critical section.3963if (!InitOnceExecuteOnce(&init_once_crit_sect, init_crit_sect_call, &crit_sect, NULL)) {3964warning("crit_sect initialization failed in %s: %d\n", __FILE__, __LINE__);3965} else if (Atomic::load_acquire(&process_exiting) == 0) {3966if (what != EPT_THREAD) {3967// Atomically set process_exiting before the critical section3968// to increase the visibility between racing threads.3969Atomic::cmpxchg(&process_exiting, (DWORD)0, GetCurrentThreadId());3970}3971EnterCriticalSection(&crit_sect);39723973if (what == EPT_THREAD && Atomic::load_acquire(&process_exiting) == 0) {3974// Remove from the array those handles of the threads that have completed exiting.3975for (i = 0, j = 0; i < handle_count; ++i) {3976res = WaitForSingleObject(handles[i], 0 /* don't wait */);3977if (res == WAIT_TIMEOUT) {3978handles[j++] = handles[i];3979} else {3980if (res == WAIT_FAILED) {3981warning("WaitForSingleObject failed (%u) in %s: %d\n",3982GetLastError(), __FILE__, __LINE__);3983}3984// Don't keep the handle, if we failed waiting for it.3985CloseHandle(handles[i]);3986}3987}39883989// If there's no free slot in the array of the kept handles, we'll have to3990// wait until at least one thread completes exiting.3991if ((handle_count = j) == MAXIMUM_THREADS_TO_KEEP) {3992// Raise the priority of the oldest exiting thread to increase its chances3993// to complete sooner.3994SetThreadPriority(handles[0], THREAD_PRIORITY_ABOVE_NORMAL);3995res = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, handles, FALSE, EXIT_TIMEOUT);3996if (res >= WAIT_OBJECT_0 && res < (WAIT_OBJECT_0 + MAXIMUM_WAIT_OBJECTS)) {3997i = (res - WAIT_OBJECT_0);3998handle_count = MAXIMUM_THREADS_TO_KEEP - 1;3999for (; i < handle_count; ++i) {4000handles[i] = handles[i + 1];4001}4002} else {4003warning("WaitForMultipleObjects %s (%u) in %s: %d\n",4004(res == WAIT_FAILED ? "failed" : "timed out"),4005GetLastError(), __FILE__, __LINE__);4006// Don't keep handles, if we failed waiting for them.4007for (i = 0; i < MAXIMUM_THREADS_TO_KEEP; ++i) {4008CloseHandle(handles[i]);4009}4010handle_count = 0;4011}4012}40134014// Store a duplicate of the current thread handle in the array of handles.4015hproc = GetCurrentProcess();4016hthr = GetCurrentThread();4017if (!DuplicateHandle(hproc, hthr, hproc, &handles[handle_count],40180, FALSE, DUPLICATE_SAME_ACCESS)) {4019warning("DuplicateHandle failed (%u) in %s: %d\n",4020GetLastError(), __FILE__, __LINE__);40214022// We can't register this thread (no more handles) so this thread4023// may be racing with a thread that is calling exit(). If the thread4024// that is calling exit() has managed to set the process_exiting4025// flag, then this thread will be caught in the SuspendThread()4026// infinite loop below which closes that race. A small timing4027// window remains before the process_exiting flag is set, but it4028// is only exposed when we are out of handles.4029} else {4030++handle_count;4031registered = true;40324033// The current exiting thread has stored its handle in the array, and now4034// should leave the critical section before calling _endthreadex().4035}40364037} else if (what != EPT_THREAD && handle_count > 0) {4038jlong start_time, finish_time, timeout_left;4039// Before ending the process, make sure all the threads that had called4040// _endthreadex() completed.40414042// Set the priority level of the current thread to the same value as4043// the priority level of exiting threads.4044// This is to ensure it will be given a fair chance to execute if4045// the timeout expires.4046hthr = GetCurrentThread();4047SetThreadPriority(hthr, THREAD_PRIORITY_ABOVE_NORMAL);4048start_time = os::javaTimeNanos();4049finish_time = start_time + ((jlong)EXIT_TIMEOUT * 1000000L);4050for (i = 0; ; ) {4051int portion_count = handle_count - i;4052if (portion_count > MAXIMUM_WAIT_OBJECTS) {4053portion_count = MAXIMUM_WAIT_OBJECTS;4054}4055for (j = 0; j < portion_count; ++j) {4056SetThreadPriority(handles[i + j], THREAD_PRIORITY_ABOVE_NORMAL);4057}4058timeout_left = (finish_time - start_time) / 1000000L;4059if (timeout_left < 0) {4060timeout_left = 0;4061}4062res = WaitForMultipleObjects(portion_count, handles + i, TRUE, timeout_left);4063if (res == WAIT_FAILED || res == WAIT_TIMEOUT) {4064warning("WaitForMultipleObjects %s (%u) in %s: %d\n",4065(res == WAIT_FAILED ? "failed" : "timed out"),4066GetLastError(), __FILE__, __LINE__);4067// Reset portion_count so we close the remaining4068// handles due to this error.4069portion_count = handle_count - i;4070}4071for (j = 0; j < portion_count; ++j) {4072CloseHandle(handles[i + j]);4073}4074if ((i += portion_count) >= handle_count) {4075break;4076}4077start_time = os::javaTimeNanos();4078}4079handle_count = 0;4080}40814082LeaveCriticalSection(&crit_sect);4083}40844085if (!registered &&4086Atomic::load_acquire(&process_exiting) != 0 &&4087process_exiting != GetCurrentThreadId()) {4088// Some other thread is about to call exit(), so we don't let4089// the current unregistered thread proceed to exit() or _endthreadex()4090while (true) {4091SuspendThread(GetCurrentThread());4092// Avoid busy-wait loop, if SuspendThread() failed.4093Sleep(EXIT_TIMEOUT);4094}4095}4096}40974098// We are here if either4099// - there's no 'race at exit' bug on this OS release;4100// - initialization of the critical section failed (unlikely);4101// - the current thread has registered itself and left the critical section;4102// - the process-exiting thread has raised the flag and left the critical section.4103if (what == EPT_THREAD) {4104_endthreadex((unsigned)exit_code);4105} else if (what == EPT_PROCESS) {4106::exit(exit_code);4107} else {4108_exit(exit_code);4109}41104111// Should not reach here4112return exit_code;4113}41144115#undef EXIT_TIMEOUT41164117void os::win32::setmode_streams() {4118_setmode(_fileno(stdin), _O_BINARY);4119_setmode(_fileno(stdout), _O_BINARY);4120_setmode(_fileno(stderr), _O_BINARY);4121}41224123void os::wait_for_keypress_at_exit(void) {4124if (PauseAtExit) {4125fprintf(stderr, "Press any key to continue...\n");4126fgetc(stdin);4127}4128}412941304131bool os::message_box(const char* title, const char* message) {4132int result = MessageBox(NULL, message, title,4133MB_YESNO | MB_ICONERROR | MB_SYSTEMMODAL | MB_DEFAULT_DESKTOP_ONLY);4134return result == IDYES;4135}41364137#ifndef PRODUCT4138#ifndef _WIN644139// Helpers to check whether NX protection is enabled4140int nx_exception_filter(_EXCEPTION_POINTERS *pex) {4141if (pex->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION &&4142pex->ExceptionRecord->NumberParameters > 0 &&4143pex->ExceptionRecord->ExceptionInformation[0] ==4144EXCEPTION_INFO_EXEC_VIOLATION) {4145return EXCEPTION_EXECUTE_HANDLER;4146}4147return EXCEPTION_CONTINUE_SEARCH;4148}41494150void nx_check_protection() {4151// If NX is enabled we'll get an exception calling into code on the stack4152char code[] = { (char)0xC3 }; // ret4153void *code_ptr = (void *)code;4154__try {4155__asm call code_ptr4156} __except(nx_exception_filter((_EXCEPTION_POINTERS*)_exception_info())) {4157tty->print_raw_cr("NX protection detected.");4158}4159}4160#endif // _WIN644161#endif // PRODUCT41624163// This is called _before_ the global arguments have been parsed4164void os::init(void) {4165_initial_pid = _getpid();41664167win32::initialize_system_info();4168win32::setmode_streams();4169_page_sizes.add(win32::vm_page_size());41704171// This may be overridden later when argument processing is done.4172FLAG_SET_ERGO(UseLargePagesIndividualAllocation, false);41734174// Initialize main_process and main_thread4175main_process = GetCurrentProcess(); // Remember main_process is a pseudo handle4176if (!DuplicateHandle(main_process, GetCurrentThread(), main_process,4177&main_thread, THREAD_ALL_ACCESS, false, 0)) {4178fatal("DuplicateHandle failed\n");4179}4180main_thread_id = (int) GetCurrentThreadId();41814182// initialize fast thread access - only used for 32-bit4183win32::initialize_thread_ptr_offset();4184}41854186// To install functions for atexit processing4187extern "C" {4188static void perfMemory_exit_helper() {4189perfMemory_exit();4190}4191}41924193static jint initSock();41944195// this is called _after_ the global arguments have been parsed4196jint os::init_2(void) {41974198// This could be set any time but all platforms4199// have to set it the same so we have to mirror Solaris.4200DEBUG_ONLY(os::set_mutex_init_done();)42014202// Setup Windows Exceptions42034204#if defined(USE_VECTORED_EXCEPTION_HANDLING)4205topLevelVectoredExceptionHandler = AddVectoredExceptionHandler(1, topLevelVectoredExceptionFilter);4206previousUnhandledExceptionFilter = SetUnhandledExceptionFilter(topLevelUnhandledExceptionFilter);4207#endif42084209// for debugging float code generation bugs4210#if defined(ASSERT) && !defined(_WIN64)4211static long fp_control_word = 0;4212__asm { fstcw fp_control_word }4213// see Intel PPro Manual, Vol. 2, p 7-164214const long invalid = 0x01;4215fp_control_word |= invalid;4216__asm { fldcw fp_control_word }4217#endif42184219// If stack_commit_size is 0, windows will reserve the default size,4220// but only commit a small portion of it.4221size_t stack_commit_size = align_up(ThreadStackSize*K, os::vm_page_size());4222size_t default_reserve_size = os::win32::default_stack_size();4223size_t actual_reserve_size = stack_commit_size;4224if (stack_commit_size < default_reserve_size) {4225// If stack_commit_size == 0, we want this too4226actual_reserve_size = default_reserve_size;4227}42284229// Check minimum allowable stack size for thread creation and to initialize4230// the java system classes, including StackOverflowError - depends on page4231// size. Add two 4K pages for compiler2 recursion in main thread.4232// Add in 4*BytesPerWord 4K pages to account for VM stack during4233// class initialization depending on 32 or 64 bit VM.4234size_t min_stack_allowed =4235(size_t)(StackOverflow::stack_guard_zone_size() +4236StackOverflow::stack_shadow_zone_size() +4237(4*BytesPerWord COMPILER2_PRESENT(+2)) * 4 * K);42384239min_stack_allowed = align_up(min_stack_allowed, os::vm_page_size());42404241if (actual_reserve_size < min_stack_allowed) {4242tty->print_cr("\nThe Java thread stack size specified is too small. "4243"Specify at least %dk",4244min_stack_allowed / K);4245return JNI_ERR;4246}42474248JavaThread::set_stack_size_at_create(stack_commit_size);42494250// Calculate theoretical max. size of Threads to guard gainst artifical4251// out-of-memory situations, where all available address-space has been4252// reserved by thread stacks.4253assert(actual_reserve_size != 0, "Must have a stack");42544255// Calculate the thread limit when we should start doing Virtual Memory4256// banging. Currently when the threads will have used all but 200Mb of space.4257//4258// TODO: consider performing a similar calculation for commit size instead4259// as reserve size, since on a 64-bit platform we'll run into that more4260// often than running out of virtual memory space. We can use the4261// lower value of the two calculations as the os_thread_limit.4262size_t max_address_space = ((size_t)1 << (BitsPerWord - 1)) - (200 * K * K);4263win32::_os_thread_limit = (intx)(max_address_space / actual_reserve_size);42644265// at exit methods are called in the reverse order of their registration.4266// there is no limit to the number of functions registered. atexit does4267// not set errno.42684269if (PerfAllowAtExitRegistration) {4270// only register atexit functions if PerfAllowAtExitRegistration is set.4271// atexit functions can be delayed until process exit time, which4272// can be problematic for embedded VM situations. Embedded VMs should4273// call DestroyJavaVM() to assure that VM resources are released.42744275// note: perfMemory_exit_helper atexit function may be removed in4276// the future if the appropriate cleanup code can be added to the4277// VM_Exit VMOperation's doit method.4278if (atexit(perfMemory_exit_helper) != 0) {4279warning("os::init_2 atexit(perfMemory_exit_helper) failed");4280}4281}42824283#ifndef _WIN644284// Print something if NX is enabled (win32 on AMD64)4285NOT_PRODUCT(if (PrintMiscellaneous && Verbose) nx_check_protection());4286#endif42874288// initialize thread priority policy4289prio_init();42904291UseNUMA = false; // We don't fully support this yet42924293if (UseNUMAInterleaving || (UseNUMA && FLAG_IS_DEFAULT(UseNUMAInterleaving))) {4294if (!numa_interleaving_init()) {4295FLAG_SET_ERGO(UseNUMAInterleaving, false);4296} else if (!UseNUMAInterleaving) {4297// When NUMA requested, not-NUMA-aware allocations default to interleaving.4298FLAG_SET_ERGO(UseNUMAInterleaving, true);4299}4300}43014302if (initSock() != JNI_OK) {4303return JNI_ERR;4304}43054306SymbolEngine::recalc_search_path();43074308// Initialize data for jdk.internal.misc.Signal4309if (!ReduceSignalUsage) {4310jdk_misc_signal_init();4311}43124313return JNI_OK;4314}43154316// combine the high and low DWORD into a ULONGLONG4317static ULONGLONG make_double_word(DWORD high_word, DWORD low_word) {4318ULONGLONG value = high_word;4319value <<= sizeof(high_word) * 8;4320value |= low_word;4321return value;4322}43234324// Transfers data from WIN32_FILE_ATTRIBUTE_DATA structure to struct stat4325static void file_attribute_data_to_stat(struct stat* sbuf, WIN32_FILE_ATTRIBUTE_DATA file_data) {4326::memset((void*)sbuf, 0, sizeof(struct stat));4327sbuf->st_size = (_off_t)make_double_word(file_data.nFileSizeHigh, file_data.nFileSizeLow);4328sbuf->st_mtime = make_double_word(file_data.ftLastWriteTime.dwHighDateTime,4329file_data.ftLastWriteTime.dwLowDateTime);4330sbuf->st_ctime = make_double_word(file_data.ftCreationTime.dwHighDateTime,4331file_data.ftCreationTime.dwLowDateTime);4332sbuf->st_atime = make_double_word(file_data.ftLastAccessTime.dwHighDateTime,4333file_data.ftLastAccessTime.dwLowDateTime);4334if ((file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) {4335sbuf->st_mode |= S_IFDIR;4336} else {4337sbuf->st_mode |= S_IFREG;4338}4339}43404341static errno_t convert_to_unicode(char const* char_path, LPWSTR* unicode_path) {4342// Get required buffer size to convert to Unicode4343int unicode_path_len = MultiByteToWideChar(CP_ACP,4344MB_ERR_INVALID_CHARS,4345char_path, -1,4346NULL, 0);4347if (unicode_path_len == 0) {4348return EINVAL;4349}43504351*unicode_path = NEW_C_HEAP_ARRAY(WCHAR, unicode_path_len, mtInternal);43524353int result = MultiByteToWideChar(CP_ACP,4354MB_ERR_INVALID_CHARS,4355char_path, -1,4356*unicode_path, unicode_path_len);4357assert(result == unicode_path_len, "length already checked above");43584359return ERROR_SUCCESS;4360}43614362static errno_t get_full_path(LPCWSTR unicode_path, LPWSTR* full_path) {4363// Get required buffer size to convert to full path. The return4364// value INCLUDES the terminating null character.4365DWORD full_path_len = GetFullPathNameW(unicode_path, 0, NULL, NULL);4366if (full_path_len == 0) {4367return EINVAL;4368}43694370*full_path = NEW_C_HEAP_ARRAY(WCHAR, full_path_len, mtInternal);43714372// When the buffer has sufficient size, the return value EXCLUDES the4373// terminating null character4374DWORD result = GetFullPathNameW(unicode_path, full_path_len, *full_path, NULL);4375assert(result <= full_path_len, "length already checked above");43764377return ERROR_SUCCESS;4378}43794380static void set_path_prefix(char* buf, LPWSTR* prefix, int* prefix_off, bool* needs_fullpath) {4381*prefix_off = 0;4382*needs_fullpath = true;43834384if (::isalpha(buf[0]) && !::IsDBCSLeadByte(buf[0]) && buf[1] == ':' && buf[2] == '\\') {4385*prefix = L"\\\\?\\";4386} else if (buf[0] == '\\' && buf[1] == '\\') {4387if (buf[2] == '?' && buf[3] == '\\') {4388*prefix = L"";4389*needs_fullpath = false;4390} else {4391*prefix = L"\\\\?\\UNC";4392*prefix_off = 1; // Overwrite the first char with the prefix, so \\share\path becomes \\?\UNC\share\path4393}4394} else {4395*prefix = L"\\\\?\\";4396}4397}43984399// Returns the given path as an absolute wide path in unc format. The returned path is NULL4400// on error (with err being set accordingly) and should be freed via os::free() otherwise.4401// additional_space is the size of space, in wchar_t, the function will additionally add to4402// the allocation of return buffer (such that the size of the returned buffer is at least4403// wcslen(buf) + 1 + additional_space).4404static wchar_t* wide_abs_unc_path(char const* path, errno_t & err, int additional_space = 0) {4405if ((path == NULL) || (path[0] == '\0')) {4406err = ENOENT;4407return NULL;4408}44094410// Need to allocate at least room for 3 characters, since os::native_path transforms C: to C:.4411size_t buf_len = 1 + MAX2((size_t)3, strlen(path));4412char* buf = NEW_C_HEAP_ARRAY(char, buf_len, mtInternal);4413strncpy(buf, path, buf_len);4414os::native_path(buf);44154416LPWSTR prefix = NULL;4417int prefix_off = 0;4418bool needs_fullpath = true;4419set_path_prefix(buf, &prefix, &prefix_off, &needs_fullpath);44204421LPWSTR unicode_path = NULL;4422err = convert_to_unicode(buf, &unicode_path);4423FREE_C_HEAP_ARRAY(char, buf);4424if (err != ERROR_SUCCESS) {4425return NULL;4426}44274428LPWSTR converted_path = NULL;4429if (needs_fullpath) {4430err = get_full_path(unicode_path, &converted_path);4431} else {4432converted_path = unicode_path;4433}44344435LPWSTR result = NULL;4436if (converted_path != NULL) {4437size_t prefix_len = wcslen(prefix);4438size_t result_len = prefix_len - prefix_off + wcslen(converted_path) + additional_space + 1;4439result = NEW_C_HEAP_ARRAY(WCHAR, result_len, mtInternal);4440_snwprintf(result, result_len, L"%s%s", prefix, &converted_path[prefix_off]);44414442// Remove trailing pathsep (not for \\?\<DRIVE>:\, since it would make it relative)4443result_len = wcslen(result);4444if ((result[result_len - 1] == L'\\') &&4445!(::iswalpha(result[4]) && result[5] == L':' && result_len == 7)) {4446result[result_len - 1] = L'\0';4447}4448}44494450if (converted_path != unicode_path) {4451FREE_C_HEAP_ARRAY(WCHAR, converted_path);4452}4453FREE_C_HEAP_ARRAY(WCHAR, unicode_path);44544455return static_cast<wchar_t*>(result); // LPWSTR and wchat_t* are the same type on Windows.4456}44574458int os::stat(const char *path, struct stat *sbuf) {4459errno_t err;4460wchar_t* wide_path = wide_abs_unc_path(path, err);44614462if (wide_path == NULL) {4463errno = err;4464return -1;4465}44664467WIN32_FILE_ATTRIBUTE_DATA file_data;;4468BOOL bret = ::GetFileAttributesExW(wide_path, GetFileExInfoStandard, &file_data);4469os::free(wide_path);44704471if (!bret) {4472errno = ::GetLastError();4473return -1;4474}44754476file_attribute_data_to_stat(sbuf, file_data);4477return 0;4478}44794480static HANDLE create_read_only_file_handle(const char* file) {4481errno_t err;4482wchar_t* wide_path = wide_abs_unc_path(file, err);44834484if (wide_path == NULL) {4485errno = err;4486return INVALID_HANDLE_VALUE;4487}44884489HANDLE handle = ::CreateFileW(wide_path, 0, FILE_SHARE_READ,4490NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);4491os::free(wide_path);44924493return handle;4494}44954496bool os::same_files(const char* file1, const char* file2) {44974498if (file1 == NULL && file2 == NULL) {4499return true;4500}45014502if (file1 == NULL || file2 == NULL) {4503return false;4504}45054506if (strcmp(file1, file2) == 0) {4507return true;4508}45094510char* native_file1 = os::strdup_check_oom(file1);4511native_file1 = os::native_path(native_file1);4512char* native_file2 = os::strdup_check_oom(file2);4513native_file2 = os::native_path(native_file2);4514if (strcmp(native_file1, native_file2) == 0) {4515os::free(native_file1);4516os::free(native_file2);4517return true;4518}45194520HANDLE handle1 = create_read_only_file_handle(native_file1);4521HANDLE handle2 = create_read_only_file_handle(native_file2);4522bool result = false;45234524// if we could open both paths...4525if (handle1 != INVALID_HANDLE_VALUE && handle2 != INVALID_HANDLE_VALUE) {4526BY_HANDLE_FILE_INFORMATION fileInfo1;4527BY_HANDLE_FILE_INFORMATION fileInfo2;4528if (::GetFileInformationByHandle(handle1, &fileInfo1) &&4529::GetFileInformationByHandle(handle2, &fileInfo2)) {4530// the paths are the same if they refer to the same file (fileindex) on the same volume (volume serial number)4531if (fileInfo1.dwVolumeSerialNumber == fileInfo2.dwVolumeSerialNumber &&4532fileInfo1.nFileIndexHigh == fileInfo2.nFileIndexHigh &&4533fileInfo1.nFileIndexLow == fileInfo2.nFileIndexLow) {4534result = true;4535}4536}4537}45384539//free the handles4540if (handle1 != INVALID_HANDLE_VALUE) {4541::CloseHandle(handle1);4542}45434544if (handle2 != INVALID_HANDLE_VALUE) {4545::CloseHandle(handle2);4546}45474548os::free(native_file1);4549os::free(native_file2);45504551return result;4552}45534554#define FT2INT64(ft) \4555((jlong)((jlong)(ft).dwHighDateTime << 32 | (julong)(ft).dwLowDateTime))455645574558// current_thread_cpu_time(bool) and thread_cpu_time(Thread*, bool)4559// are used by JVM M&M and JVMTI to get user+sys or user CPU time4560// of a thread.4561//4562// current_thread_cpu_time() and thread_cpu_time(Thread*) returns4563// the fast estimate available on the platform.45644565// current_thread_cpu_time() is not optimized for Windows yet4566jlong os::current_thread_cpu_time() {4567// return user + sys since the cost is the same4568return os::thread_cpu_time(Thread::current(), true /* user+sys */);4569}45704571jlong os::thread_cpu_time(Thread* thread) {4572// consistent with what current_thread_cpu_time() returns.4573return os::thread_cpu_time(thread, true /* user+sys */);4574}45754576jlong os::current_thread_cpu_time(bool user_sys_cpu_time) {4577return os::thread_cpu_time(Thread::current(), user_sys_cpu_time);4578}45794580jlong os::thread_cpu_time(Thread* thread, bool user_sys_cpu_time) {4581// This code is copy from clasic VM -> hpi::sysThreadCPUTime4582// If this function changes, os::is_thread_cpu_time_supported() should too4583FILETIME CreationTime;4584FILETIME ExitTime;4585FILETIME KernelTime;4586FILETIME UserTime;45874588if (GetThreadTimes(thread->osthread()->thread_handle(), &CreationTime,4589&ExitTime, &KernelTime, &UserTime) == 0) {4590return -1;4591} else if (user_sys_cpu_time) {4592return (FT2INT64(UserTime) + FT2INT64(KernelTime)) * 100;4593} else {4594return FT2INT64(UserTime) * 100;4595}4596}45974598void os::current_thread_cpu_time_info(jvmtiTimerInfo *info_ptr) {4599info_ptr->max_value = ALL_64_BITS; // the max value -- all 64 bits4600info_ptr->may_skip_backward = false; // GetThreadTimes returns absolute time4601info_ptr->may_skip_forward = false; // GetThreadTimes returns absolute time4602info_ptr->kind = JVMTI_TIMER_TOTAL_CPU; // user+system time is returned4603}46044605void os::thread_cpu_time_info(jvmtiTimerInfo *info_ptr) {4606info_ptr->max_value = ALL_64_BITS; // the max value -- all 64 bits4607info_ptr->may_skip_backward = false; // GetThreadTimes returns absolute time4608info_ptr->may_skip_forward = false; // GetThreadTimes returns absolute time4609info_ptr->kind = JVMTI_TIMER_TOTAL_CPU; // user+system time is returned4610}46114612bool os::is_thread_cpu_time_supported() {4613// see os::thread_cpu_time4614FILETIME CreationTime;4615FILETIME ExitTime;4616FILETIME KernelTime;4617FILETIME UserTime;46184619if (GetThreadTimes(GetCurrentThread(), &CreationTime, &ExitTime,4620&KernelTime, &UserTime) == 0) {4621return false;4622} else {4623return true;4624}4625}46264627// Windows does't provide a loadavg primitive so this is stubbed out for now.4628// It does have primitives (PDH API) to get CPU usage and run queue length.4629// "\\Processor(_Total)\\% Processor Time", "\\System\\Processor Queue Length"4630// If we wanted to implement loadavg on Windows, we have a few options:4631//4632// a) Query CPU usage and run queue length and "fake" an answer by4633// returning the CPU usage if it's under 100%, and the run queue4634// length otherwise. It turns out that querying is pretty slow4635// on Windows, on the order of 200 microseconds on a fast machine.4636// Note that on the Windows the CPU usage value is the % usage4637// since the last time the API was called (and the first call4638// returns 100%), so we'd have to deal with that as well.4639//4640// b) Sample the "fake" answer using a sampling thread and store4641// the answer in a global variable. The call to loadavg would4642// just return the value of the global, avoiding the slow query.4643//4644// c) Sample a better answer using exponential decay to smooth the4645// value. This is basically the algorithm used by UNIX kernels.4646//4647// Note that sampling thread starvation could affect both (b) and (c).4648int os::loadavg(double loadavg[], int nelem) {4649return -1;4650}465146524653// DontYieldALot=false by default: dutifully perform all yields as requested by JVM_Yield()4654bool os::dont_yield() {4655return DontYieldALot;4656}46574658int os::open(const char *path, int oflag, int mode) {4659errno_t err;4660wchar_t* wide_path = wide_abs_unc_path(path, err);46614662if (wide_path == NULL) {4663errno = err;4664return -1;4665}4666int fd = ::_wopen(wide_path, oflag | O_BINARY | O_NOINHERIT, mode);4667os::free(wide_path);46684669if (fd == -1) {4670errno = ::GetLastError();4671}46724673return fd;4674}46754676FILE* os::open(int fd, const char* mode) {4677return ::_fdopen(fd, mode);4678}46794680size_t os::write(int fd, const void *buf, unsigned int nBytes) {4681return ::write(fd, buf, nBytes);4682}46834684int os::close(int fd) {4685return ::close(fd);4686}46874688void os::exit(int num) {4689win32::exit_process_or_thread(win32::EPT_PROCESS, num);4690}46914692// Is a (classpath) directory empty?4693bool os::dir_is_empty(const char* path) {4694errno_t err;4695wchar_t* wide_path = wide_abs_unc_path(path, err, 2);46964697if (wide_path == NULL) {4698errno = err;4699return false;4700}47014702// Make sure we end with "\\*"4703if (wide_path[wcslen(wide_path) - 1] == L'\\') {4704wcscat(wide_path, L"*");4705} else {4706wcscat(wide_path, L"\\*");4707}47084709WIN32_FIND_DATAW fd;4710HANDLE f = ::FindFirstFileW(wide_path, &fd);4711os::free(wide_path);4712bool is_empty = true;47134714if (f != INVALID_HANDLE_VALUE) {4715while (is_empty && ::FindNextFileW(f, &fd)) {4716// An empty directory contains only the current directory file4717// and the previous directory file.4718if ((wcscmp(fd.cFileName, L".") != 0) &&4719(wcscmp(fd.cFileName, L"..") != 0)) {4720is_empty = false;4721}4722}4723FindClose(f);4724} else {4725errno = ::GetLastError();4726}47274728return is_empty;4729}47304731// create binary file, rewriting existing file if required4732int os::create_binary_file(const char* path, bool rewrite_existing) {4733int oflags = _O_CREAT | _O_WRONLY | _O_BINARY;4734if (!rewrite_existing) {4735oflags |= _O_EXCL;4736}4737return ::open(path, oflags, _S_IREAD | _S_IWRITE);4738}47394740// return current position of file pointer4741jlong os::current_file_offset(int fd) {4742return (jlong)::_lseeki64(fd, (__int64)0L, SEEK_CUR);4743}47444745// move file pointer to the specified offset4746jlong os::seek_to_file_offset(int fd, jlong offset) {4747return (jlong)::_lseeki64(fd, (__int64)offset, SEEK_SET);4748}474947504751jlong os::lseek(int fd, jlong offset, int whence) {4752return (jlong) ::_lseeki64(fd, offset, whence);4753}47544755ssize_t os::read_at(int fd, void *buf, unsigned int nBytes, jlong offset) {4756OVERLAPPED ov;4757DWORD nread;4758BOOL result;47594760ZeroMemory(&ov, sizeof(ov));4761ov.Offset = (DWORD)offset;4762ov.OffsetHigh = (DWORD)(offset >> 32);47634764HANDLE h = (HANDLE)::_get_osfhandle(fd);47654766result = ReadFile(h, (LPVOID)buf, nBytes, &nread, &ov);47674768return result ? nread : 0;4769}477047714772// This method is a slightly reworked copy of JDK's sysNativePath4773// from src/windows/hpi/src/path_md.c47744775// Convert a pathname to native format. On win32, this involves forcing all4776// separators to be '\\' rather than '/' (both are legal inputs, but Win954777// sometimes rejects '/') and removing redundant separators. The input path is4778// assumed to have been converted into the character encoding used by the local4779// system. Because this might be a double-byte encoding, care is taken to4780// treat double-byte lead characters correctly.4781//4782// This procedure modifies the given path in place, as the result is never4783// longer than the original. There is no error return; this operation always4784// succeeds.4785char * os::native_path(char *path) {4786char *src = path, *dst = path, *end = path;4787char *colon = NULL; // If a drive specifier is found, this will4788// point to the colon following the drive letter47894790// Assumption: '/', '\\', ':', and drive letters are never lead bytes4791assert(((!::IsDBCSLeadByte('/')) && (!::IsDBCSLeadByte('\\'))4792&& (!::IsDBCSLeadByte(':'))), "Illegal lead byte");47934794// Check for leading separators4795#define isfilesep(c) ((c) == '/' || (c) == '\\')4796while (isfilesep(*src)) {4797src++;4798}47994800if (::isalpha(*src) && !::IsDBCSLeadByte(*src) && src[1] == ':') {4801// Remove leading separators if followed by drive specifier. This4802// hack is necessary to support file URLs containing drive4803// specifiers (e.g., "file://c:/path"). As a side effect,4804// "/c:/path" can be used as an alternative to "c:/path".4805*dst++ = *src++;4806colon = dst;4807*dst++ = ':';4808src++;4809} else {4810src = path;4811if (isfilesep(src[0]) && isfilesep(src[1])) {4812// UNC pathname: Retain first separator; leave src pointed at4813// second separator so that further separators will be collapsed4814// into the second separator. The result will be a pathname4815// beginning with "\\\\" followed (most likely) by a host name.4816src = dst = path + 1;4817path[0] = '\\'; // Force first separator to '\\'4818}4819}48204821end = dst;48224823// Remove redundant separators from remainder of path, forcing all4824// separators to be '\\' rather than '/'. Also, single byte space4825// characters are removed from the end of the path because those4826// are not legal ending characters on this operating system.4827//4828while (*src != '\0') {4829if (isfilesep(*src)) {4830*dst++ = '\\'; src++;4831while (isfilesep(*src)) src++;4832if (*src == '\0') {4833// Check for trailing separator4834end = dst;4835if (colon == dst - 2) break; // "z:\\"4836if (dst == path + 1) break; // "\\"4837if (dst == path + 2 && isfilesep(path[0])) {4838// "\\\\" is not collapsed to "\\" because "\\\\" marks the4839// beginning of a UNC pathname. Even though it is not, by4840// itself, a valid UNC pathname, we leave it as is in order4841// to be consistent with the path canonicalizer as well4842// as the win32 APIs, which treat this case as an invalid4843// UNC pathname rather than as an alias for the root4844// directory of the current drive.4845break;4846}4847end = --dst; // Path does not denote a root directory, so4848// remove trailing separator4849break;4850}4851end = dst;4852} else {4853if (::IsDBCSLeadByte(*src)) { // Copy a double-byte character4854*dst++ = *src++;4855if (*src) *dst++ = *src++;4856end = dst;4857} else { // Copy a single-byte character4858char c = *src++;4859*dst++ = c;4860// Space is not a legal ending character4861if (c != ' ') end = dst;4862}4863}4864}48654866*end = '\0';48674868// For "z:", add "." to work around a bug in the C runtime library4869if (colon == dst - 1) {4870path[2] = '.';4871path[3] = '\0';4872}48734874return path;4875}48764877// This code is a copy of JDK's sysSetLength4878// from src/windows/hpi/src/sys_api_md.c48794880int os::ftruncate(int fd, jlong length) {4881HANDLE h = (HANDLE)::_get_osfhandle(fd);4882long high = (long)(length >> 32);4883DWORD ret;48844885if (h == (HANDLE)(-1)) {4886return -1;4887}48884889ret = ::SetFilePointer(h, (long)(length), &high, FILE_BEGIN);4890if ((ret == 0xFFFFFFFF) && (::GetLastError() != NO_ERROR)) {4891return -1;4892}48934894if (::SetEndOfFile(h) == FALSE) {4895return -1;4896}48974898return 0;4899}49004901int os::get_fileno(FILE* fp) {4902return _fileno(fp);4903}49044905// This code is a copy of JDK's sysSync4906// from src/windows/hpi/src/sys_api_md.c4907// except for the legacy workaround for a bug in Win 9849084909int os::fsync(int fd) {4910HANDLE handle = (HANDLE)::_get_osfhandle(fd);49114912if ((!::FlushFileBuffers(handle)) &&4913(GetLastError() != ERROR_ACCESS_DENIED)) {4914// from winerror.h4915return -1;4916}4917return 0;4918}49194920static int nonSeekAvailable(int, long *);4921static int stdinAvailable(int, long *);49224923// This code is a copy of JDK's sysAvailable4924// from src/windows/hpi/src/sys_api_md.c49254926int os::available(int fd, jlong *bytes) {4927jlong cur, end;4928struct _stati64 stbuf64;49294930if (::_fstati64(fd, &stbuf64) >= 0) {4931int mode = stbuf64.st_mode;4932if (S_ISCHR(mode) || S_ISFIFO(mode)) {4933int ret;4934long lpbytes;4935if (fd == 0) {4936ret = stdinAvailable(fd, &lpbytes);4937} else {4938ret = nonSeekAvailable(fd, &lpbytes);4939}4940(*bytes) = (jlong)(lpbytes);4941return ret;4942}4943if ((cur = ::_lseeki64(fd, 0L, SEEK_CUR)) == -1) {4944return FALSE;4945} else if ((end = ::_lseeki64(fd, 0L, SEEK_END)) == -1) {4946return FALSE;4947} else if (::_lseeki64(fd, cur, SEEK_SET) == -1) {4948return FALSE;4949}4950*bytes = end - cur;4951return TRUE;4952} else {4953return FALSE;4954}4955}49564957void os::flockfile(FILE* fp) {4958_lock_file(fp);4959}49604961void os::funlockfile(FILE* fp) {4962_unlock_file(fp);4963}49644965// This code is a copy of JDK's nonSeekAvailable4966// from src/windows/hpi/src/sys_api_md.c49674968static int nonSeekAvailable(int fd, long *pbytes) {4969// This is used for available on non-seekable devices4970// (like both named and anonymous pipes, such as pipes4971// connected to an exec'd process).4972// Standard Input is a special case.4973HANDLE han;49744975if ((han = (HANDLE) ::_get_osfhandle(fd)) == (HANDLE)(-1)) {4976return FALSE;4977}49784979if (! ::PeekNamedPipe(han, NULL, 0, NULL, (LPDWORD)pbytes, NULL)) {4980// PeekNamedPipe fails when at EOF. In that case we4981// simply make *pbytes = 0 which is consistent with the4982// behavior we get on Solaris when an fd is at EOF.4983// The only alternative is to raise an Exception,4984// which isn't really warranted.4985//4986if (::GetLastError() != ERROR_BROKEN_PIPE) {4987return FALSE;4988}4989*pbytes = 0;4990}4991return TRUE;4992}49934994#define MAX_INPUT_EVENTS 200049954996// This code is a copy of JDK's stdinAvailable4997// from src/windows/hpi/src/sys_api_md.c49984999static int stdinAvailable(int fd, long *pbytes) {5000HANDLE han;5001DWORD numEventsRead = 0; // Number of events read from buffer5002DWORD numEvents = 0; // Number of events in buffer5003DWORD i = 0; // Loop index5004DWORD curLength = 0; // Position marker5005DWORD actualLength = 0; // Number of bytes readable5006BOOL error = FALSE; // Error holder5007INPUT_RECORD *lpBuffer; // Pointer to records of input events50085009if ((han = ::GetStdHandle(STD_INPUT_HANDLE)) == INVALID_HANDLE_VALUE) {5010return FALSE;5011}50125013// Construct an array of input records in the console buffer5014error = ::GetNumberOfConsoleInputEvents(han, &numEvents);5015if (error == 0) {5016return nonSeekAvailable(fd, pbytes);5017}50185019// lpBuffer must fit into 64K or else PeekConsoleInput fails5020if (numEvents > MAX_INPUT_EVENTS) {5021numEvents = MAX_INPUT_EVENTS;5022}50235024lpBuffer = (INPUT_RECORD *)os::malloc(numEvents * sizeof(INPUT_RECORD), mtInternal);5025if (lpBuffer == NULL) {5026return FALSE;5027}50285029error = ::PeekConsoleInput(han, lpBuffer, numEvents, &numEventsRead);5030if (error == 0) {5031os::free(lpBuffer);5032return FALSE;5033}50345035// Examine input records for the number of bytes available5036for (i=0; i<numEvents; i++) {5037if (lpBuffer[i].EventType == KEY_EVENT) {50385039KEY_EVENT_RECORD *keyRecord = (KEY_EVENT_RECORD *)5040&(lpBuffer[i].Event);5041if (keyRecord->bKeyDown == TRUE) {5042CHAR *keyPressed = (CHAR *) &(keyRecord->uChar);5043curLength++;5044if (*keyPressed == '\r') {5045actualLength = curLength;5046}5047}5048}5049}50505051if (lpBuffer != NULL) {5052os::free(lpBuffer);5053}50545055*pbytes = (long) actualLength;5056return TRUE;5057}50585059// Map a block of memory.5060char* os::pd_map_memory(int fd, const char* file_name, size_t file_offset,5061char *addr, size_t bytes, bool read_only,5062bool allow_exec) {50635064errno_t err;5065wchar_t* wide_path = wide_abs_unc_path(file_name, err);50665067if (wide_path == NULL) {5068return NULL;5069}50705071HANDLE hFile;5072char* base;50735074hFile = CreateFileW(wide_path, GENERIC_READ, FILE_SHARE_READ, NULL,5075OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);5076if (hFile == INVALID_HANDLE_VALUE) {5077log_info(os)("CreateFileW() failed: GetLastError->%ld.", GetLastError());5078os::free(wide_path);5079return NULL;5080}5081os::free(wide_path);50825083if (allow_exec) {5084// CreateFileMapping/MapViewOfFileEx can't map executable memory5085// unless it comes from a PE image (which the shared archive is not.)5086// Even VirtualProtect refuses to give execute access to mapped memory5087// that was not previously executable.5088//5089// Instead, stick the executable region in anonymous memory. Yuck.5090// Penalty is that ~4 pages will not be shareable - in the future5091// we might consider DLLizing the shared archive with a proper PE5092// header so that mapping executable + sharing is possible.50935094base = (char*) virtualAlloc(addr, bytes, MEM_COMMIT | MEM_RESERVE,5095PAGE_READWRITE);5096if (base == NULL) {5097CloseHandle(hFile);5098return NULL;5099}51005101// Record virtual memory allocation5102MemTracker::record_virtual_memory_reserve_and_commit((address)addr, bytes, CALLER_PC);51035104DWORD bytes_read;5105OVERLAPPED overlapped;5106overlapped.Offset = (DWORD)file_offset;5107overlapped.OffsetHigh = 0;5108overlapped.hEvent = NULL;5109// ReadFile guarantees that if the return value is true, the requested5110// number of bytes were read before returning.5111bool res = ReadFile(hFile, base, (DWORD)bytes, &bytes_read, &overlapped) != 0;5112if (!res) {5113log_info(os)("ReadFile() failed: GetLastError->%ld.", GetLastError());5114release_memory(base, bytes);5115CloseHandle(hFile);5116return NULL;5117}5118} else {5119HANDLE hMap = CreateFileMapping(hFile, NULL, PAGE_WRITECOPY, 0, 0,5120NULL /* file_name */);5121if (hMap == NULL) {5122log_info(os)("CreateFileMapping() failed: GetLastError->%ld.", GetLastError());5123CloseHandle(hFile);5124return NULL;5125}51265127DWORD access = read_only ? FILE_MAP_READ : FILE_MAP_COPY;5128base = (char*)mapViewOfFileEx(hMap, access, 0, (DWORD)file_offset,5129(DWORD)bytes, addr);5130if (base == NULL) {5131CloseHandle(hMap);5132CloseHandle(hFile);5133return NULL;5134}51355136if (CloseHandle(hMap) == 0) {5137log_info(os)("CloseHandle(hMap) failed: GetLastError->%ld.", GetLastError());5138CloseHandle(hFile);5139return base;5140}5141}51425143if (allow_exec) {5144DWORD old_protect;5145DWORD exec_access = read_only ? PAGE_EXECUTE_READ : PAGE_EXECUTE_READWRITE;5146bool res = VirtualProtect(base, bytes, exec_access, &old_protect) != 0;51475148if (!res) {5149log_info(os)("VirtualProtect() failed: GetLastError->%ld.", GetLastError());5150// Don't consider this a hard error, on IA32 even if the5151// VirtualProtect fails, we should still be able to execute5152CloseHandle(hFile);5153return base;5154}5155}51565157if (CloseHandle(hFile) == 0) {5158log_info(os)("CloseHandle(hFile) failed: GetLastError->%ld.", GetLastError());5159return base;5160}51615162return base;5163}516451655166// Remap a block of memory.5167char* os::pd_remap_memory(int fd, const char* file_name, size_t file_offset,5168char *addr, size_t bytes, bool read_only,5169bool allow_exec) {5170// This OS does not allow existing memory maps to be remapped so we5171// would have to unmap the memory before we remap it.51725173// Because there is a small window between unmapping memory and mapping5174// it in again with different protections, CDS archives are mapped RW5175// on windows, so this function isn't called.5176ShouldNotReachHere();5177return NULL;5178}517951805181// Unmap a block of memory.5182// Returns true=success, otherwise false.51835184bool os::pd_unmap_memory(char* addr, size_t bytes) {5185MEMORY_BASIC_INFORMATION mem_info;5186if (VirtualQuery(addr, &mem_info, sizeof(mem_info)) == 0) {5187log_info(os)("VirtualQuery() failed: GetLastError->%ld.", GetLastError());5188return false;5189}51905191// Executable memory was not mapped using CreateFileMapping/MapViewOfFileEx.5192// Instead, executable region was allocated using VirtualAlloc(). See5193// pd_map_memory() above.5194//5195// The following flags should match the 'exec_access' flages used for5196// VirtualProtect() in pd_map_memory().5197if (mem_info.Protect == PAGE_EXECUTE_READ ||5198mem_info.Protect == PAGE_EXECUTE_READWRITE) {5199return pd_release_memory(addr, bytes);5200}52015202BOOL result = unmapViewOfFile(addr);5203if (result == 0) {5204return false;5205}5206return true;5207}52085209void os::pause() {5210char filename[MAX_PATH];5211if (PauseAtStartupFile && PauseAtStartupFile[0]) {5212jio_snprintf(filename, MAX_PATH, "%s", PauseAtStartupFile);5213} else {5214jio_snprintf(filename, MAX_PATH, "./vm.paused.%d", current_process_id());5215}52165217int fd = ::open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666);5218if (fd != -1) {5219struct stat buf;5220::close(fd);5221while (::stat(filename, &buf) == 0) {5222Sleep(100);5223}5224} else {5225jio_fprintf(stderr,5226"Could not open pause file '%s', continuing immediately.\n", filename);5227}5228}52295230Thread* os::ThreadCrashProtection::_protected_thread = NULL;5231os::ThreadCrashProtection* os::ThreadCrashProtection::_crash_protection = NULL;52325233os::ThreadCrashProtection::ThreadCrashProtection() {5234_protected_thread = Thread::current();5235assert(_protected_thread->is_JfrSampler_thread(), "should be JFRSampler");5236}52375238// See the caveats for this class in os_windows.hpp5239// Protects the callback call so that raised OS EXCEPTIONS causes a jump back5240// into this method and returns false. If no OS EXCEPTION was raised, returns5241// true.5242// The callback is supposed to provide the method that should be protected.5243//5244bool os::ThreadCrashProtection::call(os::CrashProtectionCallback& cb) {5245bool success = true;5246__try {5247_crash_protection = this;5248cb.call();5249} __except(EXCEPTION_EXECUTE_HANDLER) {5250// only for protection, nothing to do5251success = false;5252}5253_crash_protection = NULL;5254_protected_thread = NULL;5255return success;5256}525752585259class HighResolutionInterval : public CHeapObj<mtThread> {5260// The default timer resolution seems to be 10 milliseconds.5261// (Where is this written down?)5262// If someone wants to sleep for only a fraction of the default,5263// then we set the timer resolution down to 1 millisecond for5264// the duration of their interval.5265// We carefully set the resolution back, since otherwise we5266// seem to incur an overhead (3%?) that we don't need.5267// CONSIDER: if ms is small, say 3, then we should run with a high resolution time.5268// Buf if ms is large, say 500, or 503, we should avoid the call to timeBeginPeriod().5269// Alternatively, we could compute the relative error (503/500 = .6%) and only use5270// timeBeginPeriod() if the relative error exceeded some threshold.5271// timeBeginPeriod() has been linked to problems with clock drift on win32 systems and5272// to decreased efficiency related to increased timer "tick" rates. We want to minimize5273// (a) calls to timeBeginPeriod() and timeEndPeriod() and (b) time spent with high5274// resolution timers running.5275private:5276jlong resolution;5277public:5278HighResolutionInterval(jlong ms) {5279resolution = ms % 10L;5280if (resolution != 0) {5281MMRESULT result = timeBeginPeriod(1L);5282}5283}5284~HighResolutionInterval() {5285if (resolution != 0) {5286MMRESULT result = timeEndPeriod(1L);5287}5288resolution = 0L;5289}5290};52915292// An Event wraps a win32 "CreateEvent" kernel handle.5293//5294// We have a number of choices regarding "CreateEvent" win32 handle leakage:5295//5296// 1: When a thread dies return the Event to the EventFreeList, clear the ParkHandle5297// field, and call CloseHandle() on the win32 event handle. Unpark() would5298// need to be modified to tolerate finding a NULL (invalid) win32 event handle.5299// In addition, an unpark() operation might fetch the handle field, but the5300// event could recycle between the fetch and the SetEvent() operation.5301// SetEvent() would either fail because the handle was invalid, or inadvertently work,5302// as the win32 handle value had been recycled. In an ideal world calling SetEvent()5303// on an stale but recycled handle would be harmless, but in practice this might5304// confuse other non-Sun code, so it's not a viable approach.5305//5306// 2: Once a win32 event handle is associated with an Event, it remains associated5307// with the Event. The event handle is never closed. This could be construed5308// as handle leakage, but only up to the maximum # of threads that have been extant5309// at any one time. This shouldn't be an issue, as windows platforms typically5310// permit a process to have hundreds of thousands of open handles.5311//5312// 3: Same as (1), but periodically, at stop-the-world time, rundown the EventFreeList5313// and release unused handles.5314//5315// 4: Add a CRITICAL_SECTION to the Event to protect LD+SetEvent from LD;ST(null);CloseHandle.5316// It's not clear, however, that we wouldn't be trading one type of leak for another.5317//5318// 5. Use an RCU-like mechanism (Read-Copy Update).5319// Or perhaps something similar to Maged Michael's "Hazard pointers".5320//5321// We use (2).5322//5323// TODO-FIXME:5324// 1. Reconcile Doug's JSR166 j.u.c park-unpark with the objectmonitor implementation.5325// 2. Consider wrapping the WaitForSingleObject(Ex) calls in SEH try/finally blocks5326// to recover from (or at least detect) the dreaded Windows 841176 bug.5327// 3. Collapse the JSR166 parker event, and the objectmonitor ParkEvent5328// into a single win32 CreateEvent() handle.5329//5330// Assumption:5331// Only one parker can exist on an event, which is why we allocate5332// them per-thread. Multiple unparkers can coexist.5333//5334// _Event transitions in park()5335// -1 => -1 : illegal5336// 1 => 0 : pass - return immediately5337// 0 => -1 : block; then set _Event to 0 before returning5338//5339// _Event transitions in unpark()5340// 0 => 1 : just return5341// 1 => 1 : just return5342// -1 => either 0 or 1; must signal target thread5343// That is, we can safely transition _Event from -1 to either5344// 0 or 1.5345//5346// _Event serves as a restricted-range semaphore.5347// -1 : thread is blocked, i.e. there is a waiter5348// 0 : neutral: thread is running or ready,5349// could have been signaled after a wait started5350// 1 : signaled - thread is running or ready5351//5352// Another possible encoding of _Event would be with5353// explicit "PARKED" == 01b and "SIGNALED" == 10b bits.5354//53555356int os::PlatformEvent::park(jlong Millis) {5357// Transitions for _Event:5358// -1 => -1 : illegal5359// 1 => 0 : pass - return immediately5360// 0 => -1 : block; then set _Event to 0 before returning53615362guarantee(_ParkHandle != NULL , "Invariant");5363guarantee(Millis > 0 , "Invariant");53645365// CONSIDER: defer assigning a CreateEvent() handle to the Event until5366// the initial park() operation.5367// Consider: use atomic decrement instead of CAS-loop53685369int v;5370for (;;) {5371v = _Event;5372if (Atomic::cmpxchg(&_Event, v, v-1) == v) break;5373}5374guarantee((v == 0) || (v == 1), "invariant");5375if (v != 0) return OS_OK;53765377// Do this the hard way by blocking ...5378// TODO: consider a brief spin here, gated on the success of recent5379// spin attempts by this thread.5380//5381// We decompose long timeouts into series of shorter timed waits.5382// Evidently large timo values passed in WaitForSingleObject() are problematic on some5383// versions of Windows. See EventWait() for details. This may be superstition. Or not.5384// We trust the WAIT_TIMEOUT indication and don't track the elapsed wait time5385// with os::javaTimeNanos(). Furthermore, we assume that spurious returns from5386// ::WaitForSingleObject() caused by latent ::setEvent() operations will tend5387// to happen early in the wait interval. Specifically, after a spurious wakeup (rv ==5388// WAIT_OBJECT_0 but _Event is still < 0) we don't bother to recompute Millis to compensate5389// for the already waited time. This policy does not admit any new outcomes.5390// In the future, however, we might want to track the accumulated wait time and5391// adjust Millis accordingly if we encounter a spurious wakeup.53925393const int MAXTIMEOUT = 0x10000000;5394DWORD rv = WAIT_TIMEOUT;5395while (_Event < 0 && Millis > 0) {5396DWORD prd = Millis; // set prd = MAX (Millis, MAXTIMEOUT)5397if (Millis > MAXTIMEOUT) {5398prd = MAXTIMEOUT;5399}5400HighResolutionInterval *phri = NULL;5401if (!ForceTimeHighResolution) {5402phri = new HighResolutionInterval(prd);5403}5404rv = ::WaitForSingleObject(_ParkHandle, prd);5405assert(rv == WAIT_OBJECT_0 || rv == WAIT_TIMEOUT, "WaitForSingleObject failed");5406if (rv == WAIT_TIMEOUT) {5407Millis -= prd;5408}5409delete phri; // if it is NULL, harmless5410}5411v = _Event;5412_Event = 0;5413// see comment at end of os::PlatformEvent::park() below:5414OrderAccess::fence();5415// If we encounter a nearly simultanous timeout expiry and unpark()5416// we return OS_OK indicating we awoke via unpark().5417// Implementor's license -- returning OS_TIMEOUT would be equally valid, however.5418return (v >= 0) ? OS_OK : OS_TIMEOUT;5419}54205421void os::PlatformEvent::park() {5422// Transitions for _Event:5423// -1 => -1 : illegal5424// 1 => 0 : pass - return immediately5425// 0 => -1 : block; then set _Event to 0 before returning54265427guarantee(_ParkHandle != NULL, "Invariant");5428// Invariant: Only the thread associated with the Event/PlatformEvent5429// may call park().5430// Consider: use atomic decrement instead of CAS-loop5431int v;5432for (;;) {5433v = _Event;5434if (Atomic::cmpxchg(&_Event, v, v-1) == v) break;5435}5436guarantee((v == 0) || (v == 1), "invariant");5437if (v != 0) return;54385439// Do this the hard way by blocking ...5440// TODO: consider a brief spin here, gated on the success of recent5441// spin attempts by this thread.5442while (_Event < 0) {5443DWORD rv = ::WaitForSingleObject(_ParkHandle, INFINITE);5444assert(rv == WAIT_OBJECT_0, "WaitForSingleObject failed");5445}54465447// Usually we'll find _Event == 0 at this point, but as5448// an optional optimization we clear it, just in case can5449// multiple unpark() operations drove _Event up to 1.5450_Event = 0;5451OrderAccess::fence();5452guarantee(_Event >= 0, "invariant");5453}54545455void os::PlatformEvent::unpark() {5456guarantee(_ParkHandle != NULL, "Invariant");54575458// Transitions for _Event:5459// 0 => 1 : just return5460// 1 => 1 : just return5461// -1 => either 0 or 1; must signal target thread5462// That is, we can safely transition _Event from -1 to either5463// 0 or 1.5464// See also: "Semaphores in Plan 9" by Mullender & Cox5465//5466// Note: Forcing a transition from "-1" to "1" on an unpark() means5467// that it will take two back-to-back park() calls for the owning5468// thread to block. This has the benefit of forcing a spurious return5469// from the first park() call after an unpark() call which will help5470// shake out uses of park() and unpark() without condition variables.54715472if (Atomic::xchg(&_Event, 1) >= 0) return;54735474::SetEvent(_ParkHandle);5475}547654775478// JSR1665479// -------------------------------------------------------54805481// The Windows implementation of Park is very straightforward: Basic5482// operations on Win32 Events turn out to have the right semantics to5483// use them directly.54845485void Parker::park(bool isAbsolute, jlong time) {5486guarantee(_ParkHandle != NULL, "invariant");5487// First, demultiplex/decode time arguments5488if (time < 0) { // don't wait5489return;5490} else if (time == 0 && !isAbsolute) {5491time = INFINITE;5492} else if (isAbsolute) {5493time -= os::javaTimeMillis(); // convert to relative time5494if (time <= 0) { // already elapsed5495return;5496}5497} else { // relative5498time /= 1000000; // Must coarsen from nanos to millis5499if (time == 0) { // Wait for the minimal time unit if zero5500time = 1;5501}5502}55035504JavaThread* thread = JavaThread::current();55055506// Don't wait if interrupted or already triggered5507if (thread->is_interrupted(false) ||5508WaitForSingleObject(_ParkHandle, 0) == WAIT_OBJECT_0) {5509ResetEvent(_ParkHandle);5510return;5511} else {5512ThreadBlockInVM tbivm(thread);5513OSThreadWaitState osts(thread->osthread(), false /* not Object.wait() */);55145515WaitForSingleObject(_ParkHandle, time);5516ResetEvent(_ParkHandle);5517}5518}55195520void Parker::unpark() {5521guarantee(_ParkHandle != NULL, "invariant");5522SetEvent(_ParkHandle);5523}55245525// Platform Monitor implementation55265527// Must already be locked5528int os::PlatformMonitor::wait(jlong millis) {5529assert(millis >= 0, "negative timeout");5530int ret = OS_TIMEOUT;5531int status = SleepConditionVariableCS(&_cond, &_mutex,5532millis == 0 ? INFINITE : millis);5533if (status != 0) {5534ret = OS_OK;5535}5536#ifndef PRODUCT5537else {5538DWORD err = GetLastError();5539assert(err == ERROR_TIMEOUT, "SleepConditionVariableCS: %ld:", err);5540}5541#endif5542return ret;5543}55445545// Run the specified command in a separate process. Return its exit value,5546// or -1 on failure (e.g. can't create a new process).5547int os::fork_and_exec(const char* cmd, bool dummy /* ignored */) {5548STARTUPINFO si;5549PROCESS_INFORMATION pi;5550DWORD exit_code;55515552char * cmd_string;5553const char * cmd_prefix = "cmd /C ";5554size_t len = strlen(cmd) + strlen(cmd_prefix) + 1;5555cmd_string = NEW_C_HEAP_ARRAY_RETURN_NULL(char, len, mtInternal);5556if (cmd_string == NULL) {5557return -1;5558}5559cmd_string[0] = '\0';5560strcat(cmd_string, cmd_prefix);5561strcat(cmd_string, cmd);55625563// now replace all '\n' with '&'5564char * substring = cmd_string;5565while ((substring = strchr(substring, '\n')) != NULL) {5566substring[0] = '&';5567substring++;5568}5569memset(&si, 0, sizeof(si));5570si.cb = sizeof(si);5571memset(&pi, 0, sizeof(pi));5572BOOL rslt = CreateProcess(NULL, // executable name - use command line5573cmd_string, // command line5574NULL, // process security attribute5575NULL, // thread security attribute5576TRUE, // inherits system handles55770, // no creation flags5578NULL, // use parent's environment block5579NULL, // use parent's starting directory5580&si, // (in) startup information5581&pi); // (out) process information55825583if (rslt) {5584// Wait until child process exits.5585WaitForSingleObject(pi.hProcess, INFINITE);55865587GetExitCodeProcess(pi.hProcess, &exit_code);55885589// Close process and thread handles.5590CloseHandle(pi.hProcess);5591CloseHandle(pi.hThread);5592} else {5593exit_code = -1;5594}55955596FREE_C_HEAP_ARRAY(char, cmd_string);5597return (int)exit_code;5598}55995600bool os::find(address addr, outputStream* st) {5601int offset = -1;5602bool result = false;5603char buf[256];5604if (os::dll_address_to_library_name(addr, buf, sizeof(buf), &offset)) {5605st->print(PTR_FORMAT " ", addr);5606if (strlen(buf) < sizeof(buf) - 1) {5607char* p = strrchr(buf, '\\');5608if (p) {5609st->print("%s", p + 1);5610} else {5611st->print("%s", buf);5612}5613} else {5614// The library name is probably truncated. Let's omit the library name.5615// See also JDK-8147512.5616}5617if (os::dll_address_to_function_name(addr, buf, sizeof(buf), &offset)) {5618st->print("::%s + 0x%x", buf, offset);5619}5620st->cr();5621result = true;5622}5623return result;5624}56255626static jint initSock() {5627WSADATA wsadata;56285629if (WSAStartup(MAKEWORD(2,2), &wsadata) != 0) {5630jio_fprintf(stderr, "Could not initialize Winsock (error: %d)\n",5631::GetLastError());5632return JNI_ERR;5633}5634return JNI_OK;5635}56365637struct hostent* os::get_host_by_name(char* name) {5638return (struct hostent*)gethostbyname(name);5639}56405641int os::socket_close(int fd) {5642return ::closesocket(fd);5643}56445645int os::socket(int domain, int type, int protocol) {5646return ::socket(domain, type, protocol);5647}56485649int os::connect(int fd, struct sockaddr* him, socklen_t len) {5650return ::connect(fd, him, len);5651}56525653int os::recv(int fd, char* buf, size_t nBytes, uint flags) {5654return ::recv(fd, buf, (int)nBytes, flags);5655}56565657int os::send(int fd, char* buf, size_t nBytes, uint flags) {5658return ::send(fd, buf, (int)nBytes, flags);5659}56605661int os::raw_send(int fd, char* buf, size_t nBytes, uint flags) {5662return ::send(fd, buf, (int)nBytes, flags);5663}56645665// WINDOWS CONTEXT Flags for THREAD_SAMPLING5666#if defined(IA32)5667#define sampling_context_flags (CONTEXT_FULL | CONTEXT_FLOATING_POINT | CONTEXT_EXTENDED_REGISTERS)5668#elif defined(AMD64) || defined(_M_ARM64)5669#define sampling_context_flags (CONTEXT_FULL | CONTEXT_FLOATING_POINT)5670#endif56715672// returns true if thread could be suspended,5673// false otherwise5674static bool do_suspend(HANDLE* h) {5675if (h != NULL) {5676if (SuspendThread(*h) != ~0) {5677return true;5678}5679}5680return false;5681}56825683// resume the thread5684// calling resume on an active thread is a no-op5685static void do_resume(HANDLE* h) {5686if (h != NULL) {5687ResumeThread(*h);5688}5689}56905691// retrieve a suspend/resume context capable handle5692// from the tid. Caller validates handle return value.5693void get_thread_handle_for_extended_context(HANDLE* h,5694OSThread::thread_id_t tid) {5695if (h != NULL) {5696*h = OpenThread(THREAD_SUSPEND_RESUME | THREAD_GET_CONTEXT | THREAD_QUERY_INFORMATION, FALSE, tid);5697}5698}56995700// Thread sampling implementation5701//5702void os::SuspendedThreadTask::internal_do_task() {5703CONTEXT ctxt;5704HANDLE h = NULL;57055706// get context capable handle for thread5707get_thread_handle_for_extended_context(&h, _thread->osthread()->thread_id());57085709// sanity5710if (h == NULL || h == INVALID_HANDLE_VALUE) {5711return;5712}57135714// suspend the thread5715if (do_suspend(&h)) {5716ctxt.ContextFlags = sampling_context_flags;5717// get thread context5718GetThreadContext(h, &ctxt);5719SuspendedThreadTaskContext context(_thread, &ctxt);5720// pass context to Thread Sampling impl5721do_task(context);5722// resume thread5723do_resume(&h);5724}57255726// close handle5727CloseHandle(h);5728}57295730bool os::start_debugging(char *buf, int buflen) {5731int len = (int)strlen(buf);5732char *p = &buf[len];57335734jio_snprintf(p, buflen-len,5735"\n\n"5736"Do you want to debug the problem?\n\n"5737"To debug, attach Visual Studio to process %d; then switch to thread 0x%x\n"5738"Select 'Yes' to launch Visual Studio automatically (PATH must include msdev)\n"5739"Otherwise, select 'No' to abort...",5740os::current_process_id(), os::current_thread_id());57415742bool yes = os::message_box("Unexpected Error", buf);57435744if (yes) {5745// os::breakpoint() calls DebugBreak(), which causes a breakpoint5746// exception. If VM is running inside a debugger, the debugger will5747// catch the exception. Otherwise, the breakpoint exception will reach5748// the default windows exception handler, which can spawn a debugger and5749// automatically attach to the dying VM.5750os::breakpoint();5751yes = false;5752}5753return yes;5754}57555756void* os::get_default_process_handle() {5757return (void*)GetModuleHandle(NULL);5758}57595760// Builds a platform dependent Agent_OnLoad_<lib_name> function name5761// which is used to find statically linked in agents.5762// Additionally for windows, takes into account __stdcall names.5763// Parameters:5764// sym_name: Symbol in library we are looking for5765// lib_name: Name of library to look in, NULL for shared libs.5766// is_absolute_path == true if lib_name is absolute path to agent5767// such as "C:/a/b/L.dll"5768// == false if only the base name of the library is passed in5769// such as "L"5770char* os::build_agent_function_name(const char *sym_name, const char *lib_name,5771bool is_absolute_path) {5772char *agent_entry_name;5773size_t len;5774size_t name_len;5775size_t prefix_len = strlen(JNI_LIB_PREFIX);5776size_t suffix_len = strlen(JNI_LIB_SUFFIX);5777const char *start;57785779if (lib_name != NULL) {5780len = name_len = strlen(lib_name);5781if (is_absolute_path) {5782// Need to strip path, prefix and suffix5783if ((start = strrchr(lib_name, *os::file_separator())) != NULL) {5784lib_name = ++start;5785} else {5786// Need to check for drive prefix5787if ((start = strchr(lib_name, ':')) != NULL) {5788lib_name = ++start;5789}5790}5791if (len <= (prefix_len + suffix_len)) {5792return NULL;5793}5794lib_name += prefix_len;5795name_len = strlen(lib_name) - suffix_len;5796}5797}5798len = (lib_name != NULL ? name_len : 0) + strlen(sym_name) + 2;5799agent_entry_name = NEW_C_HEAP_ARRAY_RETURN_NULL(char, len, mtThread);5800if (agent_entry_name == NULL) {5801return NULL;5802}5803if (lib_name != NULL) {5804const char *p = strrchr(sym_name, '@');5805if (p != NULL && p != sym_name) {5806// sym_name == _Agent_OnLoad@XX5807strncpy(agent_entry_name, sym_name, (p - sym_name));5808agent_entry_name[(p-sym_name)] = '\0';5809// agent_entry_name == _Agent_OnLoad5810strcat(agent_entry_name, "_");5811strncat(agent_entry_name, lib_name, name_len);5812strcat(agent_entry_name, p);5813// agent_entry_name == _Agent_OnLoad_lib_name@XX5814} else {5815strcpy(agent_entry_name, sym_name);5816strcat(agent_entry_name, "_");5817strncat(agent_entry_name, lib_name, name_len);5818}5819} else {5820strcpy(agent_entry_name, sym_name);5821}5822return agent_entry_name;5823}58245825/*5826All the defined signal names for Windows.58275828NOTE that not all of these names are accepted by FindSignal!58295830For various reasons some of these may be rejected at runtime.58315832Here are the names currently accepted by a user of sun.misc.Signal with58331.4.1 (ignoring potential interaction with use of chaining, etc):58345835(LIST TBD)58365837*/5838int os::get_signal_number(const char* name) {5839static const struct {5840const char* name;5841int number;5842} siglabels [] =5843// derived from version 6.0 VC98/include/signal.h5844{"ABRT", SIGABRT, // abnormal termination triggered by abort cl5845"FPE", SIGFPE, // floating point exception5846"SEGV", SIGSEGV, // segment violation5847"INT", SIGINT, // interrupt5848"TERM", SIGTERM, // software term signal from kill5849"BREAK", SIGBREAK, // Ctrl-Break sequence5850"ILL", SIGILL}; // illegal instruction5851for (unsigned i = 0; i < ARRAY_SIZE(siglabels); ++i) {5852if (strcmp(name, siglabels[i].name) == 0) {5853return siglabels[i].number;5854}5855}5856return -1;5857}58585859// Fast current thread access58605861int os::win32::_thread_ptr_offset = 0;58625863static void call_wrapper_dummy() {}58645865// We need to call the os_exception_wrapper once so that it sets5866// up the offset from FS of the thread pointer.5867void os::win32::initialize_thread_ptr_offset() {5868os::os_exception_wrapper((java_call_t)call_wrapper_dummy,5869NULL, methodHandle(), NULL, NULL);5870}58715872bool os::supports_map_sync() {5873return false;5874}58755876#ifdef ASSERT5877static void check_meminfo(MEMORY_BASIC_INFORMATION* minfo) {5878assert(minfo->State == MEM_FREE || minfo->State == MEM_COMMIT || minfo->State == MEM_RESERVE, "Invalid state");5879if (minfo->State != MEM_FREE) {5880assert(minfo->AllocationBase != NULL && minfo->BaseAddress >= minfo->AllocationBase, "Invalid pointers");5881assert(minfo->RegionSize > 0, "Invalid region size");5882}5883}5884#endif588558865887static bool checkedVirtualQuery(address addr, MEMORY_BASIC_INFORMATION* minfo) {5888ZeroMemory(minfo, sizeof(MEMORY_BASIC_INFORMATION));5889if (::VirtualQuery(addr, minfo, sizeof(MEMORY_BASIC_INFORMATION)) == sizeof(MEMORY_BASIC_INFORMATION)) {5890DEBUG_ONLY(check_meminfo(minfo);)5891return true;5892}5893return false;5894}58955896// Given a pointer pointing into an allocation (an area allocated with VirtualAlloc),5897// return information about that allocation.5898bool os::win32::find_mapping(address addr, mapping_info_t* mi) {5899// Query at addr to find allocation base; then, starting at allocation base,5900// query all regions, until we either find the next allocation or a free area.5901ZeroMemory(mi, sizeof(mapping_info_t));5902MEMORY_BASIC_INFORMATION minfo;5903address allocation_base = NULL;5904address allocation_end = NULL;5905bool rc = false;5906if (checkedVirtualQuery(addr, &minfo)) {5907if (minfo.State != MEM_FREE) {5908allocation_base = (address)minfo.AllocationBase;5909allocation_end = allocation_base;5910// Iterate through all regions in this allocation to find its end. While we are here, also count things.5911for (;;) {5912bool rc = checkedVirtualQuery(allocation_end, &minfo);5913if (rc == false || // VirtualQuery error, end of allocation?5914minfo.State == MEM_FREE || // end of allocation, free memory follows5915(address)minfo.AllocationBase != allocation_base) // end of allocation, a new one starts5916{5917break;5918}5919const size_t region_size = minfo.RegionSize;5920mi->regions ++;5921if (minfo.State == MEM_COMMIT) {5922mi->committed_size += minfo.RegionSize;5923}5924allocation_end += region_size;5925}5926if (allocation_base != NULL && allocation_end > allocation_base) {5927mi->base = allocation_base;5928mi->size = allocation_end - allocation_base;5929rc = true;5930}5931}5932}5933#ifdef ASSERT5934if (rc) {5935assert(mi->size > 0 && mi->size >= mi->committed_size, "Sanity");5936assert(addr >= mi->base && addr < mi->base + mi->size, "Sanity");5937assert(mi->regions > 0, "Sanity");5938}5939#endif5940return rc;5941}59425943// Helper for print_one_mapping: print n words, both as hex and ascii.5944// Use Safefetch for all values.5945static void print_snippet(const void* p, outputStream* st) {5946static const int num_words = LP64_ONLY(3) NOT_LP64(6);5947static const int num_bytes = num_words * sizeof(int);5948intptr_t v[num_words];5949const int errval = 0xDE210244;5950for (int i = 0; i < num_words; i++) {5951v[i] = SafeFetchN((intptr_t*)p + i, errval);5952if (v[i] == errval &&5953SafeFetchN((intptr_t*)p + i, ~errval) == ~errval) {5954return;5955}5956}5957st->put('[');5958for (int i = 0; i < num_words; i++) {5959st->print(INTPTR_FORMAT " ", v[i]);5960}5961const char* b = (char*)v;5962st->put('\"');5963for (int i = 0; i < num_bytes; i++) {5964st->put(::isgraph(b[i]) ? b[i] : '.');5965}5966st->put('\"');5967st->put(']');5968}59695970// Helper function for print_memory_mappings:5971// Given a MEMORY_BASIC_INFORMATION, containing information about a non-free region:5972// print out all regions in that allocation. If any of those regions5973// fall outside the given range [start, end), indicate that in the output.5974// Return the pointer to the end of the allocation.5975static address print_one_mapping(MEMORY_BASIC_INFORMATION* minfo, address start, address end, outputStream* st) {5976// Print it like this:5977//5978// Base: <xxxxx>: [xxxx - xxxx], state=MEM_xxx, prot=x, type=MEM_xxx (region 1)5979// [xxxx - xxxx], state=MEM_xxx, prot=x, type=MEM_xxx (region 2)5980assert(minfo->State != MEM_FREE, "Not inside an allocation.");5981address allocation_base = (address)minfo->AllocationBase;5982#define IS_IN(p) (p >= start && p < end)5983bool first_line = true;5984bool is_dll = false;5985for(;;) {5986if (first_line) {5987st->print("Base " PTR_FORMAT ": ", p2i(allocation_base));5988} else {5989st->print_raw(NOT_LP64 (" ")5990LP64_ONLY(" "));5991}5992address region_start = (address)minfo->BaseAddress;5993address region_end = region_start + minfo->RegionSize;5994assert(region_end > region_start, "Sanity");5995if (region_end <= start) {5996st->print("<outside range> ");5997} else if (region_start >= end) {5998st->print("<outside range> ");5999} else if (!IS_IN(region_start) || !IS_IN(region_end - 1)) {6000st->print("<partly outside range> ");6001}6002st->print("[" PTR_FORMAT "-" PTR_FORMAT "), state=", p2i(region_start), p2i(region_end));6003switch (minfo->State) {6004case MEM_COMMIT: st->print_raw("MEM_COMMIT "); break;6005case MEM_FREE: st->print_raw("MEM_FREE "); break;6006case MEM_RESERVE: st->print_raw("MEM_RESERVE"); break;6007default: st->print("%x?", (unsigned)minfo->State);6008}6009st->print(", prot=%3x, type=", (unsigned)minfo->Protect);6010switch (minfo->Type) {6011case MEM_IMAGE: st->print_raw("MEM_IMAGE "); break;6012case MEM_MAPPED: st->print_raw("MEM_MAPPED "); break;6013case MEM_PRIVATE: st->print_raw("MEM_PRIVATE"); break;6014default: st->print("%x?", (unsigned)minfo->State);6015}6016// At the start of every allocation, print some more information about this mapping.6017// Notes:6018// - this could be beefed up a lot, similar to os::print_location6019// - for now we just query the allocation start point. This may be confusing for cases where6020// the kernel merges multiple mappings.6021if (first_line) {6022char buf[MAX_PATH];6023if (os::dll_address_to_library_name(allocation_base, buf, sizeof(buf), nullptr)) {6024st->print(", %s", buf);6025is_dll = true;6026}6027}6028// If memory is accessible, and we do not know anything else about it, print a snippet6029if (!is_dll &&6030minfo->State == MEM_COMMIT &&6031!(minfo->Protect & PAGE_NOACCESS || minfo->Protect & PAGE_GUARD)) {6032st->print_raw(", ");6033print_snippet(region_start, st);6034}6035st->cr();6036// Next region...6037bool rc = checkedVirtualQuery(region_end, minfo);6038if (rc == false || // VirtualQuery error, end of allocation?6039(minfo->State == MEM_FREE) || // end of allocation, free memory follows6040((address)minfo->AllocationBase != allocation_base) || // end of allocation, a new one starts6041(region_end > end)) // end of range to print.6042{6043return region_end;6044}6045first_line = false;6046}6047#undef IS_IN6048ShouldNotReachHere();6049return NULL;6050}60516052void os::print_memory_mappings(char* addr, size_t bytes, outputStream* st) {6053MEMORY_BASIC_INFORMATION minfo;6054address start = (address)addr;6055address end = start + bytes;6056address p = start;6057if (p == nullptr) { // Lets skip the zero pages.6058p += os::vm_allocation_granularity();6059}6060address p2 = p; // guard against wraparounds6061int fuse = 0;60626063while (p < end && p >= p2) {6064p2 = p;6065// Probe for the next mapping.6066if (checkedVirtualQuery(p, &minfo)) {6067if (minfo.State != MEM_FREE) {6068// Found one. Print it out.6069address p2 = print_one_mapping(&minfo, start, end, st);6070assert(p2 > p, "Sanity");6071p = p2;6072} else {6073// Note: for free regions, most of MEMORY_BASIC_INFORMATION is undefined.6074// Only region dimensions are not: use those to jump to the end of6075// the free range.6076address region_start = (address)minfo.BaseAddress;6077address region_end = region_start + minfo.RegionSize;6078assert(p >= region_start && p < region_end, "Sanity");6079p = region_end;6080}6081} else {6082// MSDN doc on VirtualQuery is unclear about what it means if it returns an error.6083// In particular, whether querying an address outside any mappings would report6084// a MEM_FREE region or just return an error. From experiments, it seems to return6085// a MEM_FREE region for unmapped areas in valid address space and an error if we6086// are outside valid address space.6087// Here, we advance the probe pointer by alloc granularity. But if the range to print6088// is large, this may take a long time. Therefore lets stop right away if the address6089// is outside of what we know are valid addresses on Windows. Also, add a loop fuse.6090static const address end_virt = (address)(LP64_ONLY(0x7ffffffffffULL) NOT_LP64(3*G));6091if (p >= end_virt) {6092break;6093} else {6094// Advance probe pointer, but with a fuse to break long loops.6095if (fuse++ == 100000) {6096break;6097}6098p += os::vm_allocation_granularity();6099}6100}6101}6102}610361046105