File: cpu_darwin_arm64.go

package info (click to toggle)
golang-github-shirou-gopsutil 4.25.2-1
  • links: PTS, VCS
  • area: main
  • in suites: experimental, forky, sid, trixie
  • size: 1,824 kB
  • sloc: makefile: 76; ansic: 19; sh: 11
file content (80 lines) | stat: -rw-r--r-- 2,871 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
// SPDX-License-Identifier: BSD-3-Clause
//go:build darwin && arm64

package cpu

import (
	"encoding/binary"
	"fmt"
	"unsafe"

	"github.com/shirou/gopsutil/v4/internal/common"
)

// https://github.com/shoenig/go-m1cpu/blob/v0.1.6/cpu.go
func getFrequency() (float64, error) {
	ioKit, err := common.NewLibrary(common.IOKit)
	if err != nil {
		return 0, err
	}
	defer ioKit.Close()

	coreFoundation, err := common.NewLibrary(common.CoreFoundation)
	if err != nil {
		return 0, err
	}
	defer coreFoundation.Close()

	ioServiceMatching := common.GetFunc[common.IOServiceMatchingFunc](ioKit, common.IOServiceMatchingSym)
	ioServiceGetMatchingServices := common.GetFunc[common.IOServiceGetMatchingServicesFunc](ioKit, common.IOServiceGetMatchingServicesSym)
	ioIteratorNext := common.GetFunc[common.IOIteratorNextFunc](ioKit, common.IOIteratorNextSym)
	ioRegistryEntryGetName := common.GetFunc[common.IORegistryEntryGetNameFunc](ioKit, common.IORegistryEntryGetNameSym)
	ioRegistryEntryCreateCFProperty := common.GetFunc[common.IORegistryEntryCreateCFPropertyFunc](ioKit, common.IORegistryEntryCreateCFPropertySym)
	ioObjectRelease := common.GetFunc[common.IOObjectReleaseFunc](ioKit, common.IOObjectReleaseSym)

	cfStringCreateWithCString := common.GetFunc[common.CFStringCreateWithCStringFunc](coreFoundation, common.CFStringCreateWithCStringSym)
	cfDataGetLength := common.GetFunc[common.CFDataGetLengthFunc](coreFoundation, common.CFDataGetLengthSym)
	cfDataGetBytePtr := common.GetFunc[common.CFDataGetBytePtrFunc](coreFoundation, common.CFDataGetBytePtrSym)
	cfRelease := common.GetFunc[common.CFReleaseFunc](coreFoundation, common.CFReleaseSym)

	matching := ioServiceMatching("AppleARMIODevice")

	var iterator uint32
	if status := ioServiceGetMatchingServices(common.KIOMainPortDefault, uintptr(matching), &iterator); status != common.KERN_SUCCESS {
		return 0.0, fmt.Errorf("IOServiceGetMatchingServices error=%d", status)
	}
	defer ioObjectRelease(iterator)

	pCorekey := cfStringCreateWithCString(common.KCFAllocatorDefault, "voltage-states5-sram", common.KCFStringEncodingUTF8)
	defer cfRelease(uintptr(pCorekey))

	var pCoreHz uint32
	for {
		service := ioIteratorNext(iterator)
		if !(service > 0) {
			break
		}

		buf := common.NewCStr(512)
		ioRegistryEntryGetName(service, buf)

		if buf.GoString() == "pmgr" {
			pCoreRef := ioRegistryEntryCreateCFProperty(service, uintptr(pCorekey), common.KCFAllocatorDefault, common.KNilOptions)
			length := cfDataGetLength(uintptr(pCoreRef))
			data := cfDataGetBytePtr(uintptr(pCoreRef))

			// composite uint32 from the byte array
			buf := unsafe.Slice((*byte)(data), length)

			// combine the bytes into a uint32 value
			b := buf[length-8 : length-4]
			pCoreHz = binary.LittleEndian.Uint32(b)
			ioObjectRelease(service)
			break
		}

		ioObjectRelease(service)
	}

	return float64(pCoreHz / 1_000_000), nil
}