gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

cpu.go (1377B)


      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 }