3x-ui/util/sys/sys_darwin.go
2025-09-16 14:15:18 +02:00

95 lines
1.8 KiB
Go

//go:build darwin
// +build darwin
package sys
import (
"encoding/binary"
"fmt"
"sync"
"github.com/shirou/gopsutil/v4/net"
"golang.org/x/sys/unix"
)
func GetTCPCount() (int, error) {
stats, err := net.Connections("tcp")
if err != nil {
return 0, err
}
return len(stats), nil
}
func GetUDPCount() (int, error) {
stats, err := net.Connections("udp")
if err != nil {
return 0, err
}
return len(stats), nil
}
// --- CPU Utilization (macOS native) ---
// sysctl kern.cp_time returns an array of 5 longs: user, nice, sys, idle, intr.
// We compute utilization deltas without cgo.
var (
cpuMu sync.Mutex
lastTotals [5]uint64
hasLastCPUT bool
)
func CPUPercentRaw() (float64, error) {
raw, err := unix.SysctlRaw("kern.cp_time")
if err != nil {
return 0, err
}
// Expect either 5*8 bytes (uint64) or 5*4 bytes (uint32)
var out [5]uint64
switch len(raw) {
case 5 * 8:
for i := 0; i < 5; i++ {
out[i] = binary.LittleEndian.Uint64(raw[i*8 : (i+1)*8])
}
case 5 * 4:
for i := 0; i < 5; i++ {
out[i] = uint64(binary.LittleEndian.Uint32(raw[i*4 : (i+1)*4]))
}
default:
return 0, fmt.Errorf("unexpected kern.cp_time size: %d", len(raw))
}
// user, nice, sys, idle, intr
user := out[0]
nice := out[1]
sysv := out[2]
idle := out[3]
intr := out[4]
cpuMu.Lock()
defer cpuMu.Unlock()
if !hasLastCPUT {
lastTotals = out
hasLastCPUT = true
return 0, nil
}
dUser := user - lastTotals[0]
dNice := nice - lastTotals[1]
dSys := sysv - lastTotals[2]
dIdle := idle - lastTotals[3]
dIntr := intr - lastTotals[4]
lastTotals = out
totald := dUser + dNice + dSys + dIdle + dIntr
if totald == 0 {
return 0, nil
}
busy := totald - dIdle
pct := float64(busy) / float64(totald) * 100.0
if pct > 100 {
pct = 100
}
return pct, nil
}