cpu.go 1.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. package internal
  2. import (
  3. "fmt"
  4. "os"
  5. "sync"
  6. "github.com/pkg/errors"
  7. )
  8. var sysCPU struct {
  9. once sync.Once
  10. err error
  11. num int
  12. }
  13. // PossibleCPUs returns the max number of CPUs a system may possibly have
  14. // Logical CPU numbers must be of the form 0-n
  15. func PossibleCPUs() (int, error) {
  16. sysCPU.once.Do(func() {
  17. sysCPU.num, sysCPU.err = parseCPUs("/sys/devices/system/cpu/possible")
  18. })
  19. return sysCPU.num, sysCPU.err
  20. }
  21. var onlineCPU struct {
  22. once sync.Once
  23. err error
  24. num int
  25. }
  26. // OnlineCPUs returns the number of currently online CPUs
  27. // Logical CPU numbers must be of the form 0-n
  28. func OnlineCPUs() (int, error) {
  29. onlineCPU.once.Do(func() {
  30. onlineCPU.num, onlineCPU.err = parseCPUs("/sys/devices/system/cpu/online")
  31. })
  32. return onlineCPU.num, onlineCPU.err
  33. }
  34. // parseCPUs parses the number of cpus from sysfs,
  35. // in the format of "/sys/devices/system/cpu/{possible,online,..}.
  36. // Logical CPU numbers must be of the form 0-n
  37. func parseCPUs(path string) (int, error) {
  38. file, err := os.Open(path)
  39. if err != nil {
  40. return 0, err
  41. }
  42. defer file.Close()
  43. var low, high int
  44. n, _ := fmt.Fscanf(file, "%d-%d", &low, &high)
  45. if n < 1 || low != 0 {
  46. return 0, errors.Wrapf(err, "%s has unknown format", path)
  47. }
  48. if n == 1 {
  49. high = low
  50. }
  51. // cpus is 0 indexed
  52. return high + 1, nil
  53. }