1
0

sys_windows.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. //go:build windows
  2. // +build windows
  3. package sys
  4. import (
  5. "errors"
  6. "sync"
  7. "syscall"
  8. "unsafe"
  9. "github.com/shirou/gopsutil/v4/net"
  10. )
  11. func GetConnectionCount(proto string) (int, error) {
  12. if proto != "tcp" && proto != "udp" {
  13. return 0, errors.New("invalid protocol")
  14. }
  15. stats, err := net.Connections(proto)
  16. if err != nil {
  17. return 0, err
  18. }
  19. return len(stats), nil
  20. }
  21. func GetTCPCount() (int, error) {
  22. return GetConnectionCount("tcp")
  23. }
  24. func GetUDPCount() (int, error) {
  25. return GetConnectionCount("udp")
  26. }
  27. // --- CPU Utilization (Windows native) ---
  28. var (
  29. modKernel32 = syscall.NewLazyDLL("kernel32.dll")
  30. procGetSystemTimes = modKernel32.NewProc("GetSystemTimes")
  31. cpuMu sync.Mutex
  32. lastIdle uint64
  33. lastKernel uint64
  34. lastUser uint64
  35. hasLast bool
  36. )
  37. type filetime struct {
  38. LowDateTime uint32
  39. HighDateTime uint32
  40. }
  41. func ftToUint64(ft filetime) uint64 {
  42. return (uint64(ft.HighDateTime) << 32) | uint64(ft.LowDateTime)
  43. }
  44. // CPUPercentRaw returns the instantaneous total CPU utilization percentage using
  45. // Windows GetSystemTimes across all logical processors. The first call returns 0
  46. // as it initializes the baseline. Subsequent calls compute deltas.
  47. func CPUPercentRaw() (float64, error) {
  48. var idleFT, kernelFT, userFT filetime
  49. r1, _, e1 := procGetSystemTimes.Call(
  50. uintptr(unsafe.Pointer(&idleFT)),
  51. uintptr(unsafe.Pointer(&kernelFT)),
  52. uintptr(unsafe.Pointer(&userFT)),
  53. )
  54. if r1 == 0 { // failure
  55. if e1 != nil {
  56. return 0, e1
  57. }
  58. return 0, syscall.GetLastError()
  59. }
  60. idle := ftToUint64(idleFT)
  61. kernel := ftToUint64(kernelFT)
  62. user := ftToUint64(userFT)
  63. cpuMu.Lock()
  64. defer cpuMu.Unlock()
  65. if !hasLast {
  66. lastIdle = idle
  67. lastKernel = kernel
  68. lastUser = user
  69. hasLast = true
  70. return 0, nil
  71. }
  72. idleDelta := idle - lastIdle
  73. kernelDelta := kernel - lastKernel
  74. userDelta := user - lastUser
  75. // Update for next call
  76. lastIdle = idle
  77. lastKernel = kernel
  78. lastUser = user
  79. total := kernelDelta + userDelta
  80. if total == 0 {
  81. return 0, nil
  82. }
  83. // On Windows, kernel time includes idle time; busy = total - idle
  84. busy := total - idleDelta
  85. pct := float64(busy) / float64(total) * 100.0
  86. // lower bound not needed; ratios of uint64 are non-negative
  87. if pct > 100 {
  88. pct = 100
  89. }
  90. return pct, nil
  91. }