1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162 |
- package internal
- import (
- "fmt"
- "os"
- "strings"
- "sync"
- )
- var sysCPU struct {
- once sync.Once
- err error
- num int
- }
- // PossibleCPUs returns the max number of CPUs a system may possibly have
- // Logical CPU numbers must be of the form 0-n
- func PossibleCPUs() (int, error) {
- sysCPU.once.Do(func() {
- sysCPU.num, sysCPU.err = parseCPUsFromFile("/sys/devices/system/cpu/possible")
- })
- return sysCPU.num, sysCPU.err
- }
- func parseCPUsFromFile(path string) (int, error) {
- spec, err := os.ReadFile(path)
- if err != nil {
- return 0, err
- }
- n, err := parseCPUs(string(spec))
- if err != nil {
- return 0, fmt.Errorf("can't parse %s: %v", path, err)
- }
- return n, nil
- }
- // parseCPUs parses the number of cpus from a string produced
- // by bitmap_list_string() in the Linux kernel.
- // Multiple ranges are rejected, since they can't be unified
- // into a single number.
- // This is the format of /sys/devices/system/cpu/possible, it
- // is not suitable for /sys/devices/system/cpu/online, etc.
- func parseCPUs(spec string) (int, error) {
- if strings.Trim(spec, "\n") == "0" {
- return 1, nil
- }
- var low, high int
- n, err := fmt.Sscanf(spec, "%d-%d\n", &low, &high)
- if n != 2 || err != nil {
- return 0, fmt.Errorf("invalid format: %s", spec)
- }
- if low != 0 {
- return 0, fmt.Errorf("CPU spec doesn't start at zero: %s", spec)
- }
- // cpus is 0 indexed
- return high + 1, nil
- }
|