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