diff --git a/spec/std/system_spec.cr b/spec/std/system_spec.cr index ec583cc66895..b7778fd616a4 100644 --- a/spec/std/system_spec.cr +++ b/spec/std/system_spec.cr @@ -13,7 +13,12 @@ describe System do describe "cpu_count" do it "returns current CPU count" do - shell_cpus = `getconf _NPROCESSORS_ONLN 2>/dev/null || nproc --all 2>/dev/null || grep -sc '^processor' /proc/cpuinfo || sysctl -n hw.ncpu 2>/dev/null`.to_i + shell_cpus = + {% if flag?(:win32) %} + ENV["NUMBER_OF_PROCESSORS"].to_i + {% elsif flag?(:unix) %} + `getconf _NPROCESSORS_ONLN 2>/dev/null || nproc --all 2>/dev/null || grep -sc '^processor' /proc/cpuinfo || sysctl -n hw.ncpu 2>/dev/null`.to_i + {% end %} cpu_count = System.cpu_count cpu_count.should eq(shell_cpus) end diff --git a/src/crystal/system.cr b/src/crystal/system.cr index 277ae020b137..35c09e5d0b0b 100644 --- a/src/crystal/system.cr +++ b/src/crystal/system.cr @@ -8,10 +8,17 @@ module Crystal::System # def self.cpu_count end -require "./system/unix/hostname" +{% if flag?(:unix) %} + require "./system/unix/hostname" -{% if flag?(:freebsd) || flag?(:openbsd) %} - require "./system/unix/sysctl_cpucount" -{% elsif flag?(:unix) %} - require "./system/unix/sysconf_cpucount" + {% if flag?(:freebsd) || flag?(:openbsd) %} + require "./system/unix/sysctl_cpucount" + {% else %} + require "./system/unix/sysconf_cpucount" + {% end %} +{% elsif flag?(:win32) %} + require "./system/win32/hostname" + require "./system/win32/cpucount" +{% else %} + {% raise "No Crystal::System implementation available" %} {% end %} diff --git a/src/crystal/system/win32/cpucount.cr b/src/crystal/system/win32/cpucount.cr new file mode 100644 index 000000000000..f98ee2439d84 --- /dev/null +++ b/src/crystal/system/win32/cpucount.cr @@ -0,0 +1,8 @@ +require "c/sysinfoapi" + +module Crystal::System + def self.cpu_count + LibC.GetNativeSystemInfo(out system_info) + system_info.dwNumberOfProcessors + end +end diff --git a/src/crystal/system/win32/hostname.cr b/src/crystal/system/win32/hostname.cr new file mode 100644 index 000000000000..2e92d076858b --- /dev/null +++ b/src/crystal/system/win32/hostname.cr @@ -0,0 +1,16 @@ +require "c/sysinfoapi" + +module Crystal::System + def self.hostname + retry_wstr_buffer do |buffer, small_buf| + name_size = LibC::DWORD.new(buffer.size) + if LibC.GetComputerNameExW(LibC::COMPUTER_NAME_FORMAT::ComputerNameDnsHostname, buffer, pointerof(name_size)) != 0 + break String.from_utf16(buffer[0, name_size]) + elsif small_buf && name_size > 0 + next name_size + else + raise WinError.new("GetComputerNameExW") + end + end + end +end diff --git a/src/lib_c/x86_64-windows-msvc/c/sysinfoapi.cr b/src/lib_c/x86_64-windows-msvc/c/sysinfoapi.cr new file mode 100644 index 000000000000..7fe6b54c6d37 --- /dev/null +++ b/src/lib_c/x86_64-windows-msvc/c/sysinfoapi.cr @@ -0,0 +1,45 @@ +require "c/winnt" +require "c/win_def" +require "c/int_safe" + +lib LibC + fun GetNativeSystemInfo(system_info : SYSTEM_INFO*) + + struct PROCESSOR_INFO + wProcessorArchitecture : WORD + wReserved : WORD + end + + union OEM_PROCESSOR_INFO + dwOemId : DWORD + processorInfo : PROCESSOR_INFO + end + + struct SYSTEM_INFO + oemProcessorInfo : OEM_PROCESSOR_INFO + dwPageSize : DWORD + lpMinimumApplicationAddress : Void* + lpMaximumApplicationAddress : Void* + dwActiveProcessorMask : DWORD* + dwNumberOfProcessors : DWORD + dwProcessorType : DWORD + dwAllocationGranularity : DWORD + wProcessorLevel : WORD + wProcessorRevision : WORD + end + + fun GetComputerNameExW(computer_name_format : COMPUTER_NAME_FORMAT, + machine_name : LPWSTR, + machine_name_size : DWORD*) : BOOLEAN + + enum COMPUTER_NAME_FORMAT + ComputerNameNetBIOS + ComputerNameDnsHostname + ComputerNameDnsDomain + ComputerNameDnsFullyQualified + ComputerNamePhysicalNetBIOS + ComputerNamePhysicalDnsHostname + ComputerNamePhysicalDomain + ComputerNamePhysicalDnsFullyQualified + end +end