7
7
"context"
8
8
"fmt"
9
9
"runtime"
10
- "syscall"
11
10
"unsafe"
12
11
13
12
"github.com/shirou/gopsutil/v3/internal/common"
@@ -26,13 +25,14 @@ const (
26
25
cpIntr = 4
27
26
cpIdle = 5
28
27
cpuStates = 6
28
+ cpuOnline = 0x0001 // CPUSTATS_ONLINE
29
29
30
30
// sys/sysctl.h
31
- ctlKern = 1 // "high kernel": proc, limits
32
- ctlHw = 6 // CTL_HW
33
- smt = 24 // HW_SMT
34
- kernCptime = 40 // KERN_CPTIME
35
- kernCptime2 = 71 // KERN_CPTIME2
31
+ ctlKern = 1 // "high kernel": proc, limits
32
+ ctlHw = 6 // CTL_HW
33
+ smt = 24 // HW_SMT
34
+ kernCpTime = 40 // KERN_CPTIME
35
+ kernCPUStats = 85 // KERN_CPUSTATS
36
36
)
37
37
38
38
var ClocksPerSec = float64 (128 )
@@ -45,87 +45,66 @@ func init() {
45
45
}
46
46
}
47
47
48
- func smtEnabled () (bool , error ) {
49
- mib := []int32 {ctlHw , smt }
50
- buf , _ , err := common .CallSyscall (mib )
51
- if err != nil {
52
- return false , err
53
- }
54
-
55
- smt := * (* uint32 )(unsafe .Pointer (& buf [0 ]))
56
- return smt == 1 , nil
57
- }
58
-
59
48
func Times (percpu bool ) ([]TimesStat , error ) {
60
49
return TimesWithContext (context .Background (), percpu )
61
50
}
62
51
63
- func TimesWithContext ( ctx context. Context , percpu bool ) ([] TimesStat , error ) {
64
- var ret [] TimesStat
65
-
66
- var ncpu int
67
- if percpu {
68
- ncpu , _ = Counts ( true )
69
- } else {
70
- ncpu = 1
52
+ func cpsToTS ( cpuTimes [ cpuStates ] uint64 , name string ) TimesStat {
53
+ return TimesStat {
54
+ CPU : name ,
55
+ User : float64 ( cpuTimes [ cpUser ]) / ClocksPerSec ,
56
+ Nice : float64 ( cpuTimes [ cpNice ]) / ClocksPerSec ,
57
+ System : float64 ( cpuTimes [ cpSys ]) / ClocksPerSec ,
58
+ Idle : float64 ( cpuTimes [ cpIdle ]) / ClocksPerSec ,
59
+ Irq : float64 ( cpuTimes [ cpIntr ]) / ClocksPerSec ,
71
60
}
61
+ }
72
62
73
- smt , err := smtEnabled ()
74
- if err == syscall .EOPNOTSUPP {
75
- // if hw.smt is not applicable for this platform (e.g. i386),
76
- // pretend it's enabled
77
- smt = true
78
- } else if err != nil {
79
- return nil , err
80
- }
63
+ func TimesWithContext (ctx context.Context , percpu bool ) (ret []TimesStat , err error ) {
64
+ cpuTimes := [cpuStates ]uint64 {}
81
65
82
- for i := 0 ; i < ncpu ; i ++ {
83
- j := i
84
- if ! smt {
85
- j *= 2
66
+ if ! percpu {
67
+ mib := []int32 {ctlKern , kernCpTime }
68
+ buf , _ , err := common .CallSyscall (mib )
69
+ if err != nil {
70
+ return ret , err
86
71
}
87
-
88
- var mib []int32
89
- if percpu {
90
- mib = []int32 {ctlKern , kernCptime2 , int32 (j )}
91
- } else {
92
- mib = []int32 {ctlKern , kernCptime }
72
+ var x []C.long
73
+ // could use unsafe.Slice but it's only for go1.17+
74
+ x = (* [cpuStates ]C.long )(unsafe .Pointer (& buf [0 ]))[:]
75
+ for i := range x {
76
+ cpuTimes [i ] = uint64 (x [i ])
93
77
}
78
+ c := cpsToTS (cpuTimes , "cpu-total" )
79
+ return []TimesStat {c }, nil
80
+ }
81
+
82
+ ncpu , err := unix .SysctlUint32 ("hw.ncpu" )
83
+ if err != nil {
84
+ return
85
+ }
86
+
87
+ var i uint32
88
+ for i = 0 ; i < ncpu ; i ++ {
89
+ mib := []int32 {ctlKern , kernCPUStats , int32 (i )}
94
90
buf , _ , err := common .CallSyscall (mib )
95
91
if err != nil {
96
92
return ret , err
97
93
}
98
94
99
- var cpuTimes [cpuStates ]uint64
100
- if percpu {
101
- // could use unsafe.Slice but it's only for go1.17+
102
- var x []uint64
103
- x = (* [cpuStates ]uint64 )(unsafe .Pointer (& buf [0 ]))[:]
104
- for i := range x {
105
- cpuTimes [i ] = x [i ]
106
- }
107
- } else {
108
- // KERN_CPTIME yields long[CPUSTATES] and `long' is
109
- // platform dependent
110
- var x []C.long
111
- x = (* [cpuStates ]C.long )(unsafe .Pointer (& buf [0 ]))[:]
112
- for i := range x {
113
- cpuTimes [i ] = uint64 (x [i ])
114
- }
95
+ data := unsafe .Pointer (& buf [0 ])
96
+ fptr := unsafe .Pointer (uintptr (data ) + uintptr (8 * cpuStates ))
97
+ flags := * (* uint64 )(fptr )
98
+ if (flags & cpuOnline ) == 0 {
99
+ continue
115
100
}
116
101
117
- c := TimesStat {
118
- User : float64 (cpuTimes [cpUser ]) / ClocksPerSec ,
119
- Nice : float64 (cpuTimes [cpNice ]) / ClocksPerSec ,
120
- System : float64 (cpuTimes [cpSys ]) / ClocksPerSec ,
121
- Idle : float64 (cpuTimes [cpIdle ]) / ClocksPerSec ,
122
- Irq : float64 (cpuTimes [cpIntr ]) / ClocksPerSec ,
123
- }
124
- if percpu {
125
- c .CPU = fmt .Sprintf ("cpu%d" , j )
126
- } else {
127
- c .CPU = "cpu-total"
102
+ var x []uint64
103
+ x = (* [cpuStates ]uint64 )(data )[:]
104
+ for i := range x {
105
+ cpuTimes [i ] = x [i ]
128
106
}
107
+ c := cpsToTS (cpuTimes , fmt .Sprintf ("cpu%d" , i ))
129
108
ret = append (ret , c )
130
109
}
131
110
0 commit comments