1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package numcpus
16
17 import (
18 "io/ioutil"
19 "os"
20 "path/filepath"
21 "strconv"
22 "strings"
23
24 "golang.org/x/sys/unix"
25 )
26
27 const sysfsCPUBasePath = "/sys/devices/system/cpu"
28
29 func getFromCPUAffinity() (int, error) {
30 var cpuSet unix.CPUSet
31 if err := unix.SchedGetaffinity(0, &cpuSet); err != nil {
32 return 0, err
33 }
34 return cpuSet.Count(), nil
35 }
36
37 func readCPURange(file string) (int, error) {
38 buf, err := ioutil.ReadFile(filepath.Join(sysfsCPUBasePath, file))
39 if err != nil {
40 return 0, err
41 }
42 return parseCPURange(strings.Trim(string(buf), "\n "))
43 }
44
45 func parseCPURange(cpus string) (int, error) {
46 n := int(0)
47 for _, cpuRange := range strings.Split(cpus, ",") {
48 if len(cpuRange) == 0 {
49 continue
50 }
51 rangeOp := strings.SplitN(cpuRange, "-", 2)
52 first, err := strconv.ParseUint(rangeOp[0], 10, 32)
53 if err != nil {
54 return 0, err
55 }
56 if len(rangeOp) == 1 {
57 n++
58 continue
59 }
60 last, err := strconv.ParseUint(rangeOp[1], 10, 32)
61 if err != nil {
62 return 0, err
63 }
64 n += int(last - first + 1)
65 }
66 return n, nil
67 }
68
69 func getConfigured() (int, error) {
70 d, err := os.Open(sysfsCPUBasePath)
71 if err != nil {
72 return 0, err
73 }
74 defer d.Close()
75 fis, err := d.Readdir(-1)
76 if err != nil {
77 return 0, err
78 }
79 count := 0
80 for _, fi := range fis {
81 if name := fi.Name(); fi.IsDir() && strings.HasPrefix(name, "cpu") {
82 _, err := strconv.ParseInt(name[3:], 10, 64)
83 if err == nil {
84 count++
85 }
86 }
87 }
88 return count, nil
89 }
90
91 func getKernelMax() (int, error) {
92 buf, err := ioutil.ReadFile(filepath.Join(sysfsCPUBasePath, "kernel_max"))
93 if err != nil {
94 return 0, err
95 }
96 n, err := strconv.ParseInt(strings.Trim(string(buf), "\n "), 10, 32)
97 if err != nil {
98 return 0, err
99 }
100 return int(n), nil
101 }
102
103 func getOffline() (int, error) {
104 return readCPURange("offline")
105 }
106
107 func getOnline() (int, error) {
108 if n, err := getFromCPUAffinity(); err == nil {
109 return n, nil
110 }
111 return readCPURange("online")
112 }
113
114 func getPossible() (int, error) {
115 return readCPURange("possible")
116 }
117
118 func getPresent() (int, error) {
119 return readCPURange("present")
120 }
121
View as plain text