...

Source file src/github.com/cilium/ebpf/internal/cpu.go

Documentation: github.com/cilium/ebpf/internal

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

View as plain text