...

Source file src/github.com/shirou/gopsutil/cpu/cpu_openbsd.go

Documentation: github.com/shirou/gopsutil/cpu

     1  // +build openbsd
     2  
     3  package cpu
     4  
     5  import (
     6  	"bytes"
     7  	"context"
     8  	"encoding/binary"
     9  	"fmt"
    10  	"runtime"
    11  	"strconv"
    12  	"strings"
    13  	"syscall"
    14  
    15  	"github.com/shirou/gopsutil/internal/common"
    16  	"github.com/tklauser/go-sysconf"
    17  	"golang.org/x/sys/unix"
    18  )
    19  
    20  // sys/sched.h
    21  var (
    22  	CPUser    = 0
    23  	CPNice    = 1
    24  	CPSys     = 2
    25  	CPIntr    = 3
    26  	CPIdle    = 4
    27  	CPUStates = 5
    28  )
    29  
    30  // sys/sysctl.h
    31  const (
    32  	CTLKern     = 1  // "high kernel": proc, limits
    33  	CTLHw       = 6  // CTL_HW
    34  	SMT         = 24 // HW_SMT
    35  	KernCptime  = 40 // KERN_CPTIME
    36  	KernCptime2 = 71 // KERN_CPTIME2
    37  )
    38  
    39  var ClocksPerSec = float64(128)
    40  
    41  func init() {
    42  	clkTck, err := sysconf.Sysconf(sysconf.SC_CLK_TCK)
    43  	// ignore errors
    44  	if err == nil {
    45  		ClocksPerSec = float64(clkTck)
    46  	}
    47  
    48  	func() {
    49  		v, err := unix.Sysctl("kern.osrelease") // can't reuse host.PlatformInformation because of circular import
    50  		if err != nil {
    51  			return
    52  		}
    53  		v = strings.ToLower(v)
    54  		version, err := strconv.ParseFloat(v, 64)
    55  		if err != nil {
    56  			return
    57  		}
    58  		if version >= 6.4 {
    59  			CPIntr = 4
    60  			CPIdle = 5
    61  			CPUStates = 6
    62  		}
    63  	}()
    64  }
    65  
    66  func smt() (bool, error) {
    67  	mib := []int32{CTLHw, SMT}
    68  	buf, _, err := common.CallSyscall(mib)
    69  	if err != nil {
    70  		return false, err
    71  	}
    72  
    73  	var ret bool
    74  	br := bytes.NewReader(buf)
    75  	if err := binary.Read(br, binary.LittleEndian, &ret); err != nil {
    76  		return false, err
    77  	}
    78  
    79  	return ret, nil
    80  }
    81  
    82  func Times(percpu bool) ([]TimesStat, error) {
    83  	return TimesWithContext(context.Background(), percpu)
    84  }
    85  
    86  func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) {
    87  	var ret []TimesStat
    88  
    89  	var ncpu int
    90  	if percpu {
    91  		ncpu, _ = Counts(true)
    92  	} else {
    93  		ncpu = 1
    94  	}
    95  
    96  	smt, err := smt()
    97  	if err == syscall.EOPNOTSUPP {
    98  		// if hw.smt is not applicable for this platform (e.g. i386),
    99  		// pretend it's enabled
   100  		smt = true
   101  	} else if err != nil {
   102  		return nil, err
   103  	}
   104  
   105  	for i := 0; i < ncpu; i++ {
   106  		j := i
   107  		if !smt {
   108  			j *= 2
   109  		}
   110  
   111  		var cpuTimes = make([]int32, CPUStates)
   112  		var mib []int32
   113  		if percpu {
   114  			mib = []int32{CTLKern, KernCptime2, int32(j)}
   115  		} else {
   116  			mib = []int32{CTLKern, KernCptime}
   117  		}
   118  		buf, _, err := common.CallSyscall(mib)
   119  		if err != nil {
   120  			return ret, err
   121  		}
   122  
   123  		br := bytes.NewReader(buf)
   124  		err = binary.Read(br, binary.LittleEndian, &cpuTimes)
   125  		if err != nil {
   126  			return ret, err
   127  		}
   128  		c := TimesStat{
   129  			User:   float64(cpuTimes[CPUser]) / ClocksPerSec,
   130  			Nice:   float64(cpuTimes[CPNice]) / ClocksPerSec,
   131  			System: float64(cpuTimes[CPSys]) / ClocksPerSec,
   132  			Idle:   float64(cpuTimes[CPIdle]) / ClocksPerSec,
   133  			Irq:    float64(cpuTimes[CPIntr]) / ClocksPerSec,
   134  		}
   135  		if percpu {
   136  			c.CPU = fmt.Sprintf("cpu%d", j)
   137  		} else {
   138  			c.CPU = "cpu-total"
   139  		}
   140  		ret = append(ret, c)
   141  	}
   142  
   143  	return ret, nil
   144  }
   145  
   146  // Returns only one (minimal) CPUInfoStat on OpenBSD
   147  func Info() ([]InfoStat, error) {
   148  	return InfoWithContext(context.Background())
   149  }
   150  
   151  func InfoWithContext(ctx context.Context) ([]InfoStat, error) {
   152  	var ret []InfoStat
   153  	var err error
   154  
   155  	c := InfoStat{}
   156  
   157  	mhz, err := unix.SysctlUint32("hw.cpuspeed")
   158  	if err != nil {
   159  		return nil, err
   160  	}
   161  	c.Mhz = float64(mhz)
   162  
   163  	ncpu, err := unix.SysctlUint32("hw.ncpuonline")
   164  	if err != nil {
   165  		return nil, err
   166  	}
   167  	c.Cores = int32(ncpu)
   168  
   169  	if c.ModelName, err = unix.Sysctl("hw.model"); err != nil {
   170  		return nil, err
   171  	}
   172  
   173  	return append(ret, c), nil
   174  }
   175  
   176  func CountsWithContext(ctx context.Context, logical bool) (int, error) {
   177  	return runtime.NumCPU(), nil
   178  }
   179  

View as plain text