products/Sources/formale Sprachen/Java/openjdk-20-36_src/src/hotspot/os/windows image not shown  

Quellcode-Bibliothek

© Kompilation durch diese Firma

[Weder Korrektheit noch Funktionsfähigkeit der Software werden zugesichert.]

Datei: c2_globals_aix.hpp   Sprache: C

/*
 * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 *
 */


// API level must be at least Windows Vista or Server 2008 to use InitOnceExecuteOnce

// no precompiled headers
#include "classfile/vmSymbols.hpp"
#include "code/codeCache.hpp"
#include "code/icBuffer.hpp"
#include "code/nativeInst.hpp"
#include "code/vtableStubs.hpp"
#include "compiler/compileBroker.hpp"
#include "compiler/disassembler.hpp"
#include "interpreter/interpreter.hpp"
#include "jvm.h"
#include "jvmtifiles/jvmti.h"
#include "logging/log.hpp"
#include "logging/logStream.hpp"
#include "memory/allocation.inline.hpp"
#include "oops/oop.inline.hpp"
#include "os_windows.inline.hpp"
#include "prims/jniFastGetField.hpp"
#include "prims/jvm_misc.hpp"
#include "runtime/arguments.hpp"
#include "runtime/atomic.hpp"
#include "runtime/globals.hpp"
#include "runtime/globals_extension.hpp"
#include "runtime/interfaceSupport.inline.hpp"
#include "runtime/java.hpp"
#include "runtime/javaCalls.hpp"
#include "runtime/javaThread.hpp"
#include "runtime/mutexLocker.hpp"
#include "runtime/objectMonitor.hpp"
#include "runtime/orderAccess.hpp"
#include "runtime/osInfo.hpp"
#include "runtime/osThread.hpp"
#include "runtime/park.hpp"
#include "runtime/perfMemory.hpp"
#include "runtime/safefetch.hpp"
#include "runtime/safepointMechanism.hpp"
#include "runtime/semaphore.inline.hpp"
#include "runtime/sharedRuntime.hpp"
#include "runtime/statSampler.hpp"
#include "runtime/stubRoutines.hpp"
#include "runtime/threads.hpp"
#include "runtime/threadCritical.hpp"
#include "runtime/timer.hpp"
#include "runtime/vm_version.hpp"
#include "services/attachListener.hpp"
#include "services/memTracker.hpp"
#include "services/runtimeService.hpp"
#include "symbolengine.hpp"
#include "utilities/align.hpp"
#include "utilities/decoder.hpp"
#include "utilities/defaultStream.hpp"
#include "utilities/events.hpp"
#include "utilities/macros.hpp"
#include "utilities/vmError.hpp"
#include "windbghelp.hpp"

#ifdef _DEBUG
#include <crtdbg.h>
#endif

#include <windows.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/timeb.h>
#include <objidl.h>
#include <shlobj.h>

#include <malloc.h>
#include <signal.h>
#include <direct.h>
#include <errno.h>
#include <fcntl.h>
#include <io.h>
#include <process.h>              // For _beginthreadex(), _endthreadex()
#include <imagehlp.h>             // For os::dll_address_to_function_name
// for enumerating dll libraries
#include <vdmdbg.h>
#include <psapi.h>
#include <mmsystem.h>
#include <winsock2.h>
#include <versionhelpers.h>

// for timer info max values which include all bits
#define ALL_64_BITS CONST64(-1)

// For DLL loading/load error detection
// Values of PE COFF
#define IMAGE_FILE_PTR_TO_SIGNATURE 0x3c
#define IMAGE_FILE_SIGNATURE_LENGTH 4

static HANDLE main_process;
static HANDLE main_thread;
static int    main_thread_id;

static FILETIME process_creation_time;
static FILETIME process_exit_time;
static FILETIME process_user_time;
static FILETIME process_kernel_time;

#if defined(_M_ARM64)
  #define __CPU__ aarch64
#elif defined(_M_AMD64)
  #define __CPU__ amd64
#else
  #define __CPU__ i486
#endif

#if defined(USE_VECTORED_EXCEPTION_HANDLING)
PVOID  topLevelVectoredExceptionHandler = NULL;
LPTOP_LEVEL_EXCEPTION_FILTER previousUnhandledExceptionFilter = NULL;
#endif

// save DLL module handle, used by GetModuleFileName

HINSTANCE vm_lib_handle;

BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, LPVOID reserved) {
  switch (reason) {
  case DLL_PROCESS_ATTACH:
    vm_lib_handle = hinst;
    if (ForceTimeHighResolution) {
      timeBeginPeriod(1L);
    }
    WindowsDbgHelp::pre_initialize();
    SymbolEngine::pre_initialize();
    break;
  case DLL_PROCESS_DETACH:
    if (ForceTimeHighResolution) {
      timeEndPeriod(1L);
    }
#if defined(USE_VECTORED_EXCEPTION_HANDLING)
    if (topLevelVectoredExceptionHandler != NULL) {
      RemoveVectoredExceptionHandler(topLevelVectoredExceptionHandler);
      topLevelVectoredExceptionHandler = NULL;
    }
#endif
    break;
  default:
    break;
  }
  return true;
}

static inline double fileTimeAsDouble(FILETIME* time) {
  const double high  = (double) ((unsigned int) ~0);
  const double split = 10000000.0;
  double result = (time->dwLowDateTime / split) +
                   time->dwHighDateTime * (high/split);
  return result;
}

// Implementation of os

#define RANGE_FORMAT                "[" PTR_FORMAT "-" PTR_FORMAT ")"
#define RANGE_FORMAT_ARGS(p, len)   p2i(p), p2i((address)p + len)

// A number of wrappers for more frequently used system calls, to add standard logging.

struct PreserveLastError {
  const DWORD v;
  PreserveLastError() : v(::GetLastError()) {}
  ~PreserveLastError() { ::SetLastError(v); }
};

// Logging wrapper for VirtualAlloc
static LPVOID virtualAlloc(LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect) {
  LPVOID result = ::VirtualAlloc(lpAddress, dwSize, flAllocationType, flProtect);
  if (result != NULL) {
    log_trace(os)("VirtualAlloc(" PTR_FORMAT ", " SIZE_FORMAT ", %x, %x) returned " PTR_FORMAT "%s.",
                  p2i(lpAddress), dwSize, flAllocationType, flProtect, p2i(result),
                  ((lpAddress != NULL && result != lpAddress) ? " " : ""));
  } else {
    PreserveLastError ple;
    log_info(os)("VirtualAlloc(" PTR_FORMAT ", " SIZE_FORMAT ", %x, %x) failed (%u).",
                  p2i(lpAddress), dwSize, flAllocationType, flProtect, ple.v);
  }
  return result;
}

// Logging wrapper for VirtualFree
static BOOL virtualFree(LPVOID lpAddress, SIZE_T dwSize, DWORD  dwFreeType) {
  BOOL result = ::VirtualFree(lpAddress, dwSize, dwFreeType);
  if (result != FALSE) {
    log_trace(os)("VirtualFree(" PTR_FORMAT ", " SIZE_FORMAT ", %x) succeeded",
                  p2i(lpAddress), dwSize, dwFreeType);
  } else {
    PreserveLastError ple;
    log_info(os)("VirtualFree(" PTR_FORMAT ", " SIZE_FORMAT ", %x) failed (%u).",
                 p2i(lpAddress), dwSize, dwFreeType, ple.v);
  }
  return result;
}

// Logging wrapper for VirtualAllocExNuma
static LPVOID virtualAllocExNuma(HANDLE hProcess, LPVOID lpAddress, SIZE_T dwSize, DWORD  flAllocationType,
                                 DWORD  flProtect, DWORD  nndPreferred) {
  LPVOID result = ::VirtualAllocExNuma(hProcess, lpAddress, dwSize, flAllocationType, flProtect, nndPreferred);
  if (result != NULL) {
    log_trace(os)("VirtualAllocExNuma(" PTR_FORMAT ", " SIZE_FORMAT ", %x, %x, %x) returned " PTR_FORMAT "%s.",
                  p2i(lpAddress), dwSize, flAllocationType, flProtect, nndPreferred, p2i(result),
                  ((lpAddress != NULL && result != lpAddress) ? " " : ""));
  } else {
    PreserveLastError ple;
    log_info(os)("VirtualAllocExNuma(" PTR_FORMAT ", " SIZE_FORMAT ", %x, %x, %x) failed (%u).",
                 p2i(lpAddress), dwSize, flAllocationType, flProtect, nndPreferred, ple.v);
  }
  return result;
}

// Logging wrapper for MapViewOfFileEx
static LPVOID mapViewOfFileEx(HANDLE hFileMappingObject, DWORD  dwDesiredAccess, DWORD  dwFileOffsetHigh,
                              DWORD  dwFileOffsetLow, SIZE_T dwNumberOfBytesToMap, LPVOID lpBaseAddress) {
  LPVOID result = ::MapViewOfFileEx(hFileMappingObject, dwDesiredAccess, dwFileOffsetHigh,
                                    dwFileOffsetLow, dwNumberOfBytesToMap, lpBaseAddress);
  if (result != NULL) {
    log_trace(os)("MapViewOfFileEx(" PTR_FORMAT ", " SIZE_FORMAT ") returned " PTR_FORMAT "%s.",
                  p2i(lpBaseAddress), dwNumberOfBytesToMap, p2i(result),
                  ((lpBaseAddress != NULL && result != lpBaseAddress) ? " " : ""));
  } else {
    PreserveLastError ple;
    log_info(os)("MapViewOfFileEx(" PTR_FORMAT ", " SIZE_FORMAT ") failed (%u).",
                 p2i(lpBaseAddress), dwNumberOfBytesToMap, ple.v);
  }
  return result;
}

// Logging wrapper for UnmapViewOfFile
static BOOL unmapViewOfFile(LPCVOID lpBaseAddress) {
  BOOL result = ::UnmapViewOfFile(lpBaseAddress);
  if (result != FALSE) {
    log_trace(os)("UnmapViewOfFile(" PTR_FORMAT ") succeeded", p2i(lpBaseAddress));
  } else {
    PreserveLastError ple;
    log_info(os)("UnmapViewOfFile(" PTR_FORMAT ") failed (%u).",  p2i(lpBaseAddress), ple.v);
  }
  return result;
}

char** os::get_environ() { return _environ; }

// No setuid programs under Windows.
bool os::have_special_privileges() {
  return false;
}


// This method is a periodic task to check for misbehaving JNI applications
// under CheckJNI, we can add any periodic checks here.
// For Windows at the moment does nothing
void os::run_periodic_checks(outputStream* st) {
  return;
}

// previous UnhandledExceptionFilter, if there is one
static LPTOP_LEVEL_EXCEPTION_FILTER prev_uef_handler = NULL;

LONG WINAPI Handle_FLT_Exception(struct _EXCEPTION_POINTERS* exceptionInfo);

void os::init_system_properties_values() {
  // sysclasspath, java_home, dll_dir
  {
    char *home_path;
    char *dll_path;
    char *pslash;
    const char *bin = "\\bin";
    char home_dir[MAX_PATH + 1];
    char *alt_home_dir = ::getenv("_ALT_JAVA_HOME_DIR");

    if (alt_home_dir != NULL)  {
      strncpy(home_dir, alt_home_dir, MAX_PATH + 1);
      home_dir[MAX_PATH] = '\0';
    } else {
      os::jvm_path(home_dir, sizeof(home_dir));
      // Found the full path to jvm.dll.
      // Now cut the path to <java_home>/jre if we can.
      *(strrchr(home_dir, '\\')) = '\0';  // get rid of \jvm.dll
      pslash = strrchr(home_dir, '\\');
      if (pslash != NULL) {
        *pslash = '\0';                   // get rid of \{client|server}
        pslash = strrchr(home_dir, '\\');
        if (pslash != NULL) {
          *pslash = '\0';                 // get rid of \bin
        }
      }
    }

    home_path = NEW_C_HEAP_ARRAY(char, strlen(home_dir) + 1, mtInternal);
    strcpy(home_path, home_dir);
    Arguments::set_java_home(home_path);
    FREE_C_HEAP_ARRAY(char, home_path);

    dll_path = NEW_C_HEAP_ARRAY(char, strlen(home_dir) + strlen(bin) + 1,
                                mtInternal);
    strcpy(dll_path, home_dir);
    strcat(dll_path, bin);
    Arguments::set_dll_dir(dll_path);
    FREE_C_HEAP_ARRAY(char, dll_path);

    if (!set_boot_path('\\'';')) {
      vm_exit_during_initialization("Failed setting boot class path.", NULL);
    }
  }

// library_path
#define EXT_DIR "\\lib\\ext"
#define BIN_DIR "\\bin"
#define PACKAGE_DIR "\\Sun\\Java"
  {
    // Win32 library search order (See the documentation for LoadLibrary):
    //
    // 1. The directory from which application is loaded.
    // 2. The system wide Java Extensions directory (Java only)
    // 3. System directory (GetSystemDirectory)
    // 4. Windows directory (GetWindowsDirectory)
    // 5. The PATH environment variable
    // 6. The current directory

    char *library_path;
    char tmp[MAX_PATH];
    char *path_str = ::getenv("PATH");

    library_path = NEW_C_HEAP_ARRAY(char, MAX_PATH * 5 + sizeof(PACKAGE_DIR) +
                                    sizeof(BIN_DIR) + (path_str ? strlen(path_str) : 0) + 10, mtInternal);

    library_path[0] = '\0';

    GetModuleFileName(NULL, tmp, sizeof(tmp));
    *(strrchr(tmp, '\\')) = '\0';
    strcat(library_path, tmp);

    GetWindowsDirectory(tmp, sizeof(tmp));
    strcat(library_path, ";");
    strcat(library_path, tmp);
    strcat(library_path, PACKAGE_DIR BIN_DIR);

    GetSystemDirectory(tmp, sizeof(tmp));
    strcat(library_path, ";");
    strcat(library_path, tmp);

    GetWindowsDirectory(tmp, sizeof(tmp));
    strcat(library_path, ";");
    strcat(library_path, tmp);

    if (path_str) {
      strcat(library_path, ";");
      strcat(library_path, path_str);
    }

    strcat(library_path, ";.");

    Arguments::set_library_path(library_path);
    FREE_C_HEAP_ARRAY(char, library_path);
  }

  // Default extensions directory
  {
    char path[MAX_PATH];
    char buf[2 * MAX_PATH + 2 * sizeof(EXT_DIR) + sizeof(PACKAGE_DIR) + 1];
    GetWindowsDirectory(path, MAX_PATH);
    sprintf(buf, "%s%s;%s%s%s", Arguments::get_java_home(), EXT_DIR,
            path, PACKAGE_DIR, EXT_DIR);
    Arguments::set_ext_dirs(buf);
  }
  #undef EXT_DIR
  #undef BIN_DIR
  #undef PACKAGE_DIR

#ifndef _WIN64
  // set our UnhandledExceptionFilter and save any previous one
  prev_uef_handler = SetUnhandledExceptionFilter(Handle_FLT_Exception);
#endif

  // Done
  return;
}

void os::breakpoint() {
  DebugBreak();
}

// Invoked from the BREAKPOINT Macro
extern "C" void breakpoint() {
  os::breakpoint();
}

// RtlCaptureStackBackTrace Windows API may not exist prior to Windows XP.
// So far, this method is only used by Native Memory Tracking, which is
// only supported on Windows XP or later.
//
int os::get_native_stack(address* stack, int frames, int toSkip) {
  int captured = RtlCaptureStackBackTrace(toSkip + 1, frames, (PVOID*)stack, NULL);
  for (int index = captured; index < frames; index ++) {
    stack[index] = NULL;
  }
  return captured;
}

// os::current_stack_base()
//
//   Returns the base of the stack, which is the stack's
//   starting address.  This function must be called
//   while running on the stack of the thread being queried.

address os::current_stack_base() {
  MEMORY_BASIC_INFORMATION minfo;
  address stack_bottom;
  size_t stack_size;

  VirtualQuery(&minfo, &minfo, sizeof(minfo));
  stack_bottom =  (address)minfo.AllocationBase;
  stack_size = minfo.RegionSize;

  // Add up the sizes of all the regions with the same
  // AllocationBase.
  while (1) {
    VirtualQuery(stack_bottom+stack_size, &minfo, sizeof(minfo));
    if (stack_bottom == (address)minfo.AllocationBase) {
      stack_size += minfo.RegionSize;
    } else {
      break;
    }
  }
  return stack_bottom + stack_size;
}

size_t os::current_stack_size() {
  size_t sz;
  MEMORY_BASIC_INFORMATION minfo;
  VirtualQuery(&minfo, &minfo, sizeof(minfo));
  sz = (size_t)os::current_stack_base() - (size_t)minfo.AllocationBase;
  return sz;
}

bool os::committed_in_range(address start, size_t size, address& committed_start, size_t& committed_size) {
  MEMORY_BASIC_INFORMATION minfo;
  committed_start = NULL;
  committed_size = 0;
  address top = start + size;
  const address start_addr = start;
  while (start < top) {
    VirtualQuery(start, &minfo, sizeof(minfo));
    if ((minfo.State & MEM_COMMIT) == 0) {  // not committed
      if (committed_start != NULL) {
        break;
      }
    } else {  // committed
      if (committed_start == NULL) {
        committed_start = start;
      }
      size_t offset = start - (address)minfo.BaseAddress;
      committed_size += minfo.RegionSize - offset;
    }
    start = (address)minfo.BaseAddress + minfo.RegionSize;
  }

  if (committed_start == NULL) {
    assert(committed_size == 0, "Sanity");
    return false;
  } else {
    assert(committed_start >= start_addr && committed_start < top, "Out of range");
    // current region may go beyond the limit, trim to the limit
    committed_size = MIN2(committed_size, size_t(top - committed_start));
    return true;
  }
}

struct tm* os::localtime_pd(const time_t* clock, struct tm* res) {
  const struct tm* time_struct_ptr = localtime(clock);
  if (time_struct_ptr != NULL) {
    *res = *time_struct_ptr;
    return res;
  }
  return NULL;
}

struct tm* os::gmtime_pd(const time_t* clock, struct tm* res) {
  const struct tm* time_struct_ptr = gmtime(clock);
  if (time_struct_ptr != NULL) {
    *res = *time_struct_ptr;
    return res;
  }
  return NULL;
}

JNIEXPORT
LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo);

// Thread start routine for all newly created threads
static unsigned __stdcall thread_native_entry(Thread* thread) {

  thread->record_stack_base_and_size();
  thread->initialize_thread_current();

  OSThread* osthr = thread->osthread();
  assert(osthr->get_state() == RUNNABLE, "invalid os thread state");

  if (UseNUMA) {
    int lgrp_id = os::numa_get_group_id();
    if (lgrp_id != -1) {
      thread->set_lgrp_id(lgrp_id);
    }
  }

  // Diagnostic code to investigate JDK-6573254
  int res = 30115;  // non-java thread
  if (thread->is_Java_thread()) {
    res = 20115;    // java thread
  }

  log_info(os, thread)("Thread is alive (tid: " UINTX_FORMAT ", stacksize: " SIZE_FORMAT "k).", os::current_thread_id(), thread->stack_size() / K);

#ifdef USE_VECTORED_EXCEPTION_HANDLING
  // Any exception is caught by the Vectored Exception Handler, so VM can
  // generate error dump when an exception occurred in non-Java thread
  // (e.g. VM thread).
  thread->call_run();
#else
  // Install a win32 structured exception handler around every thread created
  // by VM, so VM can generate error dump when an exception occurred in non-
  // Java thread (e.g. VM thread).
  __try {
    thread->call_run();
  } __except(topLevelExceptionFilter(
                                     (_EXCEPTION_POINTERS*)_exception_info())) {
    // Nothing to do.
  }
#endif

  // Note: at this point the thread object may already have deleted itself.
  // Do not dereference it from here on out.

  log_info(os, thread)("Thread finished (tid: " UINTX_FORMAT ").", os::current_thread_id());

  // Thread must not return from exit_process_or_thread(), but if it does,
  // let it proceed to exit normally
  return (unsigned)os::win32::exit_process_or_thread(os::win32::EPT_THREAD, res);
}

static OSThread* create_os_thread(Thread* thread, HANDLE thread_handle,
                                  int thread_id) {
  // Allocate the OSThread object
  OSThread* osthread = new OSThread();
  if (osthread == NULL) return NULL;

  // Initialize the JDK library's interrupt event.
  // This should really be done when OSThread is constructed,
  // but there is no way for a constructor to report failure to
  // allocate the event.
  HANDLE interrupt_event = CreateEvent(NULL, truefalse, NULL);
  if (interrupt_event == NULL) {
    delete osthread;
    return NULL;
  }
  osthread->set_interrupt_event(interrupt_event);

  // Store info on the Win32 thread into the OSThread
  osthread->set_thread_handle(thread_handle);
  osthread->set_thread_id(thread_id);

  if (UseNUMA) {
    int lgrp_id = os::numa_get_group_id();
    if (lgrp_id != -1) {
      thread->set_lgrp_id(lgrp_id);
    }
  }

  // Initial thread state is INITIALIZED, not SUSPENDED
  osthread->set_state(INITIALIZED);

  return osthread;
}


bool os::create_attached_thread(JavaThread* thread) {
#ifdef ASSERT
  thread->verify_not_published();
#endif
  HANDLE thread_h;
  if (!DuplicateHandle(main_process, GetCurrentThread(), GetCurrentProcess(),
                       &thread_h, THREAD_ALL_ACCESS, false, 0)) {
    fatal("DuplicateHandle failed\n");
  }
  OSThread* osthread = create_os_thread(thread, thread_h,
                                        (int)current_thread_id());
  if (osthread == NULL) {
    return false;
  }

  // Initial thread state is RUNNABLE
  osthread->set_state(RUNNABLE);

  thread->set_osthread(osthread);

  log_info(os, thread)("Thread attached (tid: " UINTX_FORMAT ", stack: "
                       PTR_FORMAT " - " PTR_FORMAT " (" SIZE_FORMAT "k) ).",
                       os::current_thread_id(), p2i(thread->stack_base()),
                       p2i(thread->stack_end()), thread->stack_size());

  return true;
}

bool os::create_main_thread(JavaThread* thread) {
#ifdef ASSERT
  thread->verify_not_published();
#endif
  if (_starting_thread == NULL) {
    _starting_thread = create_os_thread(thread, main_thread, main_thread_id);
    if (_starting_thread == NULL) {
      return false;
    }
  }

  // The primordial thread is runnable from the start)
  _starting_thread->set_state(RUNNABLE);

  thread->set_osthread(_starting_thread);
  return true;
}

// Helper function to trace _beginthreadex attributes,
//  similar to os::Posix::describe_pthread_attr()
static char* describe_beginthreadex_attributes(char* buf, size_t buflen,
                                               size_t stacksize, unsigned initflag) {
  stringStream ss(buf, buflen);
  if (stacksize == 0) {
    ss.print("stacksize: default, ");
  } else {
    ss.print("stacksize: " SIZE_FORMAT "k, ", stacksize / K);
  }
  ss.print("flags: ");
  #define PRINT_FLAG(f) if (initflag & f) ss.print( #f " ");
  #define ALL(X) \
    X(CREATE_SUSPENDED) \
    X(STACK_SIZE_PARAM_IS_A_RESERVATION)
  ALL(PRINT_FLAG)
  #undef ALL
  #undef PRINT_FLAG
  return buf;
}

// Allocate and initialize a new OSThread
bool os::create_thread(Thread* thread, ThreadType thr_type,
                       size_t stack_size) {
  unsigned thread_id;

  // Allocate the OSThread object
  OSThread* osthread = new OSThread();
  if (osthread == NULL) {
    return false;
  }

  // Initial state is ALLOCATED but not INITIALIZED
  osthread->set_state(ALLOCATED);

  // Initialize the JDK library's interrupt event.
  // This should really be done when OSThread is constructed,
  // but there is no way for a constructor to report failure to
  // allocate the event.
  HANDLE interrupt_event = CreateEvent(NULL, truefalse, NULL);
  if (interrupt_event == NULL) {
    delete osthread;
    return false;
  }
  osthread->set_interrupt_event(interrupt_event);
  // We don't call set_interrupted(false) as it will trip the assert in there
  // as we are not operating on the current thread. We don't need to call it
  // because the initial state is already correct.

  thread->set_osthread(osthread);

  if (stack_size == 0) {
    switch (thr_type) {
    case os::java_thread:
      // Java threads use ThreadStackSize which default value can be changed with the flag -Xss
      if (JavaThread::stack_size_at_create() > 0) {
        stack_size = JavaThread::stack_size_at_create();
      }
      break;
    case os::compiler_thread:
      if (CompilerThreadStackSize > 0) {
        stack_size = (size_t)(CompilerThreadStackSize * K);
        break;
      } // else fall through:
        // use VMThreadStackSize if CompilerThreadStackSize is not defined
    case os::vm_thread:
    case os::gc_thread:
    case os::asynclog_thread:
    case os::watcher_thread:
      if (VMThreadStackSize > 0) stack_size = (size_t)(VMThreadStackSize * K);
      break;
    }
  }

  // Create the Win32 thread
  //
  // Contrary to what MSDN document says, "stack_size" in _beginthreadex()
  // does not specify stack size. Instead, it specifies the size of
  // initially committed space. The stack size is determined by
  // PE header in the executable. If the committed "stack_size" is larger
  // than default value in the PE header, the stack is rounded up to the
  // nearest multiple of 1MB. For example if the launcher has default
  // stack size of 320k, specifying any size less than 320k does not
  // affect the actual stack size at all, it only affects the initial
  // commitment. On the other hand, specifying 'stack_size' larger than
  // default value may cause significant increase in memory usage, because
  // not only the stack space will be rounded up to MB, but also the
  // entire space is committed upfront.
  //
  // Finally Windows XP added a new flag 'STACK_SIZE_PARAM_IS_A_RESERVATION'
  // for CreateThread() that can treat 'stack_size' as stack size. However we
  // are not supposed to call CreateThread() directly according to MSDN
  // document because JVM uses C runtime library. The good news is that the
  // flag appears to work with _beginthredex() as well.

  const unsigned initflag = CREATE_SUSPENDED | STACK_SIZE_PARAM_IS_A_RESERVATION;
  HANDLE thread_handle;
  int limit = 3;
  do {
    thread_handle =
      (HANDLE)_beginthreadex(NULL,
                             (unsigned)stack_size,
                             (unsigned (__stdcall *)(void*)) thread_native_entry,
                             thread,
                             initflag,
                             &thread_id);
  } while (thread_handle == NULL && errno == EAGAIN && limit-- > 0);

  ResourceMark rm;
  char buf[64];
  if (thread_handle != NULL) {
    log_info(os, thread)("Thread \"%s\" started (tid: %u, attributes: %s)",
                         thread->name(), thread_id,
                         describe_beginthreadex_attributes(buf, sizeof(buf), stack_size, initflag));
  } else {
    log_warning(os, thread)("Failed to start thread \"%s\" - _beginthreadex failed (%s) for attributes: %s.",
                            thread->name(), os::errno_name(errno), describe_beginthreadex_attributes(buf, sizeof(buf), stack_size, initflag));
    // Log some OS information which might explain why creating the thread failed.
    log_info(os, thread)("Number of threads approx. running in the VM: %d", Threads::number_of_threads());
    LogStream st(Log(os, thread)::info());
    os::print_memory_info(&st);
  }

  if (thread_handle == NULL) {
    // Need to clean up stuff we've allocated so far
    thread->set_osthread(NULL);
    delete osthread;
    return false;
  }

  // Store info on the Win32 thread into the OSThread
  osthread->set_thread_handle(thread_handle);
  osthread->set_thread_id(thread_id);

  // Thread state now is INITIALIZED, not SUSPENDED
  osthread->set_state(INITIALIZED);

  // The thread is returned suspended (in state INITIALIZED), and is started higher up in the call chain
  return true;
}


// Free Win32 resources related to the OSThread
void os::free_thread(OSThread* osthread) {
  assert(osthread != NULL, "osthread not set");

  // We are told to free resources of the argument thread,
  // but we can only really operate on the current thread.
  assert(Thread::current()->osthread() == osthread,
         "os::free_thread but not current thread");

  CloseHandle(osthread->thread_handle());
  delete osthread;
}

static jlong first_filetime;
static jlong initial_performance_count;
static jlong performance_frequency;


jlong as_long(LARGE_INTEGER x) {
  jlong result = 0; // initialization to avoid warning
  set_high(&result, x.HighPart);
  set_low(&result, x.LowPart);
  return result;
}


jlong os::elapsed_counter() {
  LARGE_INTEGER count;
  QueryPerformanceCounter(&count);
  return as_long(count) - initial_performance_count;
}


jlong os::elapsed_frequency() {
  return performance_frequency;
}


julong os::available_memory() {
  return win32::available_memory();
}

julong os::win32::available_memory() {
  // Use GlobalMemoryStatusEx() because GlobalMemoryStatus() may return incorrect
  // value if total memory is larger than 4GB
  MEMORYSTATUSEX ms;
  ms.dwLength = sizeof(ms);
  GlobalMemoryStatusEx(&ms);

  return (julong)ms.ullAvailPhys;
}

julong os::physical_memory() {
  return win32::physical_memory();
}

bool os::has_allocatable_memory_limit(size_t* limit) {
  MEMORYSTATUSEX ms;
  ms.dwLength = sizeof(ms);
  GlobalMemoryStatusEx(&ms);
#ifdef _LP64
  *limit = (size_t)ms.ullAvailVirtual;
  return true;
#else
  // Limit to 1400m because of the 2gb address space wall
  *limit = MIN2((size_t)1400*M, (size_t)ms.ullAvailVirtual);
  return true;
#endif
}

int os::active_processor_count() {
  // User has overridden the number of active processors
  if (ActiveProcessorCount > 0) {
    log_trace(os)("active_processor_count: "
                  "active processor count set by user : %d",
                  ActiveProcessorCount);
    return ActiveProcessorCount;
  }

  DWORD_PTR lpProcessAffinityMask = 0;
  DWORD_PTR lpSystemAffinityMask = 0;
  int proc_count = processor_count();
  if (proc_count <= sizeof(UINT_PTR) * BitsPerByte &&
      GetProcessAffinityMask(GetCurrentProcess(), &lpProcessAffinityMask, &lpSystemAffinityMask)) {
    // Nof active processors is number of bits in process affinity mask
    int bitcount = 0;
    while (lpProcessAffinityMask != 0) {
      lpProcessAffinityMask = lpProcessAffinityMask & (lpProcessAffinityMask-1);
      bitcount++;
    }
    return bitcount;
  } else {
    return proc_count;
  }
}

uint os::processor_id() {
  return (uint)GetCurrentProcessorNumber();
}

// For dynamic lookup of SetThreadDescription API
typedef HRESULT (WINAPI *SetThreadDescriptionFnPtr)(HANDLE, PCWSTR);
typedef HRESULT (WINAPI *GetThreadDescriptionFnPtr)(HANDLE, PWSTR*);
static SetThreadDescriptionFnPtr _SetThreadDescription = NULL;
DEBUG_ONLY(static GetThreadDescriptionFnPtr _GetThreadDescription = NULL;)

// forward decl.
static errno_t convert_to_unicode(char const* char_path, LPWSTR* unicode_path);

void os::set_native_thread_name(const char *name) {

  // From Windows 10 and Windows 2016 server, we have a direct API
  // for setting the thread name/description:
  // https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-setthreaddescription

  if (_SetThreadDescription != NULL) {
    // SetThreadDescription takes a PCWSTR but we have conversion routines that produce
    // LPWSTR. The only difference is that PCWSTR is a pointer to const WCHAR.
    LPWSTR unicode_name;
    errno_t err = convert_to_unicode(name, &unicode_name);
    if (err == ERROR_SUCCESS) {
      HANDLE current = GetCurrentThread();
      HRESULT hr = _SetThreadDescription(current, unicode_name);
      if (FAILED(hr)) {
        log_debug(os, thread)("set_native_thread_name: SetThreadDescription failed - falling back to debugger method");
        FREE_C_HEAP_ARRAY(WCHAR, unicode_name);
      } else {
        log_trace(os, thread)("set_native_thread_name: SetThreadDescription succeeded - new name: %s", name);

#ifdef ASSERT
        // For verification purposes in a debug build we read the thread name back and check it.
        PWSTR thread_name;
        HRESULT hr2 = _GetThreadDescription(current, &thread_name);
        if (FAILED(hr2)) {
          log_debug(os, thread)("set_native_thread_name: GetThreadDescription failed!");
        } else {
          int res = CompareStringW(LOCALE_USER_DEFAULT,
                                   0, // no special comparison rules
                                   unicode_name,
                                   -1, // null-terminated
                                   thread_name,
                                   -1  // null-terminated
                                   );
          assert(res == CSTR_EQUAL,
                 "Name strings were not the same - set: %ls, but read: %ls", unicode_name, thread_name);
          LocalFree(thread_name);
        }
#endif
        FREE_C_HEAP_ARRAY(WCHAR, unicode_name);
        return;
      }
    } else {
      log_debug(os, thread)("set_native_thread_name: convert_to_unicode failed - falling back to debugger method");
    }
  }

  // See: http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx
  //
  // Note that unfortunately this only works if the process
  // is already attached to a debugger; debugger must observe
  // the exception below to show the correct name.

  // If there is no debugger attached skip raising the exception
  if (!IsDebuggerPresent()) {
    log_debug(os, thread)("set_native_thread_name: no debugger present so unable to set thread name");
    return;
  }

  const DWORD MS_VC_EXCEPTION = 0x406D1388;
  struct {
    DWORD dwType;     // must be 0x1000
    LPCSTR szName;    // pointer to name (in user addr space)
    DWORD dwThreadID; // thread ID (-1=caller thread)
    DWORD dwFlags;    // reserved for future use, must be zero
  } info;

  info.dwType = 0x1000;
  info.szName = name;
  info.dwThreadID = -1;
  info.dwFlags = 0;

  __try {
    RaiseException (MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(DWORD), (const ULONG_PTR*)&info&nbsp;);
  } __except(EXCEPTION_EXECUTE_HANDLER) {}
}

void os::win32::initialize_performance_counter() {
  LARGE_INTEGER count;
  QueryPerformanceFrequency(&count);
  performance_frequency = as_long(count);
  QueryPerformanceCounter(&count);
  initial_performance_count = as_long(count);
}


double os::elapsedTime() {
  return (double) elapsed_counter() / (double) elapsed_frequency();
}


// Windows format:
//   The FILETIME structure is a 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601.
// Java format:
//   Java standards require the number of milliseconds since 1/1/1970

// Constant offset - calculated using offset()
static jlong  _offset   = 116444736000000000;
// Fake time counter for reproducible results when debugging
static jlong  fake_time = 0;

#ifdef ASSERT
// Just to be safe, recalculate the offset in debug mode
static jlong _calculated_offset = 0;
static int   _has_calculated_offset = 0;

jlong offset() {
  if (_has_calculated_offset) return _calculated_offset;
  SYSTEMTIME java_origin;
  java_origin.wYear          = 1970;
  java_origin.wMonth         = 1;
  java_origin.wDayOfWeek     = 0; // ignored
  java_origin.wDay           = 1;
  java_origin.wHour          = 0;
  java_origin.wMinute        = 0;
  java_origin.wSecond        = 0;
  java_origin.wMilliseconds  = 0;
  FILETIME jot;
  if (!SystemTimeToFileTime(&java_origin, &jot)) {
    fatal("Error = %d\nWindows error", GetLastError());
  }
  _calculated_offset = jlong_from(jot.dwHighDateTime, jot.dwLowDateTime);
  _has_calculated_offset = 1;
  assert(_calculated_offset == _offset, "Calculated and constant time offsets must be equal");
  return _calculated_offset;
}
#else
jlong offset() {
  return _offset;
}
#endif

jlong windows_to_java_time(FILETIME wt) {
  jlong a = jlong_from(wt.dwHighDateTime, wt.dwLowDateTime);
  return (a - offset()) / 10000;
}

// Returns time ticks in (10th of micro seconds)
jlong windows_to_time_ticks(FILETIME wt) {
  jlong a = jlong_from(wt.dwHighDateTime, wt.dwLowDateTime);
  return (a - offset());
}

FILETIME java_to_windows_time(jlong l) {
  jlong a = (l * 10000) + offset();
  FILETIME result;
  result.dwHighDateTime = high(a);
  result.dwLowDateTime  = low(a);
  return result;
}

bool os::supports_vtime() { return true; }

double os::elapsedVTime() {
  FILETIME created;
  FILETIME exited;
  FILETIME kernel;
  FILETIME user;
  if (GetThreadTimes(GetCurrentThread(), &created, &exited, &kernel, &user) != 0) {
    // the resolution of windows_to_java_time() should be sufficient (ms)
    return (double) (windows_to_java_time(kernel) + windows_to_java_time(user)) / MILLIUNITS;
  } else {
    return elapsedTime();
  }
}

jlong os::javaTimeMillis() {
  FILETIME wt;
  GetSystemTimeAsFileTime(&wt);
  return windows_to_java_time(wt);
}

void os::javaTimeSystemUTC(jlong &seconds, jlong &nanos) {
  FILETIME wt;
  GetSystemTimeAsFileTime(&wt);
  jlong ticks = windows_to_time_ticks(wt); // 10th of micros
  jlong secs = jlong(ticks / 10000000); // 10000 * 1000
  seconds = secs;
  nanos = jlong(ticks - (secs*10000000)) * 100;
}

jlong os::javaTimeNanos() {
    LARGE_INTEGER current_count;
    QueryPerformanceCounter(¤t_count);
    double current = as_long(current_count);
    double freq = performance_frequency;
    jlong time = (jlong)((current/freq) * NANOSECS_PER_SEC);
    return time;
}

void os::javaTimeNanos_info(jvmtiTimerInfo *info_ptr) {
  jlong freq = performance_frequency;
  if (freq < NANOSECS_PER_SEC) {
    // the performance counter is 64 bits and we will
    // be multiplying it -- so no wrap in 64 bits
    info_ptr->max_value = ALL_64_BITS;
  } else if (freq > NANOSECS_PER_SEC) {
    // use the max value the counter can reach to
    // determine the max value which could be returned
    julong max_counter = (julong)ALL_64_BITS;
    info_ptr->max_value = (jlong)(max_counter / (freq / NANOSECS_PER_SEC));
  } else {
    // the performance counter is 64 bits and we will
    // be using it directly -- so no wrap in 64 bits
    info_ptr->max_value = ALL_64_BITS;
  }

  // using a counter, so no skipping
  info_ptr->may_skip_backward = false;
  info_ptr->may_skip_forward = false;

  info_ptr->kind = JVMTI_TIMER_ELAPSED;                // elapsed not CPU time
}

char* os::local_time_string(char *buf, size_t buflen) {
  SYSTEMTIME st;
  GetLocalTime(&st);
  jio_snprintf(buf, buflen, "%d-%02d-%02d %02d:%02d:%02d",
               st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
  return buf;
}

bool os::getTimesSecs(double* process_real_time,
                      double* process_user_time,
                      double* process_system_time) {
  HANDLE h_process = GetCurrentProcess();
  FILETIME create_time, exit_time, kernel_time, user_time;
  BOOL result = GetProcessTimes(h_process,
                                &create_time,
                                &exit_time,
                                &kernel_time,
                                &user_time);
  if (result != 0) {
    FILETIME wt;
    GetSystemTimeAsFileTime(&wt);
    jlong rtc_millis = windows_to_java_time(wt);
    *process_real_time = ((double) rtc_millis) / ((double) MILLIUNITS);
    *process_user_time =
      (double) jlong_from(user_time.dwHighDateTime, user_time.dwLowDateTime) / (10 * MICROUNITS);
    *process_system_time =
      (double) jlong_from(kernel_time.dwHighDateTime, kernel_time.dwLowDateTime) / (10 * MICROUNITS);
    return true;
  } else {
    return false;
  }
}

void os::shutdown() {
  // allow PerfMemory to attempt cleanup of any persistent resources
  perfMemory_exit();

  // flush buffered output, finish log files
  ostream_abort();

  // Check for abort hook
  abort_hook_t abort_hook = Arguments::abort_hook();
  if (abort_hook != NULL) {
    abort_hook();
  }
}


static HANDLE dumpFile = NULL;

// Check if dump file can be created.
void os::check_dump_limit(char* buffer, size_t buffsz) {
  bool status = true;
  if (!FLAG_IS_DEFAULT(CreateCoredumpOnCrash) && !CreateCoredumpOnCrash) {
    jio_snprintf(buffer, buffsz, "CreateCoredumpOnCrash is disabled from command line");
    status = false;
  }

#ifndef ASSERT
  if (!os::win32::is_windows_server() && FLAG_IS_DEFAULT(CreateCoredumpOnCrash)) {
    jio_snprintf(buffer, buffsz, "Minidumps are not enabled by default on client versions of Windows");
    status = false;
  }
#endif

  if (status) {
    const char* cwd = get_current_directory(NULL, 0);
    int pid = current_process_id();
    if (cwd != NULL) {
      jio_snprintf(buffer, buffsz, "%s\\hs_err_pid%u.mdmp", cwd, pid);
    } else {
      jio_snprintf(buffer, buffsz, ".\\hs_err_pid%u.mdmp", pid);
    }

    if (dumpFile == NULL &&
       (dumpFile = CreateFile(buffer, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL))
                 == INVALID_HANDLE_VALUE) {
      jio_snprintf(buffer, buffsz, "Failed to create minidump file (0x%x).", GetLastError());
      status = false;
    }
  }
  VMError::record_coredump_status(buffer, status);
}

void os::abort(bool dump_core, void* siginfo, const void* context) {
  EXCEPTION_POINTERS ep;
  MINIDUMP_EXCEPTION_INFORMATION mei;
  MINIDUMP_EXCEPTION_INFORMATION* pmei;

  HANDLE hProcess = GetCurrentProcess();
  DWORD processId = GetCurrentProcessId();
  MINIDUMP_TYPE dumpType;

  shutdown();
  if (!dump_core || dumpFile == NULL) {
    if (dumpFile != NULL) {
      CloseHandle(dumpFile);
    }
    win32::exit_process_or_thread(win32::EPT_PROCESS, 1);
  }

  dumpType = (MINIDUMP_TYPE)(MiniDumpWithFullMemory | MiniDumpWithHandleData |
    MiniDumpWithFullMemoryInfo | MiniDumpWithThreadInfo | MiniDumpWithUnloadedModules);

  if (siginfo != NULL && context != NULL) {
    ep.ContextRecord = (PCONTEXT) context;
    ep.ExceptionRecord = (PEXCEPTION_RECORD) siginfo;

    mei.ThreadId = GetCurrentThreadId();
    mei.ExceptionPointers = &ep;
    pmei = &mei;
  } else {
    pmei = NULL;
  }

  // Older versions of dbghelp.dll (the one shipped with Win2003 for example) may not support all
  // the dump types we really want. If first call fails, lets fall back to just use MiniDumpWithFullMemory then.
  if (!WindowsDbgHelp::miniDumpWriteDump(hProcess, processId, dumpFile, dumpType, pmei, NULL, NULL) &&
      !WindowsDbgHelp::miniDumpWriteDump(hProcess, processId, dumpFile, (MINIDUMP_TYPE)MiniDumpWithFullMemory, pmei, NULL, NULL)) {
    jio_fprintf(stderr, "Call to MiniDumpWriteDump() failed (Error 0x%x)\n", GetLastError());
  }
  CloseHandle(dumpFile);
  win32::exit_process_or_thread(win32::EPT_PROCESS, 1);
}

// Die immediately, no exit hook, no abort hook, no cleanup.
void os::die() {
  win32::exit_process_or_thread(win32::EPT_PROCESS_DIE, -1);
}

void  os::dll_unload(void *lib) {
  char name[MAX_PATH];
  if (::GetModuleFileName((HMODULE)lib, name, sizeof(name)) == 0) {
    snprintf(name, MAX_PATH, "");
  }
  if (::FreeLibrary((HMODULE)lib)) {
    Events::log_dll_message(NULL, "Unloaded dll \"%s\" [" INTPTR_FORMAT "]", name, p2i(lib));
    log_info(os)("Unloaded dll \"%s\" [" INTPTR_FORMAT "]", name, p2i(lib));
  } else {
    const DWORD errcode = ::GetLastError();
    Events::log_dll_message(NULL, "Attempt to unload dll \"%s\" [" INTPTR_FORMAT "] failed (error code %d)", name, p2i(lib), errcode);
    log_info(os)("Attempt to unload dll \"%s\" [" INTPTR_FORMAT "] failed (error code %d)", name, p2i(lib), errcode);
  }
}

void* os::dll_lookup(void *lib, const char *name) {
  return (void*)::GetProcAddress((HMODULE)lib, name);
}

// Directory routines copied from src/win32/native/java/io/dirent_md.c
//  * dirent_md.c       1.15 00/02/02
//
// The declarations for DIR and struct dirent are in jvm_win32.h.

// Caller must have already run dirname through JVM_NativePath, which removes
// duplicate slashes and converts all instances of '/' into '\\'.

DIR * os::opendir(const char *dirname) {
  assert(dirname != NULL, "just checking");   // hotspot change
  DIR *dirp = (DIR *)malloc(sizeof(DIR), mtInternal);
  DWORD fattr;                                // hotspot change
  char alt_dirname[4] = { 0, 0, 0, 0 };

  if (dirp == 0) {
    errno = ENOMEM;
    return 0;
  }

  // Win32 accepts "\" in its POSIX stat(), but refuses to treat it
  // as a directory in FindFirstFile().  We detect this case here and
  // prepend the current drive name.
  //
  if (dirname[1] == '\0' && dirname[0] == '\\') {
    alt_dirname[0] = _getdrive() + 'A' - 1;
    alt_dirname[1] = ':';
    alt_dirname[2] = '\\';
    alt_dirname[3] = '\0';
    dirname = alt_dirname;
  }

  dirp->path = (char *)malloc(strlen(dirname) + 5, mtInternal);
  if (dirp->path == 0) {
    free(dirp);
    errno = ENOMEM;
    return 0;
  }
  strcpy(dirp->path, dirname);

  fattr = GetFileAttributes(dirp->path);
  if (fattr == 0xffffffff) {
    free(dirp->path);
    free(dirp);
    errno = ENOENT;
    return 0;
  } else if ((fattr & FILE_ATTRIBUTE_DIRECTORY) == 0) {
    free(dirp->path);
    free(dirp);
    errno = ENOTDIR;
    return 0;
  }

  // Append "*.*", or possibly "\\*.*", to path
  if (dirp->path[1] == ':' &&
      (dirp->path[2] == '\0' ||
      (dirp->path[2] == '\\' && dirp->path[3] == '\0'))) {
    // No '\\' needed for cases like "Z:" or "Z:\"
    strcat(dirp->path, "*.*");
  } else {
    strcat(dirp->path, "\\*.*");
  }

  dirp->handle = FindFirstFile(dirp->path, &dirp->find_data);
  if (dirp->handle == INVALID_HANDLE_VALUE) {
    if (GetLastError() != ERROR_FILE_NOT_FOUND) {
      free(dirp->path);
      free(dirp);
      errno = EACCES;
      return 0;
    }
  }
  return dirp;
}

struct dirent * os::readdir(DIR *dirp) {
  assert(dirp != NULL, "just checking");      // hotspot change
  if (dirp->handle == INVALID_HANDLE_VALUE) {
    return NULL;
  }

  strcpy(dirp->dirent.d_name, dirp->find_data.cFileName);

  if (!FindNextFile(dirp->handle, &dirp->find_data)) {
    if (GetLastError() == ERROR_INVALID_HANDLE) {
      errno = EBADF;
      return NULL;
    }
    FindClose(dirp->handle);
    dirp->handle = INVALID_HANDLE_VALUE;
  }

  return &dirp->dirent;
}

int os::closedir(DIR *dirp) {
  assert(dirp != NULL, "just checking");      // hotspot change
  if (dirp->handle != INVALID_HANDLE_VALUE) {
    if (!FindClose(dirp->handle)) {
      errno = EBADF;
      return -1;
    }
    dirp->handle = INVALID_HANDLE_VALUE;
  }
  free(dirp->path);
  free(dirp);
  return 0;
}

// This must be hard coded because it's the system's temporary
// directory not the java application's temp directory, ala java.io.tmpdir.
const char* os::get_temp_directory() {
  static char path_buf[MAX_PATH];
  if (GetTempPath(MAX_PATH, path_buf) > 0) {
    return path_buf;
  } else {
    path_buf[0] = '\0';
    return path_buf;
  }
}

// Needs to be in os specific directory because windows requires another
// header file <direct.h>
const char* os::get_current_directory(char *buf, size_t buflen) {
  int n = static_cast<int>(buflen);
  if (buflen > INT_MAX)  n = INT_MAX;
  return _getcwd(buf, n);
}

//-----------------------------------------------------------
// Helper functions for fatal error handler
#ifdef _WIN64
// Helper routine which returns true if address in
// within the NTDLL address space.
//
static bool _addr_in_ntdll(address addr) {
  HMODULE hmod;
  MODULEINFO minfo;

  hmod = GetModuleHandle("NTDLL.DLL");
  if (hmod == NULL) return false;
  if (!GetModuleInformation(GetCurrentProcess(), hmod,
                                          &minfo, sizeof(MODULEINFO))) {
    return false;
  }

  if ((addr >= minfo.lpBaseOfDll) &&
      (addr < (address)((uintptr_t)minfo.lpBaseOfDll + (uintptr_t)minfo.SizeOfImage))) {
    return true;
  } else {
    return false;
  }
}
#endif

struct _modinfo {
  address addr;
  char*   full_path;   // point to a char buffer
  int     buflen;      // size of the buffer
  address base_addr;
};

static int _locate_module_by_addr(const char * mod_fname, address base_addr,
                                  address top_address, void * param) {
  struct _modinfo *pmod = (struct _modinfo *)param;
  if (!pmod) return -1;

  if (base_addr   <= pmod->addr &&
      top_address > pmod->addr) {
    // if a buffer is provided, copy path name to the buffer
    if (pmod->full_path) {
      jio_snprintf(pmod->full_path, pmod->buflen, "%s", mod_fname);
    }
    pmod->base_addr = base_addr;
    return 1;
  }
  return 0;
}

bool os::dll_address_to_library_name(address addr, char* buf,
                                     int buflen, int* offset) {
  // buf is not optional, but offset is optional
  assert(buf != NULL, "sanity check");

// NOTE: the reason we don't use SymGetModuleInfo() is it doesn't always
//       return the full path to the DLL file, sometimes it returns path
//       to the corresponding PDB file (debug info); sometimes it only
//       returns partial path, which makes life painful.

  struct _modinfo mi;
  mi.addr      = addr;
  mi.full_path = buf;
  mi.buflen    = buflen;
  if (get_loaded_modules_info(_locate_module_by_addr, (void *)&mi)) {
    // buf already contains path name
    if (offset) *offset = addr - mi.base_addr;
    return true;
  }

  buf[0] = '\0';
  if (offset) *offset = -1;
  return false;
}

bool os::dll_address_to_function_name(address addr, char *buf,
                                      int buflen, int *offset,
                                      bool demangle) {
  // buf is not optional, but offset is optional
  assert(buf != NULL, "sanity check");

  if (Decoder::decode(addr, buf, buflen, offset, demangle)) {
    return true;
  }
  if (offset != NULL)  *offset  = -1;
  buf[0] = '\0';
  return false;
}

// save the start and end address of jvm.dll into param[0] and param[1]
static int _locate_jvm_dll(const char* mod_fname, address base_addr,
                           address top_address, void * param) {
  if (!param) return -1;

  if (base_addr   <= (address)_locate_jvm_dll &&
      top_address > (address)_locate_jvm_dll) {
    ((address*)param)[0] = base_addr;
    ((address*)param)[1] = top_address;
    return 1;
  }
  return 0;
}

address vm_lib_location[2];    // start and end address of jvm.dll

// check if addr is inside jvm.dll
bool os::address_is_in_vm(address addr) {
  if (!vm_lib_location[0] || !vm_lib_location[1]) {
    if (!get_loaded_modules_info(_locate_jvm_dll, (void *)vm_lib_location)) {
      assert(false"Can't find jvm module.");
      return false;
    }
  }

  return (vm_lib_location[0] <= addr) && (addr < vm_lib_location[1]);
}

// print module info; param is outputStream*
static int _print_module(const char* fname, address base_address,
                         address top_address, void* param) {
  if (!param) return -1;

  outputStream* st = (outputStream*)param;

  st->print(PTR_FORMAT " - " PTR_FORMAT " \t%s\n", base_address, top_address, fname);
  return 0;
}

// Loads .dll/.so and
// in case of error it checks if .dll/.so was built for the
// same architecture as Hotspot is running on
void * os::dll_load(const char *name, char *ebuf, int ebuflen) {
  log_info(os)("attempting shared library load of %s", name);

  void * result = LoadLibrary(name);
  if (result != NULL) {
    Events::log_dll_message(NULL, "Loaded shared library %s", name);
    // Recalculate pdb search path if a DLL was loaded successfully.
    SymbolEngine::recalc_search_path();
    log_info(os)("shared library load of %s was successful", name);
    return result;
  }
  DWORD errcode = GetLastError();
  // Read system error message into ebuf
  // It may or may not be overwritten below (in the for loop and just above)
  lasterror(ebuf, (size_t) ebuflen);
  ebuf[ebuflen - 1] = '\0';
  Events::log_dll_message(NULL, "Loading shared library %s failed, error code %lu"name, errcode);
  log_info(os)("shared library load of %s failed, error code %lu", name, errcode);

  if (errcode == ERROR_MOD_NOT_FOUND) {
    strncpy(ebuf, "Can't find dependent libraries", ebuflen - 1);
    ebuf[ebuflen - 1] = '\0';
    return NULL;
  }

  // Parsing dll below
  // If we can read dll-info and find that dll was built
  // for an architecture other than Hotspot is running in
  // - then print to buffer "DLL was built for a different architecture"
  // else call os::lasterror to obtain system error message
  int fd = ::open(name, O_RDONLY | O_BINARY, 0);
  if (fd < 0) {
    return NULL;
  }

  uint32_t signature_offset;
  uint16_t lib_arch = 0;
  bool failed_to_get_lib_arch =
    ( // Go to position 3c in the dll
     (os::seek_to_file_offset(fd, IMAGE_FILE_PTR_TO_SIGNATURE) < 0)
     ||
     // Read location of signature
     (sizeof(signature_offset) !=
     (::read(fd, (void*)&signature_offset, sizeof(signature_offset))))
     ||
     // Go to COFF File Header in dll
     // that is located after "signature" (4 bytes long)
     (os::seek_to_file_offset(fd,
     signature_offset + IMAGE_FILE_SIGNATURE_LENGTH) < 0)
     ||
     // Read field that contains code of architecture
     // that dll was built for
     (sizeof(lib_arch) != (::read(fd, (void*)&lib_arch, sizeof(lib_arch))))
    );

  ::close(fd);
  if (failed_to_get_lib_arch) {
    // file i/o error - report os::lasterror(...) msg
    return NULL;
  }

  typedef struct {
    uint16_t arch_code;
    char* arch_name;
  } arch_t;

  static const arch_t arch_array[] = {
    {IMAGE_FILE_MACHINE_I386,      (char*)"IA 32"},
    {IMAGE_FILE_MACHINE_AMD64,     (char*)"AMD 64"},
    {IMAGE_FILE_MACHINE_ARM64,     (char*)"ARM 64"}
  };
#if (defined _M_ARM64)
  static const uint16_t running_arch = IMAGE_FILE_MACHINE_ARM64;
#elif (defined _M_AMD64)
  static const uint16_t running_arch = IMAGE_FILE_MACHINE_AMD64;
#elif (defined _M_IX86)
  static const uint16_t running_arch = IMAGE_FILE_MACHINE_I386;
#else
  #error Method os::dll_load requires that one of following \
         is defined :_M_AMD64 or _M_IX86 or _M_ARM64
#endif


  // Obtain a string for printf operation
  // lib_arch_str shall contain string what platform this .dll was built for
  // running_arch_str shall string contain what platform Hotspot was built for
  char *running_arch_str = NULL, *lib_arch_str = NULL;
  for (unsigned int i = 0; i < ARRAY_SIZE(arch_array); i++) {
    if (lib_arch == arch_array[i].arch_code) {
      lib_arch_str = arch_array[i].arch_name;
    }
    if (running_arch == arch_array[i].arch_code) {
      running_arch_str = arch_array[i].arch_name;
    }
  }

  assert(running_arch_str,
         "Didn't find running architecture code in arch_array");

  // If the architecture is right
  // but some other error took place - report os::lasterror(...) msg
  if (lib_arch == running_arch) {
    return NULL;
  }

  if (lib_arch_str != NULL) {
    ::_snprintf(ebuf, ebuflen - 1,
                "Can't load %s-bit .dll on a %s-bit platform",
                lib_arch_str, running_arch_str);
  } else {
    // don't know what architecture this dll was build for
    ::_snprintf(ebuf, ebuflen - 1,
                "Can't load this .dll (machine code=0x%x) on a %s-bit platform",
                lib_arch, running_arch_str);
  }

  return NULL;
}

void os::print_dll_info(outputStream *st) {
  st->print_cr("Dynamic libraries:");
  get_loaded_modules_info(_print_module, (void *)st);
}

int os::get_loaded_modules_info(os::LoadedModulesCallbackFunc callback, void *param) {
  HANDLE   hProcess;

define MAX_NUM_MODULES 128
  HMODULE     modules[MAX_NUM_MODULES];
  static char filename[MAX_PATH];
  int         result = 0;

  int pid = os::current_process_id();
  hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
                         FALSE, pid);
  if (hProcess == NULL) return 0;

  DWORD size_needed;
  if (!EnumProcessModules(hProcess, modules, sizeof(modules), &size_needed)) {
    CloseHandle(hProcess);
    return 0;
  }

  // number of modules that are currently loaded
  int num_modules = size_needed / sizeof(HMODULE);

  for (int i = 0; i < MIN2(num_modules, MAX_NUM_MODULES); i++) {
    // Get Full pathname:
    if (!GetModuleFileNameEx(hProcess, modules[i], filename, sizeof(filename))) {
      filename[0] = '\0';
    }

    MODULEINFO modinfo;
    if (!GetModuleInformation(hProcess, modules[i], &modinfo, sizeof(modinfo))) {
      modinfo.lpBaseOfDll = NULL;
      modinfo.SizeOfImage = 0;
    }

    // Invoke callback function
    result = callback(filename, (address)modinfo.lpBaseOfDll,
                      (address)((u8)modinfo.lpBaseOfDll + (u8)modinfo.SizeOfImage), param);
    if (result) break;
  }

  CloseHandle(hProcess);
  return result;
}

bool os::get_host_name(char* buf, size_t buflen) {
  DWORD size = (DWORD)buflen;
  return (GetComputerNameEx(ComputerNameDnsHostname, buf, &size) == TRUE);
}

void os::get_summary_os_info(char* buf, size_t buflen) {
  stringStream sst(buf, buflen);
  os::win32::print_windows_version(&sst);
  // chop off newline character
  char* nl = strchr(buf, '\n');
  if (nl != NULL) *nl = '\0';
}

int os::vsnprintf(char* buf, size_t len, const char* fmt, va_list args) {
  // Starting with Visual Studio 2015, vsnprint is C99 compliant.
  ALLOW_C_FUNCTION(::vsnprintf, int result = ::vsnprintf(buf, len, fmt, args);)
  // If an encoding error occurred (result < 0) then it's not clear
  // whether the buffer is NUL terminated, so ensure it is.
  if ((result < 0) && (len > 0)) {
    buf[len - 1] = '\0';
  }
  return result;
}

static inline time_t get_mtime(const char* filename) {
  struct stat st;
  int ret = os::stat(filename, &st);
  assert(ret == 0, "failed to stat() file '%s': %s", filename, os::strerror(errno));
  return st.st_mtime;
}

int os::compare_file_modified_times(const char* file1, const char* file2) {
  time_t t1 = get_mtime(file1);
  time_t t2 = get_mtime(file2);
  return t1 - t2;
}

void os::print_os_info_brief(outputStream* st) {
  os::print_os_info(st);
}

void os::win32::print_uptime_info(outputStream* st) {
  unsigned long long ticks = GetTickCount64();
  os::print_dhm(st, "OS uptime:", ticks/1000);
}

void os::print_os_info(outputStream* st) {
#ifdef ASSERT
  char buffer[1024];
  st->print("HostName: ");
  if (get_host_name(buffer, sizeof(buffer))) {
    st->print_cr(buffer);
  } else {
    st->print_cr("N/A");
  }
#endif
  st->print_cr("OS:");
  os::win32::print_windows_version(st);

  os::win32::print_uptime_info(st);

  VM_Version::print_platform_virtualization_info(st);
}

void os::win32::print_windows_version(outputStream* st) {
  VS_FIXEDFILEINFO *file_info;
  TCHAR kernel32_path[MAX_PATH];
  UINT len, ret;

  bool is_workstation = !IsWindowsServer();

  // Get the full path to \Windows\System32\kernel32.dll and use that for
  // determining what version of Windows we're running on.
  len = MAX_PATH - (UINT)strlen("\\kernel32.dll") - 1;
  ret = GetSystemDirectory(kernel32_path, len);
  if (ret == 0 || ret > len) {
    st->print_cr("Call to GetSystemDirectory failed");
    return;
  }
  strncat(kernel32_path, "\\kernel32.dll", MAX_PATH - ret);

  DWORD version_size = GetFileVersionInfoSize(kernel32_path, NULL);
  if (version_size == 0) {
    st->print_cr("Call to GetFileVersionInfoSize failed");
    return;
  }

  LPTSTR version_info = (LPTSTR)os::malloc(version_size, mtInternal);
  if (version_info == NULL) {
    st->print_cr("Failed to allocate version_info");
    return;
  }

  if (!GetFileVersionInfo(kernel32_path, NULL, version_size, version_info)) {
    os::free(version_info);
    st->print_cr("Call to GetFileVersionInfo failed");
    return;
  }

  if (!VerQueryValue(version_info, TEXT("\\"), (LPVOID*)&file_info, &len)) {
    os::free(version_info);
    st->print_cr("Call to VerQueryValue failed");
    return;
  }

  int major_version = HIWORD(file_info->dwProductVersionMS);
  int minor_version = LOWORD(file_info->dwProductVersionMS);
  int build_number = HIWORD(file_info->dwProductVersionLS);
  int build_minor = LOWORD(file_info->dwProductVersionLS);
  int os_vers = major_version * 1000 + minor_version;
  os::free(version_info);

  st->print(" Windows ");
  switch (os_vers) {

  case 6000:
    if (is_workstation) {
      st->print("Vista");
    } else {
      st->print("Server 2008");
    }
    break;

  case 6001:
    if (is_workstation) {
      st->print("7");
    } else {
      st->print("Server 2008 R2");
    }
    break;

  case 6002:
    if (is_workstation) {
      st->print("8");
    } else {
      st->print("Server 2012");
    }
    break;

  case 6003:
    if (is_workstation) {
      st->print("8.1");
    } else {
      st->print("Server 2012 R2");
    }
    break;

  case 10000:
    if (is_workstation) {
      if (build_number >= 22000) {
        st->print("11");
      } else {
        st->print("10");
      }
    } else {
      // distinguish Windows Server by build number
      // - 2016 GA 10/2016 build: 14393
      // - 2019 GA 11/2018 build: 17763
      // - 2022 GA 08/2021 build: 20348
      if (build_number > 20347) {
        st->print("Server 2022");
      } else if (build_number > 17762) {
        st->print("Server 2019");
      } else {
        st->print("Server 2016");
      }
    }
    break;

  default:
    // Unrecognized windows, print out its major and minor versions
    st->print("%d.%d", major_version, minor_version);
    break;
  }

  // Retrieve SYSTEM_INFO from GetNativeSystemInfo call so that we could
  // find out whether we are running on 64 bit processor or not
  SYSTEM_INFO si;
  ZeroMemory(&si, sizeof(SYSTEM_INFO));
  GetNativeSystemInfo(&si);
  if ((si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) ||
      (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_ARM64)) {
    st->print(" , 64 bit");
  }

  st->print(" Build %d", build_number);
  st->print(" (%d.%d.%d.%d)", major_version, minor_version, build_number, build_minor);
  st->cr();
}

void os::pd_print_cpu_info(outputStream* st, char* buf, size_t buflen) {
  // Nothing to do for now.
}

void os::get_summary_cpu_info(char* buf, size_t buflen) {
  HKEY key;
  DWORD status = RegOpenKey(HKEY_LOCAL_MACHINE,
               "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", &key);
  if (status == ERROR_SUCCESS) {
    DWORD size = (DWORD)buflen;
    status = RegQueryValueEx(key, "ProcessorNameString", NULL, NULL, (byte*)buf, &size);
    if (status != ERROR_SUCCESS) {
        strncpy(buf, "## __CPU__", buflen);
    }
    RegCloseKey(key);
  } else {
    // Put generic cpu info to return
    strncpy(buf, "## __CPU__", buflen);
  }
}

void os::print_memory_info(outputStream* st) {
  st->print("Memory:");
  st->print(" %dk page", os::vm_page_size()>>10);

  // Use GlobalMemoryStatusEx() because GlobalMemoryStatus() may return incorrect
  // value if total memory is larger than 4GB
  MEMORYSTATUSEX ms;
  ms.dwLength = sizeof(ms);
  int r1 = GlobalMemoryStatusEx(&ms);

  if (r1 != 0) {
    st->print(", system-wide physical " INT64_FORMAT "M ",
             (int64_t) ms.ullTotalPhys >> 20);
    st->print("(" INT64_FORMAT "M free)\n", (int64_t) ms.ullAvailPhys >> 20);

    st->print("TotalPageFile size " INT64_FORMAT "M ",
             (int64_t) ms.ullTotalPageFile >> 20);
    st->print("(AvailPageFile size " INT64_FORMAT "M)",
             (int64_t) ms.ullAvailPageFile >> 20);

    // on 32bit Total/AvailVirtual are interesting (show us how close we get to 2-4 GB per process borders)
#if defined(_M_IX86)
    st->print(", user-mode portion of virtual address-space " INT64_FORMAT "M ",
             (int64_t) ms.ullTotalVirtual >> 20);
    st->print("(" INT64_FORMAT "M free)", (int64_t) ms.ullAvailVirtual >> 20);
#endif
  } else {
    st->print(", GlobalMemoryStatusEx did not succeed so we miss some memory values.");
  }

  // extended memory statistics for a process
  PROCESS_MEMORY_COUNTERS_EX pmex;
  ZeroMemory(&pmex, sizeof(PROCESS_MEMORY_COUNTERS_EX));
  pmex.cb = sizeof(pmex);
  int r2 = GetProcessMemoryInfo(GetCurrentProcess(), (PROCESS_MEMORY_COUNTERS*) &pmex, sizeof(pmex));

  if (r2 != 0) {
    st->print("\ncurrent process WorkingSet (physical memory assigned to process): " INT64_FORMAT "M, ",
             (int64_t) pmex.WorkingSetSize >> 20);
    st->print("peak: " INT64_FORMAT "M\n", (int64_t) pmex.PeakWorkingSetSize >> 20);

    st->print("current process commit charge (\"private bytes\"): " INT64_FORMAT "M, ",
             (int64_t) pmex.PrivateUsage >> 20);
    st->print("peak: " INT64_FORMAT "M", (int64_t) pmex.PeakPagefileUsage >> 20);
  } else {
    st->print("\nGetProcessMemoryInfo did not succeed so we miss some memory values.");
  }

  st->cr();
}

bool os::signal_sent_by_kill(const void* siginfo) {
  // TODO: Is this possible?
  return false;
}

void os::print_siginfo(outputStream *st, const void* siginfo) {
  const EXCEPTION_RECORD* const er = (EXCEPTION_RECORD*)siginfo;
  st->print("siginfo:");

  char tmp[64];
  if (os::exception_name(er->ExceptionCode, tmp, sizeof(tmp)) == NULL) {
    strcpy(tmp, "EXCEPTION_??");
  }
  st->print(" %s (0x%x)", tmp, er->ExceptionCode);

  if ((er->ExceptionCode == EXCEPTION_ACCESS_VIOLATION ||
       er->ExceptionCode == EXCEPTION_IN_PAGE_ERROR) &&
       er->NumberParameters >= 2) {
    switch (er->ExceptionInformation[0]) {
    case 0: st->print(", reading address"); break;
    case 1: st->print(", writing address"); break;
    case 8: st->print(", data execution prevention violation at address"); break;
    default: st->print(", ExceptionInformation=" INTPTR_FORMAT,
                       er->ExceptionInformation[0]);
    }
    st->print(" " INTPTR_FORMAT, er->ExceptionInformation[1]);
  } else {
    int num = er->NumberParameters;
    if (num > 0) {
      st->print(", ExceptionInformation=");
      for (int i = 0; i < num; i++) {
        st->print(INTPTR_FORMAT " ", er->ExceptionInformation[i]);
      }
    }
  }
  st->cr();
}

bool os::signal_thread(Thread* thread, int sig, const char* reason) {
  // TODO: Can we kill thread?
  return false;
}

void os::print_signal_handlers(outputStream* st, char* buf, size_t buflen) {
  // do nothing
}

static char saved_jvm_path[MAX_PATH] = {0};

// Find the full path to the current module, jvm.dll
void os::jvm_path(char *buf, jint buflen) {
  // Error checking.
  if (buflen < MAX_PATH) {
    assert(false"must use a large-enough buffer");
    buf[0] = '\0';
    return;
  }
  // Lazy resolve the path to current module.
  if (saved_jvm_path[0] != 0) {
    strcpy(buf, saved_jvm_path);
    return;
  }

  buf[0] = '\0';
  if (Arguments::sun_java_launcher_is_altjvm()) {
    // Support for the java launcher's '-XXaltjvm=<path>' option. Check
    // for a JAVA_HOME environment variable and fix up the path so it
    // looks like jvm.dll is installed there (append a fake suffix
    // hotspot/jvm.dll).
    char* java_home_var = ::getenv("JAVA_HOME");
    if (java_home_var != NULL && java_home_var[0] != 0 &&
        strlen(java_home_var) < (size_t)buflen) {
      strncpy(buf, java_home_var, buflen);

      // determine if this is a legacy image or modules image
      // modules image doesn't have "jre" subdirectory
      size_t len = strlen(buf);
      char* jrebin_p = buf + len;
      jio_snprintf(jrebin_p, buflen-len, "\\jre\\bin\\");
      if (0 != _access(buf, 0)) {
        jio_snprintf(jrebin_p, buflen-len, "\\bin\\");
      }
      len = strlen(buf);
--> --------------------

--> maximum size reached

--> --------------------

¤ Dauer der Verarbeitung: 1.504 Sekunden  (vorverarbeitet)  ¤





Druckansicht
unsichere Verbindung
Druckansicht
sprechenden Kalenders

Eigene Datei ansehen




Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.


Bemerkung:

Die farbliche Syntaxdarstellung ist noch experimentell.


Bot Zugriff