golang.org/x/sys@v0.20.1-0.20240517151509-673e0f94c16d/cpu/hwcap_linux.go (about)

     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  	"os"
     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 := os.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  }