github.com/cilium/ebpf@v0.15.1-0.20240517100537-8079b37aa138/cpu.go (about)

     1  package ebpf
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"strings"
     7  	"sync"
     8  )
     9  
    10  var possibleCPU = sync.OnceValues(func() (int, error) {
    11  	return parseCPUsFromFile("/sys/devices/system/cpu/possible")
    12  })
    13  
    14  // PossibleCPU returns the max number of CPUs a system may possibly have
    15  // Logical CPU numbers must be of the form 0-n
    16  func PossibleCPU() (int, error) {
    17  	return possibleCPU()
    18  }
    19  
    20  // MustPossibleCPU is a helper that wraps a call to PossibleCPU and panics if
    21  // the error is non-nil.
    22  func MustPossibleCPU() int {
    23  	cpus, err := PossibleCPU()
    24  	if err != nil {
    25  		panic(err)
    26  	}
    27  	return cpus
    28  }
    29  
    30  func parseCPUsFromFile(path string) (int, error) {
    31  	spec, err := os.ReadFile(path)
    32  	if err != nil {
    33  		return 0, err
    34  	}
    35  
    36  	n, err := parseCPUs(string(spec))
    37  	if err != nil {
    38  		return 0, fmt.Errorf("can't parse %s: %v", path, err)
    39  	}
    40  
    41  	return n, nil
    42  }
    43  
    44  // parseCPUs parses the number of cpus from a string produced
    45  // by bitmap_list_string() in the Linux kernel.
    46  // Multiple ranges are rejected, since they can't be unified
    47  // into a single number.
    48  // This is the format of /sys/devices/system/cpu/possible, it
    49  // is not suitable for /sys/devices/system/cpu/online, etc.
    50  func parseCPUs(spec string) (int, error) {
    51  	if strings.Trim(spec, "\n") == "0" {
    52  		return 1, nil
    53  	}
    54  
    55  	var low, high int
    56  	n, err := fmt.Sscanf(spec, "%d-%d\n", &low, &high)
    57  	if n != 2 || err != nil {
    58  		return 0, fmt.Errorf("invalid format: %s", spec)
    59  	}
    60  	if low != 0 {
    61  		return 0, fmt.Errorf("CPU spec doesn't start at zero: %s", spec)
    62  	}
    63  
    64  	// cpus is 0 indexed
    65  	return high + 1, nil
    66  }