github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/sentry/hostcpu/hostcpu.go (about) 1 // Copyright 2018 The gVisor Authors. 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 hostcpu provides utilities for working with CPU information provided 16 // by a host Linux kernel. 17 package hostcpu 18 19 import ( 20 "fmt" 21 "io/ioutil" 22 "strconv" 23 "strings" 24 "unicode" 25 ) 26 27 // GetCPU returns the caller's current CPU number, without using the Linux VDSO 28 // (which is not available to the sentry) or the getcpu(2) system call (which 29 // is relatively slow). 30 func GetCPU() uint32 31 32 // MaxPossibleCPU returns the highest possible CPU number, which is guaranteed 33 // not to change for the lifetime of the host kernel. 34 func MaxPossibleCPU() (uint32, error) { 35 const path = "/sys/devices/system/cpu/possible" 36 data, err := ioutil.ReadFile(path) 37 if err != nil { 38 return 0, err 39 } 40 str := string(data) 41 // Linux: drivers/base/cpu.c:show_cpus_attr() => 42 // include/linux/cpumask.h:cpumask_print_to_pagebuf() => 43 // lib/bitmap.c:bitmap_print_to_pagebuf() 44 i, err := maxValueInLinuxBitmap(str) 45 if err != nil { 46 return 0, fmt.Errorf("invalid %s (%q): %v", path, str, err) 47 } 48 return uint32(i), nil 49 } 50 51 // maxValueInLinuxBitmap returns the maximum value specified in str, which is a 52 // string emitted by Linux's lib/bitmap.c:bitmap_print_to_pagebuf(list=true). 53 func maxValueInLinuxBitmap(str string) (uint64, error) { 54 str = strings.TrimSpace(str) 55 // Find the last decimal number in str. 56 idx := strings.LastIndexFunc(str, func(c rune) bool { 57 return !unicode.IsDigit(c) 58 }) 59 if idx != -1 { 60 str = str[idx+1:] 61 } 62 i, err := strconv.ParseUint(str, 10, 64) 63 if err != nil { 64 return 0, err 65 } 66 return i, nil 67 }