get.pme.sh/pnats@v0.0.0-20240304004023-26bb5a137ed0/server/pse/pse_freebsd_amd64.go (about) 1 // Copyright 2015-2020 The NATS Authors 2 // Licensed under the Apache License, Version 2.0 (the "License"); 3 // you may not use this file except in compliance with the License. 4 // You may obtain a copy of the License at 5 // 6 // http://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software 9 // distributed under the License is distributed on an "AS IS" BASIS, 10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 // This is the amd64-specific FreeBSD implementation, with hard-coded offset 15 // constants derived by running freebsd.txt; having this implementation allows 16 // us to compile without CGO, which lets us cross-compile for FreeBSD from our 17 // CI system and so supply binaries for FreeBSD amd64. 18 // 19 // To generate for other architectures: 20 // 1. Update pse_freebsd.go, change the build exclusion to exclude your arch 21 // 2. Copy this file to be built for your arch 22 // 3. Update `nativeEndian` below 23 // 4. Link `freebsd.txt` to have a .c filename and compile and run, then 24 // paste the outputs into the const section below. 25 26 package pse 27 28 import ( 29 "encoding/binary" 30 "syscall" 31 32 "golang.org/x/sys/unix" 33 ) 34 35 // On FreeBSD, to get proc information we read it out of the kernel using a 36 // binary sysctl. The endianness of integers is thus explicitly "host", rather 37 // than little or big endian. 38 var nativeEndian = binary.LittleEndian 39 40 const ( 41 KIP_OFF_size = 256 42 KIP_OFF_rssize = 264 43 KIP_OFF_pctcpu = 308 44 ) 45 46 var pageshift int 47 48 func init() { 49 // To get the physical page size, the C library checks two places: 50 // process ELF auxiliary info, AT_PAGESZ 51 // as a fallback, the hw.pagesize sysctl 52 // In looking closely, I found that the Go runtime support is handling 53 // this for us, and exposing that as syscall.Getpagesize, having checked 54 // both in the same ways, at process start, so a call to that should return 55 // a memory value without even a syscall bounce. 56 pagesize := syscall.Getpagesize() 57 pageshift = 0 58 for pagesize > 1 { 59 pageshift += 1 60 pagesize >>= 1 61 } 62 } 63 64 func ProcUsage(pcpu *float64, rss, vss *int64) error { 65 rawdata, err := unix.SysctlRaw("kern.proc.pid", unix.Getpid()) 66 if err != nil { 67 return err 68 } 69 70 r_vss_bytes := nativeEndian.Uint32(rawdata[KIP_OFF_size:]) 71 r_rss_pages := nativeEndian.Uint32(rawdata[KIP_OFF_rssize:]) 72 rss_bytes := r_rss_pages << pageshift 73 74 // In C: fixpt_t ki_pctcpu 75 // Doc: %cpu for process during ki_swtime 76 // fixpt_t is __uint32_t 77 // usr.bin/top uses pctdouble to convert to a double (float64) 78 // define pctdouble(p) ((double)(p) / FIXED_PCTCPU) 79 // FIXED_PCTCPU is _usually_ FSCALE (some architectures are special) 80 // <sys/param.h> has: 81 // #define FSHIFT 11 /* bits to right of fixed binary point */ 82 // #define FSCALE (1<<FSHIFT) 83 r_pcpu := nativeEndian.Uint32(rawdata[KIP_OFF_pctcpu:]) 84 f_pcpu := float64(r_pcpu) / float64(2048) 85 86 *rss = int64(rss_bytes) 87 *vss = int64(r_vss_bytes) 88 *pcpu = f_pcpu 89 90 return nil 91 }