Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 10 additions & 18 deletions cpu/cpu_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,17 +61,17 @@ func Times(percpu bool) ([]TimesStat, error) {
}

func TimesWithContext(_ context.Context, percpu bool) ([]TimesStat, error) {
lib, err := common.NewLibrary(common.System)
sys, err := common.NewSystemLib()
if err != nil {
return nil, err
}
defer lib.Close()
defer sys.Close()

if percpu {
return perCPUTimes(lib)
return perCPUTimes(sys)
}

return allCPUTimes(lib)
return allCPUTimes(sys)
}

// Returns only one CPUInfoStat on FreeBSD
Expand Down Expand Up @@ -138,16 +138,12 @@ func CountsWithContext(_ context.Context, logical bool) (int, error) {
return int(count), nil
}

func perCPUTimes(machLib *common.Library) ([]TimesStat, error) {
machHostSelf := common.GetFunc[common.MachHostSelfFunc](machLib, common.MachHostSelfSym)
machTaskSelf := common.GetFunc[common.MachTaskSelfFunc](machLib, common.MachTaskSelfSym)
hostProcessorInfo := common.GetFunc[common.HostProcessorInfoFunc](machLib, common.HostProcessorInfoSym)
vmDeallocate := common.GetFunc[common.VMDeallocateFunc](machLib, common.VMDeallocateSym)

func perCPUTimes(sys *common.SystemLib) ([]TimesStat, error) {
var count, ncpu uint32
var cpuload *hostCpuLoadInfoData

status := hostProcessorInfo(machHostSelf(), processorCpuLoadInfo, &ncpu, uintptr(unsafe.Pointer(&cpuload)), &count)
status := sys.HostProcessorInfo(sys.MachHostSelf(), processorCpuLoadInfo,
&ncpu, uintptr(unsafe.Pointer(&cpuload)), &count)

if status != common.KERN_SUCCESS {
return nil, fmt.Errorf("host_processor_info error=%d", status)
Expand All @@ -157,7 +153,7 @@ func perCPUTimes(machLib *common.Library) ([]TimesStat, error) {
return nil, errors.New("host_processor_info returned nil cpuload")
}

defer vmDeallocate(machTaskSelf(), uintptr(unsafe.Pointer(cpuload)), uintptr(ncpu))
defer sys.VMDeallocate(sys.MachTaskSelf(), uintptr(unsafe.Pointer(cpuload)), uintptr(ncpu))

ret := []TimesStat{}
loads := unsafe.Slice(cpuload, ncpu)
Expand All @@ -170,21 +166,17 @@ func perCPUTimes(machLib *common.Library) ([]TimesStat, error) {
Nice: float64(loads[i].cpuTicks[cpuStateNice]) / ClocksPerSec,
Idle: float64(loads[i].cpuTicks[cpuStateIdle]) / ClocksPerSec,
}

ret = append(ret, c)
}

return ret, nil
}

func allCPUTimes(machLib *common.Library) ([]TimesStat, error) {
machHostSelf := common.GetFunc[common.MachHostSelfFunc](machLib, common.MachHostSelfSym)
hostStatistics := common.GetFunc[common.HostStatisticsFunc](machLib, common.HostStatisticsSym)

func allCPUTimes(sys *common.SystemLib) ([]TimesStat, error) {
var cpuload hostCpuLoadInfoData
count := uint32(cpuStateMax)

status := hostStatistics(machHostSelf(), common.HOST_CPU_LOAD_INFO,
status := sys.HostStatistics(sys.MachHostSelf(), common.HOST_CPU_LOAD_INFO,
uintptr(unsafe.Pointer(&cpuload)), &count)

if status != common.KERN_SUCCESS {
Expand Down
46 changes: 17 additions & 29 deletions cpu/cpu_darwin_arm64.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,68 +13,56 @@ import (

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

coreFoundation, err := common.NewLibrary(common.CoreFoundation)
corefoundation, err := common.NewCoreFoundationLib()
if err != nil {
return 0, err
}
defer coreFoundation.Close()
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")
matching := iokit.IOServiceMatching("AppleARMIODevice")

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

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

var pCoreHz uint32
for {
service := ioIteratorNext(iterator)
service := iokit.IOIteratorNext(iterator)
if service <= 0 {
break
}

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

if buf.GoString() == "pmgr" {
pCoreRef := ioRegistryEntryCreateCFProperty(service, uintptr(pCorekey), common.KCFAllocatorDefault, common.KNilOptions)
length := cfDataGetLength(uintptr(pCoreRef))
data := cfDataGetBytePtr(uintptr(pCoreRef))
pCoreRef := iokit.IORegistryEntryCreateCFProperty(service, uintptr(pCorekey), common.KCFAllocatorDefault, common.KNilOptions)
length := corefoundation.CFDataGetLength(uintptr(pCoreRef))
data := corefoundation.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)
cfRelease(uintptr(pCoreRef))
ioObjectRelease(service)
corefoundation.CFRelease(uintptr(pCoreRef))
iokit.IOObjectRelease(service)
break
}

ioObjectRelease(service)
iokit.IOObjectRelease(service)
}

return float64(pCoreHz / 1_000_000), nil
Expand Down
107 changes: 38 additions & 69 deletions disk/disk_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,58 +158,41 @@ func LabelWithContext(_ context.Context, _ string) (string, error) {
}

func IOCountersWithContext(_ context.Context, names ...string) (map[string]IOCountersStat, error) {
ioKit, err := common.NewLibrary(common.IOKit)
iokit, err := common.NewIOKitLib()
if err != nil {
return nil, err
}
defer ioKit.Close()
defer iokit.Close()

coreFoundation, err := common.NewLibrary(common.CoreFoundation)
corefoundation, err := common.NewCoreFoundationLib()
if err != nil {
return nil, err
}
defer coreFoundation.Close()
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)
ioObjectRelease := common.GetFunc[common.IOObjectReleaseFunc](ioKit, common.IOObjectReleaseSym)
match := iokit.IOServiceMatching("IOMedia")

cfDictionaryAddValue := common.GetFunc[common.CFDictionaryAddValueFunc](coreFoundation, common.CFDictionaryAddValueSym)
cfStringCreateWithCString := common.GetFunc[common.CFStringCreateWithCStringFunc](coreFoundation, common.CFStringCreateWithCStringSym)
cfRelease := common.GetFunc[common.CFReleaseFunc](coreFoundation, common.CFReleaseSym)
key := corefoundation.CFStringCreateWithCString(common.KCFAllocatorDefault, common.KIOMediaWholeKey, common.KCFStringEncodingUTF8)
defer corefoundation.CFRelease(uintptr(key))

kCFBooleanTruePtr, _ := coreFoundation.Dlsym("kCFBooleanTrue")

match := ioServiceMatching("IOMedia")

key := cfStringCreateWithCString(common.KCFAllocatorDefault, common.KIOMediaWholeKey, common.KCFStringEncodingUTF8)
defer cfRelease(uintptr(key))
kCFBooleanTruePtr, _ := corefoundation.Dlsym("kCFBooleanTrue")
kCFBooleanTrue := **(**uintptr)(unsafe.Pointer(&kCFBooleanTruePtr))
corefoundation.CFDictionaryAddValue(uintptr(match), uintptr(key), kCFBooleanTrue)

var drives uint32
kCFBooleanTrue := **(**uintptr)(unsafe.Pointer(&kCFBooleanTruePtr))
cfDictionaryAddValue(uintptr(match), uintptr(key), kCFBooleanTrue)
if status := ioServiceGetMatchingServices(common.KIOMainPortDefault, uintptr(match), &drives); status != common.KERN_SUCCESS {
if status := iokit.IOServiceGetMatchingServices(common.KIOMainPortDefault, uintptr(match), &drives); status != common.KERN_SUCCESS {
return nil, fmt.Errorf("IOServiceGetMatchingServices error=%d", status)
}
defer ioObjectRelease(drives)
defer iokit.IOObjectRelease(drives)

ic := &ioCounters{
ioKit: ioKit,
coreFoundation: coreFoundation,

ioRegistryEntryCreateCFProperties: common.GetFunc[common.IORegistryEntryCreateCFPropertiesFunc](ioKit, common.IORegistryEntryCreateCFPropertiesSym),
ioObjectRelease: ioObjectRelease,

cfStringCreateWithCString: cfStringCreateWithCString,
cfDictionaryGetValue: common.GetFunc[common.CFDictionaryGetValueFunc](coreFoundation, common.CFDictionaryGetValueSym),
cfNumberGetValue: common.GetFunc[common.CFNumberGetValueFunc](coreFoundation, common.CFNumberGetValueSym),
cfRelease: cfRelease,
iokit: iokit,
corefoundation: corefoundation,
}

stats := make([]IOCountersStat, 0, 16)
for {
d := ioIteratorNext(drives)
d := iokit.IOIteratorNext(drives)
if d <= 0 {
break
}
Expand All @@ -223,7 +206,7 @@ func IOCountersWithContext(_ context.Context, names ...string) (map[string]IOCou
stats = append(stats, *stat)
}

ioObjectRelease(d)
iokit.IOObjectRelease(d)
}

ret := make(map[string]IOCountersStat, 0)
Expand All @@ -243,9 +226,9 @@ func IOCountersWithContext(_ context.Context, names ...string) (map[string]IOCou
}

const (
kIOBSDNameKey = "BSD Name"
kIOMediaSizeKey = "Size"
kIOMediaPreferredBlockSizeKey = "Preferred Block Size"
kIOBSDNameKey = "BSD Name"
// kIOMediaSizeKey = "Size"
// kIOMediaPreferredBlockSizeKey = "Preferred Block Size"

kIOBlockStorageDriverStatisticsKey = "Statistics"
kIOBlockStorageDriverStatisticsBytesReadKey = "Bytes (Read)"
Expand All @@ -257,48 +240,34 @@ const (
)

type ioCounters struct {
ioKit *common.Library
coreFoundation *common.Library

ioRegistryEntryCreateCFProperties common.IORegistryEntryCreateCFPropertiesFunc
ioObjectRelease common.IOObjectReleaseFunc

cfStringCreateWithCString common.CFStringCreateWithCStringFunc
cfDictionaryGetValue common.CFDictionaryGetValueFunc
cfNumberGetValue common.CFNumberGetValueFunc
cfRelease common.CFReleaseFunc
iokit *common.IOKitLib
corefoundation *common.CoreFoundationLib
}

func (i *ioCounters) getDriveStat(d uint32) (*IOCountersStat, error) {
ioRegistryEntryGetParentEntry := common.GetFunc[common.IORegistryEntryGetParentEntryFunc](i.ioKit, common.IORegistryEntryGetParentEntrySym)
ioObjectConformsTo := common.GetFunc[common.IOObjectConformsToFunc](i.ioKit, common.IOObjectConformsToSym)

cfStringGetLength := common.GetFunc[common.CFStringGetLengthFunc](i.coreFoundation, common.CFStringGetLengthSym)
cfStringGetCString := common.GetFunc[common.CFStringGetCStringFunc](i.coreFoundation, common.CFStringGetCStringSym)

var parent uint32
if status := ioRegistryEntryGetParentEntry(d, common.KIOServicePlane, &parent); status != common.KERN_SUCCESS {
if status := i.iokit.IORegistryEntryGetParentEntry(d, common.KIOServicePlane, &parent); status != common.KERN_SUCCESS {
return nil, fmt.Errorf("IORegistryEntryGetParentEntry error=%d", status)
}
defer i.ioObjectRelease(parent)
defer i.iokit.IOObjectRelease(parent)

if !ioObjectConformsTo(parent, "IOBlockStorageDriver") {
if !i.iokit.IOObjectConformsTo(parent, "IOBlockStorageDriver") {
// return nil, fmt.Errorf("ERROR: the object is not of the IOBlockStorageDriver class")
return nil, nil
}

var props unsafe.Pointer
if status := i.ioRegistryEntryCreateCFProperties(d, unsafe.Pointer(&props), common.KCFAllocatorDefault, common.KNilOptions); status != common.KERN_SUCCESS {
if status := i.iokit.IORegistryEntryCreateCFProperties(d, unsafe.Pointer(&props), common.KCFAllocatorDefault, common.KNilOptions); status != common.KERN_SUCCESS {
return nil, fmt.Errorf("IORegistryEntryCreateCFProperties error=%d", status)
}
defer i.cfRelease(uintptr(props))
defer i.corefoundation.CFRelease(uintptr(props))

key := i.cfStr(kIOBSDNameKey)
defer i.cfRelease(uintptr(key))
name := i.cfDictionaryGetValue(uintptr(props), uintptr(key))
defer i.corefoundation.CFRelease(uintptr(key))
name := i.corefoundation.CFDictionaryGetValue(uintptr(props), uintptr(key))

buf := common.NewCStr(cfStringGetLength(uintptr(name)))
cfStringGetCString(uintptr(name), buf, buf.Length(), common.KCFStringEncodingUTF8)
buf := common.NewCStr(i.corefoundation.CFStringGetLength(uintptr(name)))
i.corefoundation.CFStringGetCString(uintptr(name), buf, buf.Length(), common.KCFStringEncodingUTF8)

stat, err := i.fillStat(parent)
if err != nil {
Expand All @@ -314,19 +283,19 @@ func (i *ioCounters) getDriveStat(d uint32) (*IOCountersStat, error) {

func (i *ioCounters) fillStat(d uint32) (*IOCountersStat, error) {
var props unsafe.Pointer
status := i.ioRegistryEntryCreateCFProperties(d, unsafe.Pointer(&props), common.KCFAllocatorDefault, common.KNilOptions)
status := i.iokit.IORegistryEntryCreateCFProperties(d, unsafe.Pointer(&props), common.KCFAllocatorDefault, common.KNilOptions)
if status != common.KERN_SUCCESS {
return nil, fmt.Errorf("IORegistryEntryCreateCFProperties error=%d", status)
}
if props == nil {
return nil, nil
}
defer i.cfRelease(uintptr(props))
defer i.corefoundation.CFRelease(uintptr(props))

key := i.cfStr(kIOBlockStorageDriverStatisticsKey)
defer i.cfRelease(uintptr(key))
defer i.corefoundation.CFRelease(uintptr(key))

v := i.cfDictionaryGetValue(uintptr(props), uintptr(key))
v := i.corefoundation.CFDictionaryGetValue(uintptr(props), uintptr(key))
if v == nil {
return nil, errors.New("CFDictionaryGetValue failed")
}
Expand All @@ -343,15 +312,15 @@ func (i *ioCounters) fillStat(d uint32) (*IOCountersStat, error) {

for key, off := range statstab {
s := i.cfStr(key)
if num := i.cfDictionaryGetValue(uintptr(v), uintptr(s)); num != nil {
i.cfNumberGetValue(uintptr(num), common.KCFNumberSInt64Type, uintptr(unsafe.Add(unsafe.Pointer(&stat), off)))
if num := i.corefoundation.CFDictionaryGetValue(uintptr(v), uintptr(s)); num != nil {
i.corefoundation.CFNumberGetValue(uintptr(num), common.KCFNumberSInt64Type, uintptr(unsafe.Add(unsafe.Pointer(&stat), off)))
}
i.cfRelease(uintptr(s))
i.corefoundation.CFRelease(uintptr(s))
}

return &stat, nil
}

func (i *ioCounters) cfStr(str string) unsafe.Pointer {
return i.cfStringCreateWithCString(common.KCFAllocatorDefault, str, common.KCFStringEncodingUTF8)
return i.corefoundation.CFStringCreateWithCString(common.KCFAllocatorDefault, str, common.KCFStringEncodingUTF8)
}
Loading