Welcome to mirror list, hosted at ThFree Co, Russian Federation.

sys_darwin.go « sys « util - github.com/MHSanaei/3x-ui.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 6ecc78c09c1118a7bcf3c16e31f3c28f7df55393 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
//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
}