cpu_darwin.go 3.3 KB
Newer Older
1 2 3 4 5
// +build darwin

package gopsutil

import (
S
Shirou WAKAYAMA 已提交
6
	"fmt"
7
	"os/exec"
8 9
	"strconv"
	"strings"
10 11

	common "github.com/shirou/gopsutil/common"
12 13 14 15
)

// sys/resource.h
const (
L
Lukas Lueg 已提交
16 17 18 19 20 21
	CPUser    = 0
	CPNice    = 1
	CPSys     = 2
	CPIntr    = 3
	CPIdle    = 4
	CPUStates = 5
22 23 24 25
)

// time.h
const (
L
Lukas Lueg 已提交
26
	ClocksPerSec = 128
27 28 29 30 31
)

func CPUTimes(percpu bool) ([]CPUTimesStat, error) {
	var ret []CPUTimesStat

K
KenjiTakahashi 已提交
32 33 34 35 36 37 38 39
	var sysctlCall string
	var ncpu int
	if percpu {
		sysctlCall = "kern.cp_times"
		ncpu, _ = CPUCounts(true)
	} else {
		sysctlCall = "kern.cp_time"
		ncpu = 1
40 41
	}

42
	cpuTimes, err := common.DoSysctrl(sysctlCall)
43 44 45
	if err != nil {
		return ret, err
	}
46

K
KenjiTakahashi 已提交
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
	for i := 0; i < ncpu; i++ {
		offset := CPUStates * i
		user, err := strconv.ParseFloat(cpuTimes[CPUser+offset], 32)
		if err != nil {
			return ret, err
		}
		nice, err := strconv.ParseFloat(cpuTimes[CPNice+offset], 32)
		if err != nil {
			return ret, err
		}
		sys, err := strconv.ParseFloat(cpuTimes[CPSys+offset], 32)
		if err != nil {
			return ret, err
		}
		idle, err := strconv.ParseFloat(cpuTimes[CPIdle+offset], 32)
		if err != nil {
			return ret, err
		}
		intr, err := strconv.ParseFloat(cpuTimes[CPIntr+offset], 32)
		if err != nil {
			return ret, err
		}

		c := CPUTimesStat{
			User:   float32(user / ClocksPerSec),
			Nice:   float32(nice / ClocksPerSec),
			System: float32(sys / ClocksPerSec),
			Idle:   float32(idle / ClocksPerSec),
			Irq:    float32(intr / ClocksPerSec),
		}
		if !percpu {
			c.CPU = "cpu-total"
		} else {
			c.CPU = fmt.Sprintf("cpu%d", i)
		}
82

K
KenjiTakahashi 已提交
83 84
		ret = append(ret, c)
	}
85 86 87 88 89 90 91 92

	return ret, nil
}

// Returns only one CPUInfoStat on FreeBSD
func CPUInfo() ([]CPUInfoStat, error) {
	var ret []CPUInfoStat

93 94 95 96 97
	out, err := exec.Command("/usr/sbin/sysctl", "machdep.cpu").Output()
	if err != nil {
		return ret, err
	}

98
	c := CPUInfoStat{}
99 100
	for _, line := range strings.Split(string(out), "\n") {
		values := strings.Fields(line)
101 102 103
		if len(values) < 1 {
			continue
		}
104

105
		t, err := strconv.ParseInt(values[1], 10, 64)
106
		// err is not checked here because some value is string.
107 108 109 110 111 112 113
		if strings.HasPrefix(line, "machdep.cpu.brand_string") {
			c.ModelName = strings.Join(values[1:], " ")
		} else if strings.HasPrefix(line, "machdep.cpu.family") {
			c.Family = values[1]
		} else if strings.HasPrefix(line, "machdep.cpu.model") {
			c.Model = values[1]
		} else if strings.HasPrefix(line, "machdep.cpu.stepping") {
114 115 116
			if err != nil {
				return ret, err
			}
117
			c.Stepping = int32(t)
118 119 120 121 122 123
		} else if strings.HasPrefix(line, "machdep.cpu.features") {
			for _, v := range values[1:] {
				c.Flags = append(c.Flags, strings.ToLower(v))
			}
		} else if strings.HasPrefix(line, "machdep.cpu.leaf7_features") {
			for _, v := range values[1:] {
124 125
				c.Flags = append(c.Flags, strings.ToLower(v))
			}
126 127
		} else if strings.HasPrefix(line, "machdep.cpu.extfeatures") {
			for _, v := range values[1:] {
128 129
				c.Flags = append(c.Flags, strings.ToLower(v))
			}
130
		} else if strings.HasPrefix(line, "machdep.cpu.core_count") {
131 132 133
			if err != nil {
				return ret, err
			}
134
			c.Cores = int32(t)
135
		} else if strings.HasPrefix(line, "machdep.cpu.cache.size") {
136 137 138
			if err != nil {
				return ret, err
			}
139
			c.CacheSize = int32(t)
140 141
		} else if strings.HasPrefix(line, "machdep.cpu.vendor") {
			c.VendorID = values[1]
142 143
		}

144 145
		// TODO:
		// c.Mhz = mustParseFloat64(values[1])
146 147 148 149
	}

	return append(ret, c), nil
}