hwcap_linux.go (1521B)
1 // Copyright 2019 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package cpu 6 7 import ( 8 "io/ioutil" 9 ) 10 11 const ( 12 _AT_HWCAP = 16 13 _AT_HWCAP2 = 26 14 15 procAuxv = "/proc/self/auxv" 16 17 uintSize = int(32 << (^uint(0) >> 63)) 18 ) 19 20 // For those platforms don't have a 'cpuid' equivalent we use HWCAP/HWCAP2 21 // These are initialized in cpu_$GOARCH.go 22 // and should not be changed after they are initialized. 23 var hwCap uint 24 var hwCap2 uint 25 26 func readHWCAP() error { 27 // For Go 1.21+, get auxv from the Go runtime. 28 if a := getAuxv(); len(a) > 0 { 29 for len(a) >= 2 { 30 tag, val := a[0], uint(a[1]) 31 a = a[2:] 32 switch tag { 33 case _AT_HWCAP: 34 hwCap = val 35 case _AT_HWCAP2: 36 hwCap2 = val 37 } 38 } 39 return nil 40 } 41 42 buf, err := ioutil.ReadFile(procAuxv) 43 if err != nil { 44 // e.g. on android /proc/self/auxv is not accessible, so silently 45 // ignore the error and leave Initialized = false. On some 46 // architectures (e.g. arm64) doinit() implements a fallback 47 // readout and will set Initialized = true again. 48 return err 49 } 50 bo := hostByteOrder() 51 for len(buf) >= 2*(uintSize/8) { 52 var tag, val uint 53 switch uintSize { 54 case 32: 55 tag = uint(bo.Uint32(buf[0:])) 56 val = uint(bo.Uint32(buf[4:])) 57 buf = buf[8:] 58 case 64: 59 tag = uint(bo.Uint64(buf[0:])) 60 val = uint(bo.Uint64(buf[8:])) 61 buf = buf[16:] 62 } 63 switch tag { 64 case _AT_HWCAP: 65 hwCap = val 66 case _AT_HWCAP2: 67 hwCap2 = val 68 } 69 } 70 return nil 71 }