...

Source file src/github.com/tklauser/numcpus/numcpus_linux.go

Documentation: github.com/tklauser/numcpus

     1  // Copyright 2018 Tobias Klauser
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package numcpus
    16  
    17  import (
    18  	"io/ioutil"
    19  	"os"
    20  	"path/filepath"
    21  	"strconv"
    22  	"strings"
    23  
    24  	"golang.org/x/sys/unix"
    25  )
    26  
    27  const sysfsCPUBasePath = "/sys/devices/system/cpu"
    28  
    29  func getFromCPUAffinity() (int, error) {
    30  	var cpuSet unix.CPUSet
    31  	if err := unix.SchedGetaffinity(0, &cpuSet); err != nil {
    32  		return 0, err
    33  	}
    34  	return cpuSet.Count(), nil
    35  }
    36  
    37  func readCPURange(file string) (int, error) {
    38  	buf, err := ioutil.ReadFile(filepath.Join(sysfsCPUBasePath, file))
    39  	if err != nil {
    40  		return 0, err
    41  	}
    42  	return parseCPURange(strings.Trim(string(buf), "\n "))
    43  }
    44  
    45  func parseCPURange(cpus string) (int, error) {
    46  	n := int(0)
    47  	for _, cpuRange := range strings.Split(cpus, ",") {
    48  		if len(cpuRange) == 0 {
    49  			continue
    50  		}
    51  		rangeOp := strings.SplitN(cpuRange, "-", 2)
    52  		first, err := strconv.ParseUint(rangeOp[0], 10, 32)
    53  		if err != nil {
    54  			return 0, err
    55  		}
    56  		if len(rangeOp) == 1 {
    57  			n++
    58  			continue
    59  		}
    60  		last, err := strconv.ParseUint(rangeOp[1], 10, 32)
    61  		if err != nil {
    62  			return 0, err
    63  		}
    64  		n += int(last - first + 1)
    65  	}
    66  	return n, nil
    67  }
    68  
    69  func getConfigured() (int, error) {
    70  	d, err := os.Open(sysfsCPUBasePath)
    71  	if err != nil {
    72  		return 0, err
    73  	}
    74  	defer d.Close()
    75  	fis, err := d.Readdir(-1)
    76  	if err != nil {
    77  		return 0, err
    78  	}
    79  	count := 0
    80  	for _, fi := range fis {
    81  		if name := fi.Name(); fi.IsDir() && strings.HasPrefix(name, "cpu") {
    82  			_, err := strconv.ParseInt(name[3:], 10, 64)
    83  			if err == nil {
    84  				count++
    85  			}
    86  		}
    87  	}
    88  	return count, nil
    89  }
    90  
    91  func getKernelMax() (int, error) {
    92  	buf, err := ioutil.ReadFile(filepath.Join(sysfsCPUBasePath, "kernel_max"))
    93  	if err != nil {
    94  		return 0, err
    95  	}
    96  	n, err := strconv.ParseInt(strings.Trim(string(buf), "\n "), 10, 32)
    97  	if err != nil {
    98  		return 0, err
    99  	}
   100  	return int(n), nil
   101  }
   102  
   103  func getOffline() (int, error) {
   104  	return readCPURange("offline")
   105  }
   106  
   107  func getOnline() (int, error) {
   108  	if n, err := getFromCPUAffinity(); err == nil {
   109  		return n, nil
   110  	}
   111  	return readCPURange("online")
   112  }
   113  
   114  func getPossible() (int, error) {
   115  	return readCPURange("possible")
   116  }
   117  
   118  func getPresent() (int, error) {
   119  	return readCPURange("present")
   120  }
   121  

View as plain text