From 142b36c840a51b4e3b73ab893d9f7ed96d831c22 Mon Sep 17 00:00:00 2001 From: Saint Wesonga Date: Thu, 9 Nov 2023 14:56:33 -0700 Subject: [PATCH 01/32] Count processors across all processor groups Windows 11 and Windows Server 2022 make processes and their threads span all processor groups. The correct number of processors can be safely used on these operating systems. --- src/hotspot/os/windows/os_windows.cpp | 140 +++++++++++++++++++++++++- src/hotspot/os/windows/os_windows.hpp | 6 ++ 2 files changed, 145 insertions(+), 1 deletion(-) diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index 223bc0bd13514..98df06752b59c 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -3982,14 +3982,152 @@ bool os::win32::_is_windows_server = false; // including the latest one (as of this writing - Windows Server 2012 R2) bool os::win32::_has_exit_bug = true; +int os::win32::_major_version = 0; +int os::win32::_minor_version = 0; +int os::win32::_build_number = 0; + +void os::win32::compute_windows_version() { + LPWSTR kernel32_path = NULL; + LPWSTR version_info = NULL; + DWORD version_size = 0; + + // Get the full path to \Windows\System32\kernel32.dll and use that for + // determining what version of Windows we're running on. This is the same + // approach used in src/java.base/windows/native/libjava/java_props_md.c + UINT buffer_size = GetSystemDirectoryW(NULL, 0); + if (buffer_size == 0) { + warning("GetSystemDirectoryW() failed: GetLastError->%ld.", GetLastError()); + return; + } + + UINT filename_chars = (UINT)strlen("\\kernel32.dll"); + + // buffer_size includes the terminating null character + UINT size = (buffer_size + filename_chars) * sizeof(WCHAR); + kernel32_path = (LPWSTR)os::malloc(size, mtInternal); + if (kernel32_path == NULL) { + warning("os::malloc() failed to allocate %ld bytes for the kernel32.dll path", size); + return; + } + + UINT non_null_chars_written = GetSystemDirectoryW(kernel32_path, size); + if (non_null_chars_written == 0) { + warning("GetSystemDirectoryW() failed: GetLastError->%ld.", GetLastError()); + goto free_mem; + } + + wcsncat(kernel32_path, L"\\kernel32.dll", filename_chars); + + version_size = GetFileVersionInfoSizeW(kernel32_path, NULL); + if (version_size == 0) { + warning("GetFileVersionInfoSizeW() failed: GetLastError->%ld.", GetLastError()); + goto free_mem; + } + + version_info = (LPWSTR)os::malloc(version_size, mtInternal); + if (version_info == NULL) { + warning("os::malloc() failed to allocate %ld bytes for GetFileVersionInfoW buffer", version_size); + goto free_mem; + } + + if (!GetFileVersionInfoW(kernel32_path, 0, version_size, version_info)) { + warning("GetFileVersionInfoW() failed: GetLastError->%ld.", GetLastError()); + goto free_mem; + } + + VS_FIXEDFILEINFO *file_info; + if (!VerQueryValueW(version_info, L"\\", (LPVOID*)&file_info, &size)) { + warning("VerQueryValueW() failed. Cannot determine Windows version."); + goto free_mem; + } + + _major_version = HIWORD(file_info->dwProductVersionMS); + _minor_version = LOWORD(file_info->dwProductVersionMS); + _build_number = HIWORD(file_info->dwProductVersionLS); + +free_mem: + os::free(version_info); + os::free(kernel32_path); +} + +bool os::win32::schedules_all_processor_groups() { + // Starting with Windows 11 and Windows Server 2022 the OS has changed to + // make processes and their threads span all processors in the system, + // across all processor groups, by default. Therefore, this function needs + // to detect Windows 11 or Windows Server 2022. See + // https://learn.microsoft.com/en-us/windows/win32/procthread/processor-groups#behavior-starting-with-windows-11-and-windows-server-2022 + + if (IsWindows10OrGreater()) { + if (IsWindowsServer()) { + // Windows Server 2022 starts at build 20348.169 as per + // https://learn.microsoft.com/en-us/windows/release-health/release-information + return _build_number >= 20348; + } else { + // Windows 11 starts at build 22000 (Version 21H2) as per + // https://learn.microsoft.com/en-us/windows/release-health/windows11-release-information + return _build_number >= 22000; + } + } + + return false; +} + void os::win32::initialize_system_info() { + compute_windows_version(); + SYSTEM_INFO si; GetSystemInfo(&si); OSInfo::set_vm_page_size(si.dwPageSize); OSInfo::set_vm_allocation_granularity(si.dwAllocationGranularity); _processor_type = si.dwProcessorType; _processor_level = si.wProcessorLevel; - set_processor_count(si.dwNumberOfProcessors); + + DWORD logicalProcessors = 0; + typedef BOOL(WINAPI* LPFN_GET_LOGICAL_PROCESSOR_INFORMATION_EX)( + LOGICAL_PROCESSOR_RELATIONSHIP, PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, PDWORD); + + LPFN_GET_LOGICAL_PROCESSOR_INFORMATION_EX glpiex; + + glpiex = (LPFN_GET_LOGICAL_PROCESSOR_INFORMATION_EX)GetProcAddress( + GetModuleHandle(TEXT("kernel32")), + "GetLogicalProcessorInformationEx"); + + if (glpiex != NULL && schedules_all_processor_groups()) { + LOGICAL_PROCESSOR_RELATIONSHIP relationshipType = RelationGroup; + PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX pSytemLogicalProcessorInfo = NULL; + DWORD returnedLength = 0; + + // https://learn.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getlogicalprocessorinformationex + if (!glpiex(relationshipType, pSytemLogicalProcessorInfo, &returnedLength)) { + DWORD lastError = GetLastError(); + + if (lastError == ERROR_INSUFFICIENT_BUFFER) { + pSytemLogicalProcessorInfo = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX)os::malloc(returnedLength, mtInternal); + + if (NULL == pSytemLogicalProcessorInfo) { + warning("os::malloc() failed to allocate %ld bytes for GetLogicalProcessorInformationEx buffer", returnedLength); + } else if (!glpiex(relationshipType, pSytemLogicalProcessorInfo, &returnedLength)) { + warning("GetLogicalProcessorInformationEx() failed: GetLastError->%ld.", GetLastError()); + } else { + DWORD processorGroups = pSytemLogicalProcessorInfo->Group.ActiveGroupCount; + + for (DWORD i = 0; i < processorGroups; i++) { + PROCESSOR_GROUP_INFO groupInfo = pSytemLogicalProcessorInfo->Group.GroupInfo[i]; + logicalProcessors += groupInfo.ActiveProcessorCount; + } + + assert(logicalProcessors > 0, "Must find at least 1 logical processor"); + } + + os::free(pSytemLogicalProcessorInfo); + } + else { + warning("GetLogicalProcessorInformationEx() failed: GetLastError->%ld.", lastError); + } + } + } + + set_processor_count(logicalProcessors > 0 ? logicalProcessors : si.dwNumberOfProcessors); MEMORYSTATUSEX ms; ms.dwLength = sizeof(ms); diff --git a/src/hotspot/os/windows/os_windows.hpp b/src/hotspot/os/windows/os_windows.hpp index 5bf402069f37f..a3d389a439971 100644 --- a/src/hotspot/os/windows/os_windows.hpp +++ b/src/hotspot/os/windows/os_windows.hpp @@ -44,6 +44,10 @@ class os::win32 { static bool _is_windows_server; static bool _has_exit_bug; + static int _major_version; + static int _minor_version; + static int _build_number; + static void print_windows_version(outputStream* st); static void print_uptime_info(outputStream* st); @@ -56,6 +60,8 @@ class os::win32 { // Windows-specific interface: static void initialize_system_info(); static void setmode_streams(); + static void compute_windows_version(); + static bool schedules_all_processor_groups(); // Processor info as provided by NT static int processor_type() { return _processor_type; } From e7b5ccae5d23852f2b689f3f91d77ee88bd5367a Mon Sep 17 00:00:00 2001 From: Saint Wesonga Date: Tue, 14 Nov 2023 14:13:01 -0700 Subject: [PATCH 02/32] Use major version check that works on Windows Server --- src/hotspot/os/windows/os_windows.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index 98df06752b59c..048c77f9d86f4 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -4057,7 +4057,7 @@ bool os::win32::schedules_all_processor_groups() { // to detect Windows 11 or Windows Server 2022. See // https://learn.microsoft.com/en-us/windows/win32/procthread/processor-groups#behavior-starting-with-windows-11-and-windows-server-2022 - if (IsWindows10OrGreater()) { + if (_major_version >= 10) { if (IsWindowsServer()) { // Windows Server 2022 starts at build 20348.169 as per // https://learn.microsoft.com/en-us/windows/release-health/release-information From 044b6ea647dbcc911ab3d71f687deeee19e1260f Mon Sep 17 00:00:00 2001 From: Saint Wesonga Date: Thu, 30 Nov 2023 14:27:50 -0700 Subject: [PATCH 03/32] Move processor counting logic into separate function --- src/hotspot/os/windows/os_windows.cpp | 31 +++++++++++++++++---------- src/hotspot/os/windows/os_windows.hpp | 1 + 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index 048c77f9d86f4..3d81f6914393d 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -4072,16 +4072,7 @@ bool os::win32::schedules_all_processor_groups() { return false; } -void os::win32::initialize_system_info() { - compute_windows_version(); - - SYSTEM_INFO si; - GetSystemInfo(&si); - OSInfo::set_vm_page_size(si.dwPageSize); - OSInfo::set_vm_allocation_granularity(si.dwAllocationGranularity); - _processor_type = si.dwProcessorType; - _processor_level = si.wProcessorLevel; - +DWORD os::win32::get_logical_processor_count() { DWORD logicalProcessors = 0; typedef BOOL(WINAPI* LPFN_GET_LOGICAL_PROCESSOR_INFORMATION_EX)( LOGICAL_PROCESSOR_RELATIONSHIP, PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, PDWORD); @@ -4092,7 +4083,7 @@ void os::win32::initialize_system_info() { GetModuleHandle(TEXT("kernel32")), "GetLogicalProcessorInformationEx"); - if (glpiex != NULL && schedules_all_processor_groups()) { + if (glpiex != NULL) { LOGICAL_PROCESSOR_RELATIONSHIP relationshipType = RelationGroup; PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX pSytemLogicalProcessorInfo = NULL; DWORD returnedLength = 0; @@ -4127,6 +4118,24 @@ void os::win32::initialize_system_info() { } } + return logicalProcessors; +} + +void os::win32::initialize_system_info() { + compute_windows_version(); + + SYSTEM_INFO si; + GetSystemInfo(&si); + OSInfo::set_vm_page_size(si.dwPageSize); + OSInfo::set_vm_allocation_granularity(si.dwAllocationGranularity); + _processor_type = si.dwProcessorType; + _processor_level = si.wProcessorLevel; + + DWORD logicalProcessors = 0; + if (schedules_all_processor_groups()) { + logicalProcessors = get_logical_processor_count(); + } + set_processor_count(logicalProcessors > 0 ? logicalProcessors : si.dwNumberOfProcessors); MEMORYSTATUSEX ms; diff --git a/src/hotspot/os/windows/os_windows.hpp b/src/hotspot/os/windows/os_windows.hpp index a3d389a439971..750a6c0165a0e 100644 --- a/src/hotspot/os/windows/os_windows.hpp +++ b/src/hotspot/os/windows/os_windows.hpp @@ -62,6 +62,7 @@ class os::win32 { static void setmode_streams(); static void compute_windows_version(); static bool schedules_all_processor_groups(); + static DWORD get_logical_processor_count(); // Processor info as provided by NT static int processor_type() { return _processor_type; } From eaef0836b993eb8d6a045924d8dd8078248a889a Mon Sep 17 00:00:00 2001 From: Saint Wesonga Date: Mon, 4 Dec 2023 12:12:39 -0700 Subject: [PATCH 04/32] Move OS detection code into separate functions --- src/hotspot/os/windows/os_windows.cpp | 34 +++++++++++++++++---------- src/hotspot/os/windows/os_windows.hpp | 2 ++ 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index 3d81f6914393d..073e627ad6f16 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -3987,6 +3987,10 @@ int os::win32::_minor_version = 0; int os::win32::_build_number = 0; void os::win32::compute_windows_version() { + if (_major_version > 0) { + return; // nothing to do if already the version has already been set + } + LPWSTR kernel32_path = NULL; LPWSTR version_info = NULL; DWORD version_size = 0; @@ -4050,6 +4054,22 @@ void os::win32::compute_windows_version() { os::free(kernel32_path); } +bool os::win32::is_windows_11_or_greater() { + compute_windows_version(); + + // Windows 11 starts at build 22000 (Version 21H2) as per + // https://learn.microsoft.com/en-us/windows/release-health/windows11-release-information + return (_major_version >= 10 && _build_number >= 22000 && !IsWindowsServer()); +} + +bool os::win32::is_windows_server_2022_or_greater() { + compute_windows_version(); + + // Windows Server 2022 starts at build 20348.169 as per + // https://learn.microsoft.com/en-us/windows/release-health/release-information + return (_major_version >= 10 && _build_number >= 20348 && IsWindowsServer()); +} + bool os::win32::schedules_all_processor_groups() { // Starting with Windows 11 and Windows Server 2022 the OS has changed to // make processes and their threads span all processors in the system, @@ -4057,19 +4077,7 @@ bool os::win32::schedules_all_processor_groups() { // to detect Windows 11 or Windows Server 2022. See // https://learn.microsoft.com/en-us/windows/win32/procthread/processor-groups#behavior-starting-with-windows-11-and-windows-server-2022 - if (_major_version >= 10) { - if (IsWindowsServer()) { - // Windows Server 2022 starts at build 20348.169 as per - // https://learn.microsoft.com/en-us/windows/release-health/release-information - return _build_number >= 20348; - } else { - // Windows 11 starts at build 22000 (Version 21H2) as per - // https://learn.microsoft.com/en-us/windows/release-health/windows11-release-information - return _build_number >= 22000; - } - } - - return false; + return is_windows_11_or_greater() || is_windows_server_2022_or_greater(); } DWORD os::win32::get_logical_processor_count() { diff --git a/src/hotspot/os/windows/os_windows.hpp b/src/hotspot/os/windows/os_windows.hpp index 750a6c0165a0e..e59eb6fad103c 100644 --- a/src/hotspot/os/windows/os_windows.hpp +++ b/src/hotspot/os/windows/os_windows.hpp @@ -61,6 +61,8 @@ class os::win32 { static void initialize_system_info(); static void setmode_streams(); static void compute_windows_version(); + static bool is_windows_11_or_greater(); + static bool is_windows_server_2022_or_greater(); static bool schedules_all_processor_groups(); static DWORD get_logical_processor_count(); From 63211fc5ad527d03718b89ebeff7678449dc03cb Mon Sep 17 00:00:00 2001 From: Saint Wesonga Date: Mon, 4 Dec 2023 23:52:22 -0700 Subject: [PATCH 05/32] Remove unnecessary function --- src/hotspot/os/windows/os_windows.cpp | 19 ++++++++----------- src/hotspot/os/windows/os_windows.hpp | 1 - 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index 073e627ad6f16..78eb6d5020f52 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -4070,16 +4070,6 @@ bool os::win32::is_windows_server_2022_or_greater() { return (_major_version >= 10 && _build_number >= 20348 && IsWindowsServer()); } -bool os::win32::schedules_all_processor_groups() { - // Starting with Windows 11 and Windows Server 2022 the OS has changed to - // make processes and their threads span all processors in the system, - // across all processor groups, by default. Therefore, this function needs - // to detect Windows 11 or Windows Server 2022. See - // https://learn.microsoft.com/en-us/windows/win32/procthread/processor-groups#behavior-starting-with-windows-11-and-windows-server-2022 - - return is_windows_11_or_greater() || is_windows_server_2022_or_greater(); -} - DWORD os::win32::get_logical_processor_count() { DWORD logicalProcessors = 0; typedef BOOL(WINAPI* LPFN_GET_LOGICAL_PROCESSOR_INFORMATION_EX)( @@ -4139,8 +4129,15 @@ void os::win32::initialize_system_info() { _processor_type = si.dwProcessorType; _processor_level = si.wProcessorLevel; + // Starting with Windows 11 and Windows Server 2022 the OS has changed to + // make processes and their threads span all processors in the system, + // across all processor groups, by default. Therefore, this function needs + // to detect Windows 11 or Windows Server 2022. See + // https://learn.microsoft.com/en-us/windows/win32/procthread/processor-groups#behavior-starting-with-windows-11-and-windows-server-2022 + bool schedules_all_processor_groups = is_windows_11_or_greater() || is_windows_server_2022_or_greater(); + DWORD logicalProcessors = 0; - if (schedules_all_processor_groups()) { + if (schedules_all_processor_groups) { logicalProcessors = get_logical_processor_count(); } diff --git a/src/hotspot/os/windows/os_windows.hpp b/src/hotspot/os/windows/os_windows.hpp index e59eb6fad103c..cc657dd3644cb 100644 --- a/src/hotspot/os/windows/os_windows.hpp +++ b/src/hotspot/os/windows/os_windows.hpp @@ -63,7 +63,6 @@ class os::win32 { static void compute_windows_version(); static bool is_windows_11_or_greater(); static bool is_windows_server_2022_or_greater(); - static bool schedules_all_processor_groups(); static DWORD get_logical_processor_count(); // Processor info as provided by NT From 3871382a2c8daa395d392befde3f468df4308bd5 Mon Sep 17 00:00:00 2001 From: Saint Wesonga Date: Tue, 5 Dec 2023 11:07:47 -0700 Subject: [PATCH 06/32] Respect processor affinity set in a job object --- src/hotspot/os/windows/os_windows.cpp | 106 +++++++++++++++++++------- src/hotspot/os/windows/os_windows.hpp | 2 + 2 files changed, 81 insertions(+), 27 deletions(-) diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index 78eb6d5020f52..e3bfb5db7258d 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -867,21 +867,7 @@ int os::active_processor_count() { 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; - } + return processor_count(); } uint os::processor_id() { @@ -4070,6 +4056,83 @@ bool os::win32::is_windows_server_2022_or_greater() { return (_major_version >= 10 && _build_number >= 20348 && IsWindowsServer()); } +int os::win32::count_set_bits(ULONG64 argument) { + int bitcount = 0; + while (argument != 0) { + argument &= (argument-1); + bitcount++; + } + return bitcount; +} + +DWORD os::win32::get_available_logical_processors() { + DWORD logical_processors = 0; + + // Get the number of available logical processors from the associated job object + LPVOID lpJobObjectInformation = NULL; + DWORD cbJobObjectInformationLength = 0; + + bool is_in_windows_job = false; // TODO: test other jobs with other JobObjectInformationClass values + if (!QueryInformationJobObject(NULL, JobObjectGroupInformationEx, NULL, 0, &cbJobObjectInformationLength)) { + DWORD last_error = GetLastError(); + if (last_error == ERROR_INSUFFICIENT_BUFFER) { + DWORD group_count = cbJobObjectInformationLength / sizeof(GROUP_AFFINITY); + + lpJobObjectInformation = os::malloc(cbJobObjectInformationLength, mtInternal); + if (lpJobObjectInformation != NULL) { + if (QueryInformationJobObject(NULL, JobObjectGroupInformationEx, lpJobObjectInformation, cbJobObjectInformationLength, &cbJobObjectInformationLength)) { + is_in_windows_job = true; + group_count = cbJobObjectInformationLength / sizeof(GROUP_AFFINITY); + + for (DWORD i = 0; i < group_count; i++) { + KAFFINITY group_affinity = ((GROUP_AFFINITY*)lpJobObjectInformation)[i].Mask; + logical_processors += count_set_bits(group_affinity); + } + } else { + warning("QueryInformationJobObject() failed: GetLastError->%ld.", GetLastError()); + } + + os::free(lpJobObjectInformation); + } else { + warning("os::malloc() failed to allocate %ld bytes for QueryInformationJobObject", lpJobObjectInformation); + } + } + } + + if (is_in_windows_job) { + assert(logical_processors > 0, "Must find at least 1 logical processor"); + return logical_processors; + } + + SYSTEM_INFO si; + GetSystemInfo(&si); + + // If there is no associated job object, get the number of available logical processors from the process affinity + DWORD_PTR lpProcessAffinityMask = 0; + DWORD_PTR lpSystemAffinityMask = 0; + if (GetProcessAffinityMask(GetCurrentProcess(), &lpProcessAffinityMask, &lpSystemAffinityMask)) { + logical_processors = count_set_bits(lpProcessAffinityMask); + + if (logical_processors != si.dwNumberOfProcessors) { + // Respect the custom processor affinity since it is not equal to all processors in the current (main) processor group + return logical_processors; + } + } else { + warning("GetProcessAffinityMask() failed: GetLastError->%ld.", GetLastError()); + } + + // Starting with Windows 11 and Windows Server 2022 the OS has changed to + // make processes and their threads span all processors in the system, + // across all processor groups, by default. Therefore, this function needs + // to detect Windows 11 or Windows Server 2022. See + // https://learn.microsoft.com/en-us/windows/win32/procthread/processor-groups#behavior-starting-with-windows-11-and-windows-server-2022 + if (is_windows_11_or_greater() || is_windows_server_2022_or_greater()) { + logical_processors = get_logical_processor_count(); + } + + return logical_processors == 0 ? si.dwNumberOfProcessors : logical_processors; +} + DWORD os::win32::get_logical_processor_count() { DWORD logicalProcessors = 0; typedef BOOL(WINAPI* LPFN_GET_LOGICAL_PROCESSOR_INFORMATION_EX)( @@ -4129,18 +4192,7 @@ void os::win32::initialize_system_info() { _processor_type = si.dwProcessorType; _processor_level = si.wProcessorLevel; - // Starting with Windows 11 and Windows Server 2022 the OS has changed to - // make processes and their threads span all processors in the system, - // across all processor groups, by default. Therefore, this function needs - // to detect Windows 11 or Windows Server 2022. See - // https://learn.microsoft.com/en-us/windows/win32/procthread/processor-groups#behavior-starting-with-windows-11-and-windows-server-2022 - bool schedules_all_processor_groups = is_windows_11_or_greater() || is_windows_server_2022_or_greater(); - - DWORD logicalProcessors = 0; - if (schedules_all_processor_groups) { - logicalProcessors = get_logical_processor_count(); - } - + DWORD logicalProcessors = get_available_logical_processors(); set_processor_count(logicalProcessors > 0 ? logicalProcessors : si.dwNumberOfProcessors); MEMORYSTATUSEX ms; diff --git a/src/hotspot/os/windows/os_windows.hpp b/src/hotspot/os/windows/os_windows.hpp index cc657dd3644cb..14973ae3c498d 100644 --- a/src/hotspot/os/windows/os_windows.hpp +++ b/src/hotspot/os/windows/os_windows.hpp @@ -63,6 +63,8 @@ class os::win32 { static void compute_windows_version(); static bool is_windows_11_or_greater(); static bool is_windows_server_2022_or_greater(); + static int count_set_bits(ULONG64 argument); + static DWORD get_available_logical_processors(); static DWORD get_logical_processor_count(); // Processor info as provided by NT From f9560ecf6ef8449f4a1dcda82f0bbb34140698c8 Mon Sep 17 00:00:00 2001 From: Saint Wesonga Date: Tue, 5 Dec 2023 17:24:42 -0700 Subject: [PATCH 07/32] Remove version detection code duplication --- src/hotspot/os/windows/os_windows.cpp | 49 ++++----------------------- src/hotspot/os/windows/os_windows.hpp | 17 ++++++++++ 2 files changed, 23 insertions(+), 43 deletions(-) diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index e3bfb5db7258d..bc87b66c65758 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -1756,52 +1756,13 @@ void os::print_os_info(outputStream* 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, nullptr); - if (version_size == 0) { - st->print_cr("Call to GetFileVersionInfoSize failed"); - return; - } - - LPTSTR version_info = (LPTSTR)os::malloc(version_size, mtInternal); - if (version_info == nullptr) { - st->print_cr("Failed to allocate version_info"); - return; - } - - if (!GetFileVersionInfo(kernel32_path, 0, 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 major_version = windows_major_version(); + int minor_version = windows_minor_version(); + int build_number = windows_build_number(); + int build_minor = windows_build_minor(); int os_vers = major_version * 1000 + minor_version; - os::free(version_info); st->print(" Windows "); switch (os_vers) { @@ -3971,6 +3932,7 @@ bool os::win32::_has_exit_bug = true; int os::win32::_major_version = 0; int os::win32::_minor_version = 0; int os::win32::_build_number = 0; +int os::win32::_build_minor = 0; void os::win32::compute_windows_version() { if (_major_version > 0) { @@ -4034,6 +3996,7 @@ void os::win32::compute_windows_version() { _major_version = HIWORD(file_info->dwProductVersionMS); _minor_version = LOWORD(file_info->dwProductVersionMS); _build_number = HIWORD(file_info->dwProductVersionLS); + _build_minor = LOWORD(file_info->dwProductVersionLS); free_mem: os::free(version_info); diff --git a/src/hotspot/os/windows/os_windows.hpp b/src/hotspot/os/windows/os_windows.hpp index 14973ae3c498d..4155ce4d1e7b4 100644 --- a/src/hotspot/os/windows/os_windows.hpp +++ b/src/hotspot/os/windows/os_windows.hpp @@ -47,6 +47,7 @@ class os::win32 { static int _major_version; static int _minor_version; static int _build_number; + static int _build_minor; static void print_windows_version(outputStream* st); static void print_uptime_info(outputStream* st); @@ -66,6 +67,22 @@ class os::win32 { static int count_set_bits(ULONG64 argument); static DWORD get_available_logical_processors(); static DWORD get_logical_processor_count(); + static int windows_major_version() { + compute_windows_version(); + return _major_version; + } + static int windows_minor_version() { + compute_windows_version(); + return _minor_version; + } + static int windows_build_number() { + compute_windows_version(); + return _build_number; + } + static int windows_build_minor() { + compute_windows_version(); + return _build_minor; + } // Processor info as provided by NT static int processor_type() { return _processor_type; } From 7c85ebeb9c4b56bd5dd0ae237456f8183cc6e442 Mon Sep 17 00:00:00 2001 From: Saint Wesonga Date: Mon, 11 Dec 2023 19:52:05 -0700 Subject: [PATCH 08/32] Change accessibility of some functions to private --- src/hotspot/os/windows/os_windows.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hotspot/os/windows/os_windows.hpp b/src/hotspot/os/windows/os_windows.hpp index 4155ce4d1e7b4..50382cda722eb 100644 --- a/src/hotspot/os/windows/os_windows.hpp +++ b/src/hotspot/os/windows/os_windows.hpp @@ -61,10 +61,8 @@ class os::win32 { // Windows-specific interface: static void initialize_system_info(); static void setmode_streams(); - static void compute_windows_version(); static bool is_windows_11_or_greater(); static bool is_windows_server_2022_or_greater(); - static int count_set_bits(ULONG64 argument); static DWORD get_available_logical_processors(); static DWORD get_logical_processor_count(); static int windows_major_version() { @@ -99,6 +97,8 @@ class os::win32 { private: static void initialize_performance_counter(); + static void compute_windows_version(); + static int count_set_bits(ULONG64 argument); public: // Generic interface: From 3f7102a7981f5925bb731c69a7080417b3fce72f Mon Sep 17 00:00:00 2001 From: Saint Wesonga Date: Mon, 11 Dec 2023 19:54:29 -0700 Subject: [PATCH 09/32] Create a function to count processors in the job object --- src/hotspot/os/windows/os_windows.cpp | 23 ++++++++++++++--------- src/hotspot/os/windows/os_windows.hpp | 1 + 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index bc87b66c65758..99ddd7d73724a 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -4028,14 +4028,12 @@ int os::win32::count_set_bits(ULONG64 argument) { return bitcount; } -DWORD os::win32::get_available_logical_processors() { - DWORD logical_processors = 0; +DWORD os::win32::active_processors_in_job_object() { + DWORD processors = 0; - // Get the number of available logical processors from the associated job object LPVOID lpJobObjectInformation = NULL; DWORD cbJobObjectInformationLength = 0; - bool is_in_windows_job = false; // TODO: test other jobs with other JobObjectInformationClass values if (!QueryInformationJobObject(NULL, JobObjectGroupInformationEx, NULL, 0, &cbJobObjectInformationLength)) { DWORD last_error = GetLastError(); if (last_error == ERROR_INSUFFICIENT_BUFFER) { @@ -4044,13 +4042,14 @@ DWORD os::win32::get_available_logical_processors() { lpJobObjectInformation = os::malloc(cbJobObjectInformationLength, mtInternal); if (lpJobObjectInformation != NULL) { if (QueryInformationJobObject(NULL, JobObjectGroupInformationEx, lpJobObjectInformation, cbJobObjectInformationLength, &cbJobObjectInformationLength)) { - is_in_windows_job = true; group_count = cbJobObjectInformationLength / sizeof(GROUP_AFFINITY); for (DWORD i = 0; i < group_count; i++) { KAFFINITY group_affinity = ((GROUP_AFFINITY*)lpJobObjectInformation)[i].Mask; - logical_processors += count_set_bits(group_affinity); + processors += count_set_bits(group_affinity); } + + assert(processors > 0, "Must find at least 1 logical processor"); } else { warning("QueryInformationJobObject() failed: GetLastError->%ld.", GetLastError()); } @@ -4062,11 +4061,17 @@ DWORD os::win32::get_available_logical_processors() { } } - if (is_in_windows_job) { - assert(logical_processors > 0, "Must find at least 1 logical processor"); - return logical_processors; + return processors; +} + +DWORD os::win32::get_available_logical_processors() { + DWORD processors_in_job_object = active_processors_in_job_object(); + + if (processors_in_job_object > 0) { + return processors_in_job_object; } + DWORD logical_processors = 0; SYSTEM_INFO si; GetSystemInfo(&si); diff --git a/src/hotspot/os/windows/os_windows.hpp b/src/hotspot/os/windows/os_windows.hpp index 50382cda722eb..73de650cf0601 100644 --- a/src/hotspot/os/windows/os_windows.hpp +++ b/src/hotspot/os/windows/os_windows.hpp @@ -99,6 +99,7 @@ class os::win32 { static void initialize_performance_counter(); static void compute_windows_version(); static int count_set_bits(ULONG64 argument); + static DWORD active_processors_in_job_object(); public: // Generic interface: From 84974404e3a240b7ba11ae09f6ab226f54556bfa Mon Sep 17 00:00:00 2001 From: Saint Wesonga Date: Mon, 11 Dec 2023 21:06:50 -0700 Subject: [PATCH 10/32] Update method names per openjdk coding guidelines --- src/hotspot/os/windows/os_windows.cpp | 8 ++++---- src/hotspot/os/windows/os_windows.hpp | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index 99ddd7d73724a..d5de758f85621 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -4064,7 +4064,7 @@ DWORD os::win32::active_processors_in_job_object() { return processors; } -DWORD os::win32::get_available_logical_processors() { +DWORD os::win32::available_logical_processors() { DWORD processors_in_job_object = active_processors_in_job_object(); if (processors_in_job_object > 0) { @@ -4095,13 +4095,13 @@ DWORD os::win32::get_available_logical_processors() { // to detect Windows 11 or Windows Server 2022. See // https://learn.microsoft.com/en-us/windows/win32/procthread/processor-groups#behavior-starting-with-windows-11-and-windows-server-2022 if (is_windows_11_or_greater() || is_windows_server_2022_or_greater()) { - logical_processors = get_logical_processor_count(); + logical_processors = system_logical_processor_count(); } return logical_processors == 0 ? si.dwNumberOfProcessors : logical_processors; } -DWORD os::win32::get_logical_processor_count() { +DWORD os::win32::system_logical_processor_count() { DWORD logicalProcessors = 0; typedef BOOL(WINAPI* LPFN_GET_LOGICAL_PROCESSOR_INFORMATION_EX)( LOGICAL_PROCESSOR_RELATIONSHIP, PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, PDWORD); @@ -4160,7 +4160,7 @@ void os::win32::initialize_system_info() { _processor_type = si.dwProcessorType; _processor_level = si.wProcessorLevel; - DWORD logicalProcessors = get_available_logical_processors(); + DWORD logicalProcessors = available_logical_processors(); set_processor_count(logicalProcessors > 0 ? logicalProcessors : si.dwNumberOfProcessors); MEMORYSTATUSEX ms; diff --git a/src/hotspot/os/windows/os_windows.hpp b/src/hotspot/os/windows/os_windows.hpp index 73de650cf0601..0928a9d5cf7a5 100644 --- a/src/hotspot/os/windows/os_windows.hpp +++ b/src/hotspot/os/windows/os_windows.hpp @@ -63,8 +63,8 @@ class os::win32 { static void setmode_streams(); static bool is_windows_11_or_greater(); static bool is_windows_server_2022_or_greater(); - static DWORD get_available_logical_processors(); - static DWORD get_logical_processor_count(); + static DWORD available_logical_processors(); + static DWORD system_logical_processor_count(); static int windows_major_version() { compute_windows_version(); return _major_version; From aff22b517081dbf168ca5d32d787adfddcbaf4cc Mon Sep 17 00:00:00 2001 From: Saint Wesonga Date: Mon, 11 Dec 2023 21:35:28 -0700 Subject: [PATCH 11/32] Make processor_count return total processors --- src/hotspot/os/windows/os_windows.cpp | 76 +++++++++++++-------------- src/hotspot/os/windows/os_windows.hpp | 1 - 2 files changed, 36 insertions(+), 41 deletions(-) diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index d5de758f85621..a7671b4564208 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -867,7 +867,40 @@ int os::active_processor_count() { return ActiveProcessorCount; } - return processor_count(); + DWORD processors_in_job_object = win32::active_processors_in_job_object(); + + if (processors_in_job_object > 0) { + return processors_in_job_object; + } + + DWORD logical_processors = 0; + SYSTEM_INFO si; + GetSystemInfo(&si); + + // There is no associated job object so get the number of available logical processors from the process affinity mask + DWORD_PTR lpProcessAffinityMask = 0; + DWORD_PTR lpSystemAffinityMask = 0; + if (GetProcessAffinityMask(GetCurrentProcess(), &lpProcessAffinityMask, &lpSystemAffinityMask)) { + logical_processors = win32::count_set_bits(lpProcessAffinityMask); + + if (logical_processors != si.dwNumberOfProcessors) { + // Respect the custom processor affinity since it is not equal to all processors in the current processor group + return logical_processors; + } + } else { + warning("GetProcessAffinityMask() failed: GetLastError->%ld.", GetLastError()); + } + + // Starting with Windows 11 and Windows Server 2022 the OS has changed to + // make processes and their threads span all processors in the system, + // across all processor groups, by default. Therefore, this function needs + // to detect Windows 11 or Windows Server 2022. See + // https://learn.microsoft.com/en-us/windows/win32/procthread/processor-groups#behavior-starting-with-windows-11-and-windows-server-2022 + if (win32::is_windows_11_or_greater() || win32::is_windows_server_2022_or_greater()) { + logical_processors = processor_count(); + } + + return logical_processors == 0 ? si.dwNumberOfProcessors : logical_processors; } uint os::processor_id() { @@ -4064,43 +4097,6 @@ DWORD os::win32::active_processors_in_job_object() { return processors; } -DWORD os::win32::available_logical_processors() { - DWORD processors_in_job_object = active_processors_in_job_object(); - - if (processors_in_job_object > 0) { - return processors_in_job_object; - } - - DWORD logical_processors = 0; - SYSTEM_INFO si; - GetSystemInfo(&si); - - // If there is no associated job object, get the number of available logical processors from the process affinity - DWORD_PTR lpProcessAffinityMask = 0; - DWORD_PTR lpSystemAffinityMask = 0; - if (GetProcessAffinityMask(GetCurrentProcess(), &lpProcessAffinityMask, &lpSystemAffinityMask)) { - logical_processors = count_set_bits(lpProcessAffinityMask); - - if (logical_processors != si.dwNumberOfProcessors) { - // Respect the custom processor affinity since it is not equal to all processors in the current (main) processor group - return logical_processors; - } - } else { - warning("GetProcessAffinityMask() failed: GetLastError->%ld.", GetLastError()); - } - - // Starting with Windows 11 and Windows Server 2022 the OS has changed to - // make processes and their threads span all processors in the system, - // across all processor groups, by default. Therefore, this function needs - // to detect Windows 11 or Windows Server 2022. See - // https://learn.microsoft.com/en-us/windows/win32/procthread/processor-groups#behavior-starting-with-windows-11-and-windows-server-2022 - if (is_windows_11_or_greater() || is_windows_server_2022_or_greater()) { - logical_processors = system_logical_processor_count(); - } - - return logical_processors == 0 ? si.dwNumberOfProcessors : logical_processors; -} - DWORD os::win32::system_logical_processor_count() { DWORD logicalProcessors = 0; typedef BOOL(WINAPI* LPFN_GET_LOGICAL_PROCESSOR_INFORMATION_EX)( @@ -4160,8 +4156,8 @@ void os::win32::initialize_system_info() { _processor_type = si.dwProcessorType; _processor_level = si.wProcessorLevel; - DWORD logicalProcessors = available_logical_processors(); - set_processor_count(logicalProcessors > 0 ? logicalProcessors : si.dwNumberOfProcessors); + DWORD processors = system_logical_processor_count(); + set_processor_count(processors > 0 ? processors : si.dwNumberOfProcessors); MEMORYSTATUSEX ms; ms.dwLength = sizeof(ms); diff --git a/src/hotspot/os/windows/os_windows.hpp b/src/hotspot/os/windows/os_windows.hpp index 0928a9d5cf7a5..8970775def6c6 100644 --- a/src/hotspot/os/windows/os_windows.hpp +++ b/src/hotspot/os/windows/os_windows.hpp @@ -63,7 +63,6 @@ class os::win32 { static void setmode_streams(); static bool is_windows_11_or_greater(); static bool is_windows_server_2022_or_greater(); - static DWORD available_logical_processors(); static DWORD system_logical_processor_count(); static int windows_major_version() { compute_windows_version(); From 3455b642ce32cd53d4399ee66535fb66a34d5100 Mon Sep 17 00:00:00 2001 From: Saint Wesonga Date: Tue, 12 Dec 2023 10:44:25 -0700 Subject: [PATCH 12/32] Rename 2 methods --- src/hotspot/os/windows/os_windows.cpp | 14 +++++++------- src/hotspot/os/windows/os_windows.hpp | 12 ++++++------ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index a7671b4564208..7ce9c633595eb 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -881,7 +881,7 @@ int os::active_processor_count() { DWORD_PTR lpProcessAffinityMask = 0; DWORD_PTR lpSystemAffinityMask = 0; if (GetProcessAffinityMask(GetCurrentProcess(), &lpProcessAffinityMask, &lpSystemAffinityMask)) { - logical_processors = win32::count_set_bits(lpProcessAffinityMask); + logical_processors = win32::bit_count(lpProcessAffinityMask); if (logical_processors != si.dwNumberOfProcessors) { // Respect the custom processor affinity since it is not equal to all processors in the current processor group @@ -3967,7 +3967,7 @@ int os::win32::_minor_version = 0; int os::win32::_build_number = 0; int os::win32::_build_minor = 0; -void os::win32::compute_windows_version() { +void os::win32::initialize_windows_version() { if (_major_version > 0) { return; // nothing to do if already the version has already been set } @@ -4037,7 +4037,7 @@ void os::win32::compute_windows_version() { } bool os::win32::is_windows_11_or_greater() { - compute_windows_version(); + initialize_windows_version(); // Windows 11 starts at build 22000 (Version 21H2) as per // https://learn.microsoft.com/en-us/windows/release-health/windows11-release-information @@ -4045,14 +4045,14 @@ bool os::win32::is_windows_11_or_greater() { } bool os::win32::is_windows_server_2022_or_greater() { - compute_windows_version(); + initialize_windows_version(); // Windows Server 2022 starts at build 20348.169 as per // https://learn.microsoft.com/en-us/windows/release-health/release-information return (_major_version >= 10 && _build_number >= 20348 && IsWindowsServer()); } -int os::win32::count_set_bits(ULONG64 argument) { +int os::win32::bit_count(ULONG64 argument) { int bitcount = 0; while (argument != 0) { argument &= (argument-1); @@ -4079,7 +4079,7 @@ DWORD os::win32::active_processors_in_job_object() { for (DWORD i = 0; i < group_count; i++) { KAFFINITY group_affinity = ((GROUP_AFFINITY*)lpJobObjectInformation)[i].Mask; - processors += count_set_bits(group_affinity); + processors += bit_count(group_affinity); } assert(processors > 0, "Must find at least 1 logical processor"); @@ -4147,7 +4147,7 @@ DWORD os::win32::system_logical_processor_count() { } void os::win32::initialize_system_info() { - compute_windows_version(); + initialize_windows_version(); SYSTEM_INFO si; GetSystemInfo(&si); diff --git a/src/hotspot/os/windows/os_windows.hpp b/src/hotspot/os/windows/os_windows.hpp index 8970775def6c6..81f42c1f35383 100644 --- a/src/hotspot/os/windows/os_windows.hpp +++ b/src/hotspot/os/windows/os_windows.hpp @@ -65,19 +65,19 @@ class os::win32 { static bool is_windows_server_2022_or_greater(); static DWORD system_logical_processor_count(); static int windows_major_version() { - compute_windows_version(); + initialize_windows_version(); return _major_version; } static int windows_minor_version() { - compute_windows_version(); + initialize_windows_version(); return _minor_version; } static int windows_build_number() { - compute_windows_version(); + initialize_windows_version(); return _build_number; } static int windows_build_minor() { - compute_windows_version(); + initialize_windows_version(); return _build_minor; } @@ -96,8 +96,8 @@ class os::win32 { private: static void initialize_performance_counter(); - static void compute_windows_version(); - static int count_set_bits(ULONG64 argument); + static void initialize_windows_version(); + static int bit_count(ULONG64 argument); static DWORD active_processors_in_job_object(); public: From 3a5feb949045e07ffbc71f10af90079ce5b6ab2f Mon Sep 17 00:00:00 2001 From: Saint Wesonga Date: Tue, 12 Dec 2023 10:54:19 -0700 Subject: [PATCH 13/32] Document why pd_print_cpu_info may not count all CPUs --- src/hotspot/os/windows/os_windows.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index 7ce9c633595eb..2d65d8e98baf5 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -1891,6 +1891,12 @@ void os::pd_print_cpu_info(outputStream* st, char* buf, size_t buflen) { if (proc_count < 1) { SYSTEM_INFO si; GetSystemInfo(&si); + + // This is the number of logical processors in the current processor group only and is therefore + // at most 64. The GetLogicalProcessorInformation function is used to compute the total number + // of processors. However, it requires memory to be allocated for the processor information buffer. + // Since this method is used in paths where memory allocation should not be done (i.e. after a crash), + // only the number of processors in the current group will be returned. proc_count = si.dwNumberOfProcessors; } @@ -3977,8 +3983,7 @@ void os::win32::initialize_windows_version() { DWORD version_size = 0; // Get the full path to \Windows\System32\kernel32.dll and use that for - // determining what version of Windows we're running on. This is the same - // approach used in src/java.base/windows/native/libjava/java_props_md.c + // determining what version of Windows we're running on. UINT buffer_size = GetSystemDirectoryW(NULL, 0); if (buffer_size == 0) { warning("GetSystemDirectoryW() failed: GetLastError->%ld.", GetLastError()); From 44fba6deca26f5de585ece67fae912d47dd99a9d Mon Sep 17 00:00:00 2001 From: Saint Wesonga Date: Tue, 12 Dec 2023 11:38:36 -0700 Subject: [PATCH 14/32] Fix naming convention of local variables --- src/hotspot/os/windows/os_windows.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index 2d65d8e98baf5..db720a074467e 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -4103,7 +4103,7 @@ DWORD os::win32::active_processors_in_job_object() { } DWORD os::win32::system_logical_processor_count() { - DWORD logicalProcessors = 0; + DWORD logical_processors = 0; typedef BOOL(WINAPI* LPFN_GET_LOGICAL_PROCESSOR_INFORMATION_EX)( LOGICAL_PROCESSOR_RELATIONSHIP, PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, PDWORD); @@ -4120,9 +4120,9 @@ DWORD os::win32::system_logical_processor_count() { // https://learn.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getlogicalprocessorinformationex if (!glpiex(relationshipType, pSytemLogicalProcessorInfo, &returnedLength)) { - DWORD lastError = GetLastError(); + DWORD last_error = GetLastError(); - if (lastError == ERROR_INSUFFICIENT_BUFFER) { + if (last_error == ERROR_INSUFFICIENT_BUFFER) { pSytemLogicalProcessorInfo = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX)os::malloc(returnedLength, mtInternal); if (NULL == pSytemLogicalProcessorInfo) { @@ -4130,25 +4130,25 @@ DWORD os::win32::system_logical_processor_count() { } else if (!glpiex(relationshipType, pSytemLogicalProcessorInfo, &returnedLength)) { warning("GetLogicalProcessorInformationEx() failed: GetLastError->%ld.", GetLastError()); } else { - DWORD processorGroups = pSytemLogicalProcessorInfo->Group.ActiveGroupCount; + DWORD processor_groups = pSytemLogicalProcessorInfo->Group.ActiveGroupCount; - for (DWORD i = 0; i < processorGroups; i++) { - PROCESSOR_GROUP_INFO groupInfo = pSytemLogicalProcessorInfo->Group.GroupInfo[i]; - logicalProcessors += groupInfo.ActiveProcessorCount; + for (DWORD i = 0; i < processor_groups; i++) { + PROCESSOR_GROUP_INFO group_info = pSytemLogicalProcessorInfo->Group.GroupInfo[i]; + logical_processors += group_info.ActiveProcessorCount; } - assert(logicalProcessors > 0, "Must find at least 1 logical processor"); + assert(logical_processors > 0, "Must find at least 1 logical processor"); } os::free(pSytemLogicalProcessorInfo); } else { - warning("GetLogicalProcessorInformationEx() failed: GetLastError->%ld.", lastError); + warning("GetLogicalProcessorInformationEx() failed: GetLastError->%ld.", last_error); } } } - return logicalProcessors; + return logical_processors; } void os::win32::initialize_system_info() { From 1eb07d8df446dbb83c29288b18afad81d97327db Mon Sep 17 00:00:00 2001 From: Saint Wesonga Date: Tue, 12 Dec 2023 11:46:32 -0700 Subject: [PATCH 15/32] Explain core count limitations on older Windows --- src/hotspot/os/windows/os_windows.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index db720a074467e..f8524d02a0b22 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -893,8 +893,14 @@ int os::active_processor_count() { // Starting with Windows 11 and Windows Server 2022 the OS has changed to // make processes and their threads span all processors in the system, - // across all processor groups, by default. Therefore, this function needs - // to detect Windows 11 or Windows Server 2022. See + // across all processor groups, by default. Therefore, on these operating + // systems, the full processor count can be used (since there are no processor + // affinity restritions at this point). Note that older operating systems can + // correctly report processor count but will not schedule threads across + // processor groups unless the application explicitly uses group affinity APIs + // to assign threads to processor groups. On these older operating systems, we + // will continue to use the dwNumberOfProcessors field. For details on the + // latest Windows scheduling behavior, see // https://learn.microsoft.com/en-us/windows/win32/procthread/processor-groups#behavior-starting-with-windows-11-and-windows-server-2022 if (win32::is_windows_11_or_greater() || win32::is_windows_server_2022_or_greater()) { logical_processors = processor_count(); From bcc74d990711fc2db3ed72cf454aea4967877c25 Mon Sep 17 00:00:00 2001 From: Saint Wesonga Date: Tue, 12 Dec 2023 15:26:14 -0700 Subject: [PATCH 16/32] Use consistent naming pattern for local variables --- src/hotspot/os/windows/os_windows.cpp | 44 +++++++++++++-------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index f8524d02a0b22..d918c3f95a0cb 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -4075,21 +4075,21 @@ int os::win32::bit_count(ULONG64 argument) { DWORD os::win32::active_processors_in_job_object() { DWORD processors = 0; - LPVOID lpJobObjectInformation = NULL; - DWORD cbJobObjectInformationLength = 0; + LPVOID job_object_information = NULL; + DWORD job_object_information_length = 0; - if (!QueryInformationJobObject(NULL, JobObjectGroupInformationEx, NULL, 0, &cbJobObjectInformationLength)) { + if (!QueryInformationJobObject(NULL, JobObjectGroupInformationEx, NULL, 0, &job_object_information_length)) { DWORD last_error = GetLastError(); if (last_error == ERROR_INSUFFICIENT_BUFFER) { - DWORD group_count = cbJobObjectInformationLength / sizeof(GROUP_AFFINITY); + DWORD group_count = job_object_information_length / sizeof(GROUP_AFFINITY); - lpJobObjectInformation = os::malloc(cbJobObjectInformationLength, mtInternal); - if (lpJobObjectInformation != NULL) { - if (QueryInformationJobObject(NULL, JobObjectGroupInformationEx, lpJobObjectInformation, cbJobObjectInformationLength, &cbJobObjectInformationLength)) { - group_count = cbJobObjectInformationLength / sizeof(GROUP_AFFINITY); + job_object_information = os::malloc(job_object_information_length, mtInternal); + if (job_object_information != NULL) { + if (QueryInformationJobObject(NULL, JobObjectGroupInformationEx, job_object_information, job_object_information_length, &job_object_information_length)) { + group_count = job_object_information_length / sizeof(GROUP_AFFINITY); for (DWORD i = 0; i < group_count; i++) { - KAFFINITY group_affinity = ((GROUP_AFFINITY*)lpJobObjectInformation)[i].Mask; + KAFFINITY group_affinity = ((GROUP_AFFINITY*)job_object_information)[i].Mask; processors += bit_count(group_affinity); } @@ -4098,9 +4098,9 @@ DWORD os::win32::active_processors_in_job_object() { warning("QueryInformationJobObject() failed: GetLastError->%ld.", GetLastError()); } - os::free(lpJobObjectInformation); + os::free(job_object_information); } else { - warning("os::malloc() failed to allocate %ld bytes for QueryInformationJobObject", lpJobObjectInformation); + warning("os::malloc() failed to allocate %ld bytes for QueryInformationJobObject", job_object_information); } } } @@ -4120,33 +4120,33 @@ DWORD os::win32::system_logical_processor_count() { "GetLogicalProcessorInformationEx"); if (glpiex != NULL) { - LOGICAL_PROCESSOR_RELATIONSHIP relationshipType = RelationGroup; - PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX pSytemLogicalProcessorInfo = NULL; - DWORD returnedLength = 0; + LOGICAL_PROCESSOR_RELATIONSHIP relationship_type = RelationGroup; + PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX sytem_logical_processor_info = NULL; + DWORD returned_length = 0; // https://learn.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getlogicalprocessorinformationex - if (!glpiex(relationshipType, pSytemLogicalProcessorInfo, &returnedLength)) { + if (!glpiex(relationship_type, sytem_logical_processor_info, &returned_length)) { DWORD last_error = GetLastError(); if (last_error == ERROR_INSUFFICIENT_BUFFER) { - pSytemLogicalProcessorInfo = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX)os::malloc(returnedLength, mtInternal); + sytem_logical_processor_info = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX)os::malloc(returned_length, mtInternal); - if (NULL == pSytemLogicalProcessorInfo) { - warning("os::malloc() failed to allocate %ld bytes for GetLogicalProcessorInformationEx buffer", returnedLength); - } else if (!glpiex(relationshipType, pSytemLogicalProcessorInfo, &returnedLength)) { + if (NULL == sytem_logical_processor_info) { + warning("os::malloc() failed to allocate %ld bytes for GetLogicalProcessorInformationEx buffer", returned_length); + } else if (!glpiex(relationship_type, sytem_logical_processor_info, &returned_length)) { warning("GetLogicalProcessorInformationEx() failed: GetLastError->%ld.", GetLastError()); } else { - DWORD processor_groups = pSytemLogicalProcessorInfo->Group.ActiveGroupCount; + DWORD processor_groups = sytem_logical_processor_info->Group.ActiveGroupCount; for (DWORD i = 0; i < processor_groups; i++) { - PROCESSOR_GROUP_INFO group_info = pSytemLogicalProcessorInfo->Group.GroupInfo[i]; + PROCESSOR_GROUP_INFO group_info = sytem_logical_processor_info->Group.GroupInfo[i]; logical_processors += group_info.ActiveProcessorCount; } assert(logical_processors > 0, "Must find at least 1 logical processor"); } - os::free(pSytemLogicalProcessorInfo); + os::free(sytem_logical_processor_info); } else { warning("GetLogicalProcessorInformationEx() failed: GetLastError->%ld.", last_error); From f5c20717c8018a0898ffac8b71137240c4269be2 Mon Sep 17 00:00:00 2001 From: Saint Wesonga Date: Wed, 13 Dec 2023 11:08:34 -0700 Subject: [PATCH 17/32] Do not inspect job object on older Windows builds --- src/hotspot/os/windows/os_windows.cpp | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index d918c3f95a0cb..91055511ff0b0 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -867,10 +867,20 @@ int os::active_processor_count() { return ActiveProcessorCount; } - DWORD processors_in_job_object = win32::active_processors_in_job_object(); + // Starting with Windows 11 and Windows Server 2022, the OS has changed to + // make processes and their threads span all processors in the system, + // across all processor groups, by default. Therefore, we will allow all + // processors to be active processors on these operating systems. However, + // job objects can be used to restrict processor affinity across the + // processor groups. In this case, the number of active processors must be + // obtained from the processor affinity in the job object. + bool schedules_all_processor_groups = win32::is_windows_11_or_greater() || win32::is_windows_server_2022_or_greater(); + if (schedules_all_processor_groups) { + DWORD processors_in_job_object = win32::active_processors_in_job_object(); - if (processors_in_job_object > 0) { - return processors_in_job_object; + if (processors_in_job_object > 0) { + return processors_in_job_object; + } } DWORD logical_processors = 0; @@ -891,18 +901,16 @@ int os::active_processor_count() { warning("GetProcessAffinityMask() failed: GetLastError->%ld.", GetLastError()); } - // Starting with Windows 11 and Windows Server 2022 the OS has changed to - // make processes and their threads span all processors in the system, - // across all processor groups, by default. Therefore, on these operating - // systems, the full processor count can be used (since there are no processor - // affinity restritions at this point). Note that older operating systems can + // There are no processor affinity restritions at this point so we can return + // the overall processor count if the OS automatically schedules threads across + // all processors on the system. Note that older operating systems can // correctly report processor count but will not schedule threads across // processor groups unless the application explicitly uses group affinity APIs // to assign threads to processor groups. On these older operating systems, we // will continue to use the dwNumberOfProcessors field. For details on the // latest Windows scheduling behavior, see // https://learn.microsoft.com/en-us/windows/win32/procthread/processor-groups#behavior-starting-with-windows-11-and-windows-server-2022 - if (win32::is_windows_11_or_greater() || win32::is_windows_server_2022_or_greater()) { + if (schedules_all_processor_groups) { logical_processors = processor_count(); } From 960f4e517078916a454bb7f2ff5c7217ab8607d2 Mon Sep 17 00:00:00 2001 From: Saint Wesonga Date: Sat, 16 Dec 2023 11:27:37 -0700 Subject: [PATCH 18/32] Fix typos --- src/hotspot/os/windows/os_windows.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index 91055511ff0b0..4b7740aacc43d 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -901,7 +901,7 @@ int os::active_processor_count() { warning("GetProcessAffinityMask() failed: GetLastError->%ld.", GetLastError()); } - // There are no processor affinity restritions at this point so we can return + // There are no processor affinity restrictions at this point so we can return // the overall processor count if the OS automatically schedules threads across // all processors on the system. Note that older operating systems can // correctly report processor count but will not schedule threads across @@ -4129,32 +4129,32 @@ DWORD os::win32::system_logical_processor_count() { if (glpiex != NULL) { LOGICAL_PROCESSOR_RELATIONSHIP relationship_type = RelationGroup; - PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX sytem_logical_processor_info = NULL; + PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX system_logical_processor_info = NULL; DWORD returned_length = 0; // https://learn.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getlogicalprocessorinformationex - if (!glpiex(relationship_type, sytem_logical_processor_info, &returned_length)) { + if (!glpiex(relationship_type, system_logical_processor_info, &returned_length)) { DWORD last_error = GetLastError(); if (last_error == ERROR_INSUFFICIENT_BUFFER) { - sytem_logical_processor_info = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX)os::malloc(returned_length, mtInternal); + system_logical_processor_info = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX)os::malloc(returned_length, mtInternal); - if (NULL == sytem_logical_processor_info) { + if (NULL == system_logical_processor_info) { warning("os::malloc() failed to allocate %ld bytes for GetLogicalProcessorInformationEx buffer", returned_length); - } else if (!glpiex(relationship_type, sytem_logical_processor_info, &returned_length)) { + } else if (!glpiex(relationship_type, system_logical_processor_info, &returned_length)) { warning("GetLogicalProcessorInformationEx() failed: GetLastError->%ld.", GetLastError()); } else { - DWORD processor_groups = sytem_logical_processor_info->Group.ActiveGroupCount; + DWORD processor_groups = system_logical_processor_info->Group.ActiveGroupCount; for (DWORD i = 0; i < processor_groups; i++) { - PROCESSOR_GROUP_INFO group_info = sytem_logical_processor_info->Group.GroupInfo[i]; + PROCESSOR_GROUP_INFO group_info = system_logical_processor_info->Group.GroupInfo[i]; logical_processors += group_info.ActiveProcessorCount; } assert(logical_processors > 0, "Must find at least 1 logical processor"); } - os::free(sytem_logical_processor_info); + os::free(system_logical_processor_info); } else { warning("GetLogicalProcessorInformationEx() failed: GetLastError->%ld.", last_error); From 4ce6446c7e88571e77a5ab96d32cbdfba2461f45 Mon Sep 17 00:00:00 2001 From: Saint Wesonga Date: Sat, 16 Dec 2023 11:31:37 -0700 Subject: [PATCH 19/32] Clarify processor counting logic by using < operator --- src/hotspot/os/windows/os_windows.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index 4b7740aacc43d..572b4c0318d8d 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -893,7 +893,7 @@ int os::active_processor_count() { if (GetProcessAffinityMask(GetCurrentProcess(), &lpProcessAffinityMask, &lpSystemAffinityMask)) { logical_processors = win32::bit_count(lpProcessAffinityMask); - if (logical_processors != si.dwNumberOfProcessors) { + if (logical_processors < si.dwNumberOfProcessors) { // Respect the custom processor affinity since it is not equal to all processors in the current processor group return logical_processors; } From 95dcd4430e7cef9f183018ee1d38569f9b8e3e08 Mon Sep 17 00:00:00 2001 From: Saint Wesonga Date: Sat, 16 Dec 2023 11:35:13 -0700 Subject: [PATCH 20/32] Use new version functions instead of internal fields --- src/hotspot/os/windows/os_windows.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index 572b4c0318d8d..df00e2fd75024 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -4056,19 +4056,15 @@ void os::win32::initialize_windows_version() { } bool os::win32::is_windows_11_or_greater() { - initialize_windows_version(); - // Windows 11 starts at build 22000 (Version 21H2) as per // https://learn.microsoft.com/en-us/windows/release-health/windows11-release-information - return (_major_version >= 10 && _build_number >= 22000 && !IsWindowsServer()); + return (windows_major_version() >= 10 && windows_build_number() >= 22000 && !IsWindowsServer()); } bool os::win32::is_windows_server_2022_or_greater() { - initialize_windows_version(); - // Windows Server 2022 starts at build 20348.169 as per // https://learn.microsoft.com/en-us/windows/release-health/release-information - return (_major_version >= 10 && _build_number >= 20348 && IsWindowsServer()); + return (windows_major_version() >= 10 && windows_build_number() >= 20348 && IsWindowsServer()); } int os::win32::bit_count(ULONG64 argument) { From 936c9eb6eaf5cc99cca47d204cebca3b46f26b76 Mon Sep 17 00:00:00 2001 From: Saint Wesonga Date: Mon, 18 Dec 2023 10:33:53 -0700 Subject: [PATCH 21/32] Restore original version checking logic --- src/hotspot/os/windows/os_windows.cpp | 67 ++++++++++----------------- 1 file changed, 25 insertions(+), 42 deletions(-) diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index df00e2fd75024..49be6d3045fd7 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -3992,67 +3992,50 @@ void os::win32::initialize_windows_version() { return; // nothing to do if already the version has already been set } - LPWSTR kernel32_path = NULL; - LPWSTR version_info = NULL; - DWORD version_size = 0; + 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. - UINT buffer_size = GetSystemDirectoryW(NULL, 0); - if (buffer_size == 0) { - warning("GetSystemDirectoryW() failed: GetLastError->%ld.", GetLastError()); + len = MAX_PATH - (UINT)strlen("\\kernel32.dll") - 1; + ret = GetSystemDirectory(kernel32_path, len); + if (ret == 0 || ret > len) { + warning("GetSystemDirectory() failed: GetLastError->%ld.", GetLastError()); return; } + strncat(kernel32_path, "\\kernel32.dll", MAX_PATH - ret); - UINT filename_chars = (UINT)strlen("\\kernel32.dll"); - - // buffer_size includes the terminating null character - UINT size = (buffer_size + filename_chars) * sizeof(WCHAR); - kernel32_path = (LPWSTR)os::malloc(size, mtInternal); - if (kernel32_path == NULL) { - warning("os::malloc() failed to allocate %ld bytes for the kernel32.dll path", size); - return; - } - - UINT non_null_chars_written = GetSystemDirectoryW(kernel32_path, size); - if (non_null_chars_written == 0) { - warning("GetSystemDirectoryW() failed: GetLastError->%ld.", GetLastError()); - goto free_mem; - } - - wcsncat(kernel32_path, L"\\kernel32.dll", filename_chars); - - version_size = GetFileVersionInfoSizeW(kernel32_path, NULL); + DWORD version_size = GetFileVersionInfoSize(kernel32_path, nullptr); if (version_size == 0) { - warning("GetFileVersionInfoSizeW() failed: GetLastError->%ld.", GetLastError()); - goto free_mem; + warning("GetFileVersionInfoSize() failed: GetLastError->%ld.", GetLastError()); + return; } - version_info = (LPWSTR)os::malloc(version_size, mtInternal); - if (version_info == NULL) { - warning("os::malloc() failed to allocate %ld bytes for GetFileVersionInfoW buffer", version_size); - goto free_mem; + LPTSTR version_info = (LPTSTR)os::malloc(version_size, mtInternal); + if (version_info == nullptr) { + warning("os::malloc() failed to allocate %ld bytes for GetFileVersionInfo buffer", version_size); + return; } - if (!GetFileVersionInfoW(kernel32_path, 0, version_size, version_info)) { - warning("GetFileVersionInfoW() failed: GetLastError->%ld.", GetLastError()); - goto free_mem; + if (!GetFileVersionInfo(kernel32_path, 0, version_size, version_info)) { + os::free(version_info); + warning("GetFileVersionInfo() failed: GetLastError->%ld.", GetLastError()); + return; } - VS_FIXEDFILEINFO *file_info; - if (!VerQueryValueW(version_info, L"\\", (LPVOID*)&file_info, &size)) { - warning("VerQueryValueW() failed. Cannot determine Windows version."); - goto free_mem; + if (!VerQueryValue(version_info, TEXT("\\"), (LPVOID*)&file_info, &len)) { + os::free(version_info); + warning("VerQueryValue() failed. Cannot determine Windows version."); + return; } _major_version = HIWORD(file_info->dwProductVersionMS); _minor_version = LOWORD(file_info->dwProductVersionMS); _build_number = HIWORD(file_info->dwProductVersionLS); _build_minor = LOWORD(file_info->dwProductVersionLS); - -free_mem: - os::free(version_info); - os::free(kernel32_path); } bool os::win32::is_windows_11_or_greater() { From 79bd0f35703df55198b9da8167c255dd61c619e0 Mon Sep 17 00:00:00 2001 From: Saint Wesonga Date: Mon, 18 Dec 2023 14:18:08 -0700 Subject: [PATCH 22/32] Explicitly check if process is in a Windows job --- src/hotspot/os/windows/os_windows.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index 49be6d3045fd7..8e8d82b850f51 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -4060,6 +4060,12 @@ int os::win32::bit_count(ULONG64 argument) { } DWORD os::win32::active_processors_in_job_object() { + BOOL is_in_job_object = false; + if (!IsProcessInJob(GetCurrentProcess(), NULL, &is_in_job_object)) { + warning("IsProcessInJob() failed: GetLastError->%ld.", GetLastError()); + return 0; + } + DWORD processors = 0; LPVOID job_object_information = NULL; From 207538e0c0704c064bbd72f91220f46ede1c9b43 Mon Sep 17 00:00:00 2001 From: Saint Wesonga Date: Mon, 18 Dec 2023 14:20:19 -0700 Subject: [PATCH 23/32] Explicitly use nullptr --- src/hotspot/os/windows/os_windows.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index 8e8d82b850f51..0ceb660bf7a8b 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -4118,7 +4118,7 @@ DWORD os::win32::system_logical_processor_count() { DWORD returned_length = 0; // https://learn.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getlogicalprocessorinformationex - if (!glpiex(relationship_type, system_logical_processor_info, &returned_length)) { + if (!glpiex(relationship_type, nullptr, &returned_length)) { DWORD last_error = GetLastError(); if (last_error == ERROR_INSUFFICIENT_BUFFER) { From fcb878e7145a3976f575f4d9b2009ee7b88e6ece Mon Sep 17 00:00:00 2001 From: Saint Wesonga Date: Mon, 18 Dec 2023 15:32:33 -0700 Subject: [PATCH 24/32] Use result of IsProcessInJob --- src/hotspot/os/windows/os_windows.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index 0ceb660bf7a8b..cc97ffd46e779 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -4066,6 +4066,10 @@ DWORD os::win32::active_processors_in_job_object() { return 0; } + if (!is_in_job_object) { + return 0; + } + DWORD processors = 0; LPVOID job_object_information = NULL; From c3b97019afa8b64382e54f83da812c8c6299b72a Mon Sep 17 00:00:00 2001 From: Saint Wesonga Date: Mon, 18 Dec 2023 15:46:08 -0700 Subject: [PATCH 25/32] Convert assignment to assertion --- src/hotspot/os/windows/os_windows.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index cc97ffd46e779..828b293b8e1f0 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -4083,7 +4083,7 @@ DWORD os::win32::active_processors_in_job_object() { job_object_information = os::malloc(job_object_information_length, mtInternal); if (job_object_information != NULL) { if (QueryInformationJobObject(NULL, JobObjectGroupInformationEx, job_object_information, job_object_information_length, &job_object_information_length)) { - group_count = job_object_information_length / sizeof(GROUP_AFFINITY); + assert(group_count == job_object_information_length / sizeof(GROUP_AFFINITY)); for (DWORD i = 0; i < group_count; i++) { KAFFINITY group_affinity = ((GROUP_AFFINITY*)job_object_information)[i].Mask; From cede98c28ce4b6fe23073c40cd3dd96572754d0a Mon Sep 17 00:00:00 2001 From: Saint Wesonga Date: Mon, 18 Dec 2023 15:58:27 -0700 Subject: [PATCH 26/32] Remove duplicated function --- src/hotspot/os/windows/os_windows.cpp | 14 +++----------- src/hotspot/os/windows/os_windows.hpp | 1 - 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index 828b293b8e1f0..fbb569d0412cc 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -76,6 +76,7 @@ #include "utilities/defaultStream.hpp" #include "utilities/events.hpp" #include "utilities/macros.hpp" +#include "utilities/population_count.hpp" #include "utilities/vmError.hpp" #include "windbghelp.hpp" #if INCLUDE_JFR @@ -891,7 +892,7 @@ int os::active_processor_count() { DWORD_PTR lpProcessAffinityMask = 0; DWORD_PTR lpSystemAffinityMask = 0; if (GetProcessAffinityMask(GetCurrentProcess(), &lpProcessAffinityMask, &lpSystemAffinityMask)) { - logical_processors = win32::bit_count(lpProcessAffinityMask); + logical_processors = population_count(lpProcessAffinityMask); if (logical_processors < si.dwNumberOfProcessors) { // Respect the custom processor affinity since it is not equal to all processors in the current processor group @@ -4050,15 +4051,6 @@ bool os::win32::is_windows_server_2022_or_greater() { return (windows_major_version() >= 10 && windows_build_number() >= 20348 && IsWindowsServer()); } -int os::win32::bit_count(ULONG64 argument) { - int bitcount = 0; - while (argument != 0) { - argument &= (argument-1); - bitcount++; - } - return bitcount; -} - DWORD os::win32::active_processors_in_job_object() { BOOL is_in_job_object = false; if (!IsProcessInJob(GetCurrentProcess(), NULL, &is_in_job_object)) { @@ -4087,7 +4079,7 @@ DWORD os::win32::active_processors_in_job_object() { for (DWORD i = 0; i < group_count; i++) { KAFFINITY group_affinity = ((GROUP_AFFINITY*)job_object_information)[i].Mask; - processors += bit_count(group_affinity); + processors += population_count(group_affinity); } assert(processors > 0, "Must find at least 1 logical processor"); diff --git a/src/hotspot/os/windows/os_windows.hpp b/src/hotspot/os/windows/os_windows.hpp index 81f42c1f35383..7eb8fcc41ab33 100644 --- a/src/hotspot/os/windows/os_windows.hpp +++ b/src/hotspot/os/windows/os_windows.hpp @@ -97,7 +97,6 @@ class os::win32 { static void initialize_performance_counter(); static void initialize_windows_version(); - static int bit_count(ULONG64 argument); static DWORD active_processors_in_job_object(); public: From 6dd0064e0caa7f7f85865c76ee34a7a5a3fa5580 Mon Sep 17 00:00:00 2001 From: Saint Wesonga Date: Tue, 19 Dec 2023 11:46:26 -0700 Subject: [PATCH 27/32] Add missing assert error message --- src/hotspot/os/windows/os_windows.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index fbb569d0412cc..069d921335b08 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -4075,7 +4075,7 @@ DWORD os::win32::active_processors_in_job_object() { job_object_information = os::malloc(job_object_information_length, mtInternal); if (job_object_information != NULL) { if (QueryInformationJobObject(NULL, JobObjectGroupInformationEx, job_object_information, job_object_information_length, &job_object_information_length)) { - assert(group_count == job_object_information_length / sizeof(GROUP_AFFINITY)); + assert(group_count == job_object_information_length / sizeof(GROUP_AFFINITY), "Unexpected group count"); for (DWORD i = 0; i < group_count; i++) { KAFFINITY group_affinity = ((GROUP_AFFINITY*)job_object_information)[i].Mask; From 1396c21c7fef4648c02d969cd99f0a4896bd4550 Mon Sep 17 00:00:00 2001 From: Saint Wesonga Date: Wed, 20 Dec 2023 13:06:30 -0700 Subject: [PATCH 28/32] Add test to verify processors counts on Windows --- test/hotspot/gtest/runtime/test_os_windows.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/test/hotspot/gtest/runtime/test_os_windows.cpp b/test/hotspot/gtest/runtime/test_os_windows.cpp index 3d7f9c5c84c5b..74b9563696f32 100644 --- a/test/hotspot/gtest/runtime/test_os_windows.cpp +++ b/test/hotspot/gtest/runtime/test_os_windows.cpp @@ -703,6 +703,22 @@ TEST_VM(os_windows, reserve_memory_special) { TestReserveMemorySpecial_test(); } +TEST_VM(os_windows, processor_count) { + int processors = os::processor_count(); + EXPECT_GT(processors, 0) << "Expected at least 1 processor"; + + int active_processors = os::active_processor_count(); + EXPECT_GT(active_processors, 0) << "Expected at least 1 active processor"; + + bool schedules_all_processor_groups = os::win32::is_windows_11_or_greater() || os::win32::is_windows_server_2022_or_greater(); + if (schedules_all_processor_groups) { + EXPECT_EQ(active_processors, processors) << "Expected all processors to be active"; + } else { + // active_processors should be at most the number of processors in 1 Windows processor group. + EXPECT_LE(active_processors, processors) << "Expected active processors to not exceed available processors"; + } +} + class ReserveMemorySpecialRunnable : public TestRunnable { public: void runUnitTest() const { From 8e480c1e35a5832a2e850405b502009c2ff86398 Mon Sep 17 00:00:00 2001 From: Saint Wesonga Date: Fri, 22 Dec 2023 10:05:12 -0700 Subject: [PATCH 29/32] Fix number of bytes shown in malloc failure warning --- src/hotspot/os/windows/os_windows.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index 069d921335b08..c5759bd2736e0 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -4089,7 +4089,7 @@ DWORD os::win32::active_processors_in_job_object() { os::free(job_object_information); } else { - warning("os::malloc() failed to allocate %ld bytes for QueryInformationJobObject", job_object_information); + warning("os::malloc() failed to allocate %ld bytes for QueryInformationJobObject", job_object_information_length); } } } From e9932b35909cd19abe30723b6be2fb87fdc3fb8f Mon Sep 17 00:00:00 2001 From: Saint Wesonga Date: Tue, 2 Jan 2024 11:54:25 -0700 Subject: [PATCH 30/32] Fix typo --- src/hotspot/os/windows/os_windows.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index c5759bd2736e0..de56f64e13c22 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -3990,7 +3990,7 @@ int os::win32::_build_minor = 0; void os::win32::initialize_windows_version() { if (_major_version > 0) { - return; // nothing to do if already the version has already been set + return; // nothing to do if the version has already been set } VS_FIXEDFILEINFO *file_info; From dce9beeca1732f4d9b630094ef122ed6ecff5a6f Mon Sep 17 00:00:00 2001 From: Saint Wesonga Date: Tue, 2 Jan 2024 14:40:00 -0700 Subject: [PATCH 31/32] Replace NULL with nullptr --- src/hotspot/os/windows/os_windows.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index de56f64e13c22..65eed3d20149b 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -4053,7 +4053,7 @@ bool os::win32::is_windows_server_2022_or_greater() { DWORD os::win32::active_processors_in_job_object() { BOOL is_in_job_object = false; - if (!IsProcessInJob(GetCurrentProcess(), NULL, &is_in_job_object)) { + if (!IsProcessInJob(GetCurrentProcess(), nullptr, &is_in_job_object)) { warning("IsProcessInJob() failed: GetLastError->%ld.", GetLastError()); return 0; } @@ -4064,17 +4064,17 @@ DWORD os::win32::active_processors_in_job_object() { DWORD processors = 0; - LPVOID job_object_information = NULL; + LPVOID job_object_information = nullptr; DWORD job_object_information_length = 0; - if (!QueryInformationJobObject(NULL, JobObjectGroupInformationEx, NULL, 0, &job_object_information_length)) { + if (!QueryInformationJobObject(nullptr, JobObjectGroupInformationEx, nullptr, 0, &job_object_information_length)) { DWORD last_error = GetLastError(); if (last_error == ERROR_INSUFFICIENT_BUFFER) { DWORD group_count = job_object_information_length / sizeof(GROUP_AFFINITY); job_object_information = os::malloc(job_object_information_length, mtInternal); - if (job_object_information != NULL) { - if (QueryInformationJobObject(NULL, JobObjectGroupInformationEx, job_object_information, job_object_information_length, &job_object_information_length)) { + if (job_object_information != nullptr) { + if (QueryInformationJobObject(nullptr, JobObjectGroupInformationEx, job_object_information, job_object_information_length, &job_object_information_length)) { assert(group_count == job_object_information_length / sizeof(GROUP_AFFINITY), "Unexpected group count"); for (DWORD i = 0; i < group_count; i++) { @@ -4108,9 +4108,9 @@ DWORD os::win32::system_logical_processor_count() { GetModuleHandle(TEXT("kernel32")), "GetLogicalProcessorInformationEx"); - if (glpiex != NULL) { + if (glpiex != nullptr) { LOGICAL_PROCESSOR_RELATIONSHIP relationship_type = RelationGroup; - PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX system_logical_processor_info = NULL; + PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX system_logical_processor_info = nullptr; DWORD returned_length = 0; // https://learn.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getlogicalprocessorinformationex @@ -4120,7 +4120,7 @@ DWORD os::win32::system_logical_processor_count() { if (last_error == ERROR_INSUFFICIENT_BUFFER) { system_logical_processor_info = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX)os::malloc(returned_length, mtInternal); - if (NULL == system_logical_processor_info) { + if (nullptr == system_logical_processor_info) { warning("os::malloc() failed to allocate %ld bytes for GetLogicalProcessorInformationEx buffer", returned_length); } else if (!glpiex(relationship_type, system_logical_processor_info, &returned_length)) { warning("GetLogicalProcessorInformationEx() failed: GetLastError->%ld.", GetLastError()); From acf97ba716da2073e9774c29bf21da21f58a9795 Mon Sep 17 00:00:00 2001 From: Nitin Singh Date: Tue, 13 Feb 2024 12:45:56 -0600 Subject: [PATCH 32/32] Enable support for multiple large page sizes in OpenJDK on Windows --- src/hotspot/os/windows/os_windows.cpp | 52 +++++++++++++++---- src/hotspot/share/runtime/globals.hpp | 3 ++ .../hotspot/gtest/runtime/test_os_windows.cpp | 50 ++++++++++++++++++ 3 files changed, 96 insertions(+), 9 deletions(-) diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index 65eed3d20149b..1a91503d5ee87 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -3216,6 +3216,7 @@ static size_t large_page_init_decide_size() { !FLAG_IS_DEFAULT(LargePageSizeInBytes); #define WARN(msg) if (warn_on_failure) { warning(msg); } +#define WARN1(msg,p) if (warn_on_failure) { warning(msg,p); } if (!request_lock_memory_privilege()) { WARN("JVM cannot use large page memory because it does not have enough privilege to lock pages in memory."); @@ -3228,15 +3229,33 @@ static size_t large_page_init_decide_size() { return 0; } -#if defined(IA32) || defined(AMD64) - if (size > 4*M || LargePageSizeInBytes > 4*M) { - WARN("JVM cannot use large pages bigger than 4mb."); - return 0; - } + // Check if OS version is 11 or greater + if (schedules_all_processor_groups) { + // OS-specific logic for versions 11 or greater + // You can implement specific checks or logic here for newer OS versions + } + else { + // Existing logic for OS versions less than 11 +#if defined(IA32) + if (size > 4 * M || LargePageSizeInBytes > 4 * M) { + WARN("JVM cannot use large pages bigger than 4mb."); + return 0; + } +#elif defined(AMD64) + if (!EnableAllLargePageSizes) { + if (size > 4 * M || LargePageSizeInBytes > 4 * M) { + WARN("JVM cannot use large pages bigger than 4mb."); + return 0; + } + } #endif + } if (LargePageSizeInBytes > 0 && LargePageSizeInBytes % size == 0) { - size = LargePageSizeInBytes; + size = LargePageSizeInBytes; + } + else { + WARN1("JVM cannot use large pages that are not a multiple of minimum large page size (%d), defaulting to minimum page size.", size); } #undef WARN @@ -3252,11 +3271,26 @@ void os::large_page_init() { _large_page_size = large_page_init_decide_size(); const size_t default_page_size = os::vm_page_size(); if (_large_page_size > default_page_size) { - _page_sizes.add(_large_page_size); - } +#if !defined(IA32) + // Check if the OS version is 11 or higher + if (schedules_all_processor_groups && EnableAllLargePageSizes) { + + // Additional logic needed for ARM architecture + size_t min_size = GetLargePageMinimum(); + + // Populate _page_sizes with large page sizes less than or equal to _large_page_size. + for (size_t page_size = min_size; page_size < _large_page_size; page_size *= 2) { + _page_sizes.add(page_size); + } + } +#endif + + _page_sizes.add(_large_page_size); + } + // Set UseLargePages based on whether a large page size was successfully determined UseLargePages = _large_page_size != 0; -} + } int os::create_file_for_heap(const char* dir) { diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp index dce90c78eb475..e49819279ff14 100644 --- a/src/hotspot/share/runtime/globals.hpp +++ b/src/hotspot/share/runtime/globals.hpp @@ -247,6 +247,9 @@ const int ObjectAlignmentInBytes = 8; "page size for the environment as the maximum)") \ range(0, max_uintx) \ \ + product(bool, EnableAllLargePageSizes, false, EXPERIMENTAL, \ + "Using high time resolution (for Windows 11+ and Win64 only)") \ + \ product(size_t, LargePageHeapSizeThreshold, 128*M, \ "Use large pages if maximum heap is at least this big") \ range(0, max_uintx) \ diff --git a/test/hotspot/gtest/runtime/test_os_windows.cpp b/test/hotspot/gtest/runtime/test_os_windows.cpp index 74b9563696f32..c8a0149635c99 100644 --- a/test/hotspot/gtest/runtime/test_os_windows.cpp +++ b/test/hotspot/gtest/runtime/test_os_windows.cpp @@ -703,6 +703,56 @@ TEST_VM(os_windows, reserve_memory_special) { TestReserveMemorySpecial_test(); } +TEST_VM(os_windows, large_page_init_decide_size) { + // Initial setup + UseLargePages = true; + bool schedules_all_processor_groups = true; + size_t LargePageSizeInBytes = 0; // Reset to default + + // Test for large page support + size_t decided_size = os::large_page_init_decide_size(); + size_t min_size = os::GetLargePageMinimum(); + if (min_size == 0) { + EXPECT_EQ(decided_size, 0) << "Expected decided size to be 0 when large page is not supported by the processor"; + } + + // Scenario 1: Test with 2MB large page size + LargePageSizeInBytes = 2 * M; // Set large page size to 2MB + decided_size = os::large_page_init_decide_size(); // Recalculate decided size + if (min_size == 2 * M) { + EXPECT_EQ(decided_size, 2 * M) << "Expected decided size to be 2M when large page and OS reported size are both 2M"; + } + + // Scenario 2: Test with 1MB large page size + LargePageSizeInBytes = 1 * M; // Set large page size to 1MB + decided_size = os::large_page_init_decide_size(); // Recalculate decided size + if (min_size == 2 * M) { + EXPECT_EQ(decided_size, 2 * M) << "Expected decided size to be 2M when large page is 1M and OS reported size is 2M"; + } + + // Check for specific OS versions or architectures + schedules_all_processor_groups = false; // Reset the flag for additional checks + if (schedules_all_processor_groups) { + // Add specific checks for OS version 11 or greater + } + else { +#if defined(IA32) || defined(AMD64) + if (!os::EnableAllLargePageSizes && (min_size > 4 * M || LargePageSizeInBytes > 4 * M)) { + EXPECT_EQ(decided_size, 0) << "Expected decided size to be 0 for large pages bigger than 4mb on IA32 or AMD64"; + } +#endif + } + + // Additional check for non-multiple of minimum size + LargePageSizeInBytes = 5 * M; // Set an arbitrary large page size + decided_size = os::large_page_init_decide_size(); // Recalculate decided size + if (LargePageSizeInBytes > 0 && LargePageSizeInBytes % min_size != 0) { + EXPECT_EQ(decided_size, min_size) << "Expected decided size to default to minimum page size when LargePageSizeInBytes is not a multiple of minimum size"; + } +} + + + TEST_VM(os_windows, processor_count) { int processors = os::processor_count(); EXPECT_GT(processors, 0) << "Expected at least 1 processor";