Skip to content

Commit

Permalink
Fix BSD cpu count (#4466)
Browse files Browse the repository at this point in the history
* Use sysctl to return the number of CPUs on BSD systems

See:
  http://man.openbsd.org/sysctl.3
  https://www.freebsd.org/cgi/man.cgi?query=sysctl&sektion=3
  • Loading branch information
Wesley Moxam authored and Martin Verzilli committed Jun 15, 2017
1 parent 74b1bb4 commit 11e76e4
Show file tree
Hide file tree
Showing 10 changed files with 91 additions and 29 deletions.
20 changes: 20 additions & 0 deletions src/crystal/system.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
module Crystal
# :nodoc
module System
# Returns the hostname
# def self.hostname

# Returns the number of logical processors available to the system.
#
# def self.cpu_count
end
end

require "./system/unix/hostname"

{% if flag?(:freebsd) || flag?(:openbsd) %}
require "./system/unix/sysctl_cpucount"
{% else %}
# TODO: restrict on flag?(:unix) after crystal > 0.22.0 is released
require "./system/unix/sysconf_cpucount"
{% end %}
13 changes: 13 additions & 0 deletions src/crystal/system/unix/hostname.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
require "c/unistd"

module Crystal::System
def self.hostname
String.new(255) do |buffer|
unless LibC.gethostname(buffer, LibC::SizeT.new(255)) == 0
raise Errno.new("Could not get hostname")
end
len = LibC.strlen(buffer)
{len, len}
end
end
end
9 changes: 9 additions & 0 deletions src/crystal/system/unix/sysconf_cpucount.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{% skip_file if flag?(:openbsd) || flag?(:freebsd) %}

require "c/unistd"

module Crystal::System
def self.cpu_count
LibC.sysconf(LibC::SC_NPROCESSORS_ONLN)
end
end
17 changes: 17 additions & 0 deletions src/crystal/system/unix/sysctl_cpucount.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{% skip_file unless flag?(:openbsd) || flag?(:freebsd) %}

require "c/sysctl"

module Crystal::System
def self.cpu_count
mib = Int32[LibC::CTL_HW, LibC::HW_NCPU]
ncpus = 0
size = sizeof(Int32).to_u64

if LibC.sysctl(mib, 2, pointerof(ncpus), pointerof(size), nil, 0) == 0
ncpus
else
-1
end
end
end
6 changes: 6 additions & 0 deletions src/lib_c/amd64-unknown-openbsd/c/sysctl.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
lib LibC
CTL_HW = 6
HW_NCPU = 3

fun sysctl(name : Int*, namelen : UInt, oldp : Void*, oldlenp : SizeT*, newp : Void*, newlen : SizeT) : Int
end
11 changes: 5 additions & 6 deletions src/lib_c/amd64-unknown-openbsd/c/unistd.cr
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@ require "./sys/types"
require "./stdint"

lib LibC
F_OK = 0
R_OK = 0x04
W_OK = 0x02
X_OK = 0x01
SC_CLK_TCK = 3
SC_NPROCESSORS_ONLN = 58
F_OK = 0
R_OK = 0x04
W_OK = 0x02
X_OK = 0x01
SC_CLK_TCK = 3

fun access(x0 : Char*, x1 : Int) : Int
fun chdir(x0 : Char*) : Int
Expand Down
10 changes: 10 additions & 0 deletions src/lib_c/x86_64-portbld-freebsd/c/sysctl.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
lib LibC
CTL_HW = 6
CTL_KERN = 1
HW_NCPU = 3
KERN_PROC = 14
KERN_PROC_PATHNAME = 12
PATH_MAX = 1024

fun sysctl(name : Int*, namelen : UInt, oldp : Void*, oldlenp : SizeT*, newp : Void*, newlen : SizeT) : Int
end
11 changes: 5 additions & 6 deletions src/lib_c/x86_64-portbld-freebsd/c/unistd.cr
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@ require "./sys/types"
require "./stdint"

lib LibC
F_OK = 0
R_OK = 0x04
W_OK = 0x02
X_OK = 0x01
SC_CLK_TCK = 3
SC_NPROCESSORS_ONLN = 58
F_OK = 0
R_OK = 0x04
W_OK = 0x02
X_OK = 0x01
SC_CLK_TCK = 3

fun access(x0 : Char*, x1 : Int) : Int
fun chdir(x0 : Char*) : Int
Expand Down
8 changes: 1 addition & 7 deletions src/process/executable_path.cr
Original file line number Diff line number Diff line change
Expand Up @@ -72,13 +72,7 @@ end
end

{% elsif flag?(:freebsd) %}
lib LibC
PATH_MAX = 1024
CTL_KERN = 1
KERN_PROC = 14
KERN_PROC_PATHNAME = 12
fun sysctl(name : Int*, namelen : UInt, oldp : Void*, oldlenp : SizeT*, newp : Void*, newlen : SizeT) : Int
end
require "c/sysctl"

class Process
private def self.executable_path_impl
Expand Down
15 changes: 5 additions & 10 deletions src/system.cr
Original file line number Diff line number Diff line change
@@ -1,22 +1,17 @@
require "c/unistd"
require "crystal/system"

module System
# Returns the hostname.
#
# NOTE: Maximum of 253 characters are allowed, with 2 bytes reserved for storage.
# NOTE: Maximum of 253 characters are allowed, with 2 bytes reserved for
# storage.
# In practice, many platforms will disallow anything longer than 63 characters.
#
# ```
# System.hostname # => "host.example.org"
# ```
def self.hostname
String.new(255) do |buffer|
unless LibC.gethostname(buffer, LibC::SizeT.new(255)) == 0
raise Errno.new("Could not get hostname")
end
len = LibC.strlen(buffer)
{len, len}
end
Crystal::System.hostname
end

# Returns the number of logical processors available to the system.
Expand All @@ -25,6 +20,6 @@ module System
# System.cpu_count # => 4
# ```
def self.cpu_count
LibC.sysconf(LibC::SC_NPROCESSORS_ONLN)
Crystal::System.cpu_count
end
end

0 comments on commit 11e76e4

Please sign in to comment.