# The Kernel class and its methods, underlying $*KERNEL, are a work in progress. # It is very hard to capture data about a changing universe in a stable API. # If you find errors for your hardware or OS distribution, please report them # with the values that you expected and how to get them in your situation. class Kernel does Systemic { has Str $!release is built(:bind); has Str $!hardware is built(:bind); has Str $!arch is built(:bind); has Int $!bits is built(:bind); #?if !jvm has $!uname; method !uname { $!uname ?? $!uname !! ($!uname := nqp::uname()) } #?endif method !uname-s(--> Str:D) { #?if !jvm nqp::atpos_s(self!uname, nqp::const::UNAME_SYSNAME) #?endif #?if jvm try shell('uname -s', :out, :!err).out.slurp(:close).chomp; #?endif } method !uname-r(--> Str:D) { #?if !jvm nqp::atpos_s(self!uname, nqp::const::UNAME_RELEASE) #?endif #?if jvm try shell('uname -r', :out, :!err).out.slurp(:close).chomp; #?endif } method !uname-v(--> Str:D) { #?if !jvm nqp::atpos_s(self!uname, nqp::const::UNAME_VERSION) #?endif #?if jvm try shell('uname -v', :out, :!err).out.slurp(:close).chomp; #?endif } method !uname-m(--> Str:D) { #?if !jvm nqp::atpos_s(self!uname, nqp::const::UNAME_MACHINE) #?endif #?if jvm try shell('uname -m', :out, :!err).out.slurp(:close).chomp; #?endif } method !uname-p(--> Str:D) { # TODO: find a way to get this without shelling out try shell("uname -p", :out, :!err).out.slurp(:close).chomp; } method name(--> Str:D) { $!name eq 'unknown' ?? self!name($*DISTRO.name) !! $!name } method !name(Str:D \distro --> Str:D) { # https://github.com/rakudo/rakudo/issues/3436 nqp::bind($!name,distro eq 'mswin32' ?? 'win32' !! distro eq 'browser' ?? 'browser' !! self!uname-s.lc ) } method version(--> Version:D) { $!version ?? $!version # https://github.com/rakudo/rakudo/issues/3436 !! nqp::bind($!version,self!uname-v.Version) } method release(--> Str:D) { # somewhat counter-intuitively the UNAME_RELEASE is what # most people think of the kernel version $!release ?? $!release !! ($!release := self!uname-r) } method hardware(--> Str:D) { $!hardware ?? $!hardware !! ($!hardware := self!uname-m) } method arch { $!arch ?? $!arch !! self!arch($*DISTRO.name) } method !arch(Str:D \distro --> Str:D) { $!arch := distro eq 'raspbian' ?? self!uname-m !! distro eq 'browser' ?? self!uname-m !! self!uname-p } method archname(--> Str:D) { self.hardware ~ '-' ~ self.name } method bits(--> Int:D) { $!bits ?? $!bits # naive approach !! ($!bits := $.hardware ~~ m/ _64 | w | amd64 | arm64 / ?? 64 !! 32); } method hostname(--> Str:D) { nqp::p6box_s(nqp::gethostname) } has @!signals; # Signal has $!signals-setup-lock = Lock.new; has $!signals-setup = False; method signals (Kernel:D:) { unless $!signals-setup { $!signals-setup-lock.protect: { unless $!signals-setup { my \arr = nqp::list(Nil); my int $els = nqp::add_i(Signal.enums.values.max, 1); my int $i = 1; nqp::while( nqp::islt_i($i, $els), nqp::bindpos(arr, $i, Signal($i) // Nil), ++$i ); @!signals = |arr; $!signals-setup = True; } } } @!signals } has %!signals-by-Str; has $!signals-by-Str-setup = False; proto method signal (|) {*} multi method signal(Kernel:D: Str:D $signal --> Int:D) { unless $!signals-by-Str-setup { $!signals-setup-lock.protect: { unless $!signals-by-Str-setup { my int $els = @.signals.elems; my int $i = -1; nqp::while( nqp::isgt_i($els,++$i), ($_ := @!signals.AT-POS($i)).defined && %!signals-by-Str.ASSIGN-KEY(.Str, nqp::decont($i)) ); $!signals-by-Str-setup := True; } } } %!signals-by-Str{$signal} // %!signals-by-Str{"SIG$signal"} // Int; } multi method signal(Kernel:D: Signal:D \signal --> Int:D) { signal.value } multi method signal(Kernel:D: Int:D \signal --> Int:D) { signal } method cpu-cores(--> Int) { nqp::cpucores } my $cpu-cores-but-one := nqp::null; method cpu-cores-but-one() is implementation-detail { nqp::ifnull( $cpu-cores-but-one, $cpu-cores-but-one := max nqp::cpucores() - 1, 1 ) } method cpu-usage(--> Int) is raw { my int @rusage; nqp::getrusage(@rusage); nqp::atpos_i(@rusage, nqp::const::RUSAGE_UTIME_SEC) * 1000000 + nqp::atpos_i(@rusage, nqp::const::RUSAGE_UTIME_MSEC) + nqp::atpos_i(@rusage, nqp::const::RUSAGE_STIME_SEC) * 1000000 + nqp::atpos_i(@rusage, nqp::const::RUSAGE_STIME_MSEC) } method free-memory(--> Int) { nqp::freemem() } my $total-mem := nqp::null(); method total-memory(--> Int) { nqp::ifnull( $total-mem, nqp::bind($total-mem,nqp::p6box_i(nqp::totalmem())) ) } my $endian := nqp::null; method endian(--> Endian:D) { nqp::ifnull( $endian, nqp::bind($endian,nqp::if( blob8.new(0,1).read-int16(0) == 1, # hacky way to find out BigEndian, LittleEndian )) ) } } Rakudo::Internals.REGISTER-DYNAMIC: '$*KERNEL', { PROCESS::<$KERNEL> := Kernel.new; } # vim: expandtab shiftwidth=4