diff options
Diffstat (limited to 'util/sys/sys_windows.go')
| -rw-r--r-- | util/sys/sys_windows.go | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/util/sys/sys_windows.go b/util/sys/sys_windows.go index fd51d470..f3eae076 100644 --- a/util/sys/sys_windows.go +++ b/util/sys/sys_windows.go @@ -5,6 +5,9 @@ package sys import ( "errors" + "sync" + "syscall" + "unsafe" "github.com/shirou/gopsutil/v4/net" ) @@ -28,3 +31,81 @@ func GetTCPCount() (int, error) { func GetUDPCount() (int, error) { return GetConnectionCount("udp") } + +// --- CPU Utilization (Windows native) --- + +var ( + modKernel32 = syscall.NewLazyDLL("kernel32.dll") + procGetSystemTimes = modKernel32.NewProc("GetSystemTimes") + + cpuMu sync.Mutex + lastIdle uint64 + lastKernel uint64 + lastUser uint64 + hasLast bool +) + +type filetime struct { + LowDateTime uint32 + HighDateTime uint32 +} + +func ftToUint64(ft filetime) uint64 { + return (uint64(ft.HighDateTime) << 32) | uint64(ft.LowDateTime) +} + +// CPUPercentRaw returns the instantaneous total CPU utilization percentage using +// Windows GetSystemTimes across all logical processors. The first call returns 0 +// as it initializes the baseline. Subsequent calls compute deltas. +func CPUPercentRaw() (float64, error) { + var idleFT, kernelFT, userFT filetime + r1, _, e1 := procGetSystemTimes.Call( + uintptr(unsafe.Pointer(&idleFT)), + uintptr(unsafe.Pointer(&kernelFT)), + uintptr(unsafe.Pointer(&userFT)), + ) + if r1 == 0 { // failure + if e1 != nil { + return 0, e1 + } + return 0, syscall.GetLastError() + } + + idle := ftToUint64(idleFT) + kernel := ftToUint64(kernelFT) + user := ftToUint64(userFT) + + cpuMu.Lock() + defer cpuMu.Unlock() + + if !hasLast { + lastIdle = idle + lastKernel = kernel + lastUser = user + hasLast = true + return 0, nil + } + + idleDelta := idle - lastIdle + kernelDelta := kernel - lastKernel + userDelta := user - lastUser + + // Update for next call + lastIdle = idle + lastKernel = kernel + lastUser = user + + total := kernelDelta + userDelta + if total == 0 { + return 0, nil + } + // On Windows, kernel time includes idle time; busy = total - idle + busy := total - idleDelta + + pct := float64(busy) / float64(total) * 100.0 + // lower bound not needed; ratios of uint64 are non-negative + if pct > 100 { + pct = 100 + } + return pct, nil +} |
