1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495 |
- //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
- }
|