- remove C bridge for IntelPowerGadget framework

- remove IntelPowerGadget framework dependency
- add IntelPowerGadget dynamic load if x86
- enable universal build (from now supports Apple Silicon) (#181)
This commit is contained in:
Serhiy Mytrovtsiy
2020-11-24 00:11:02 +01:00
parent 3909be70b9
commit 5974548d56
6 changed files with 159 additions and 153 deletions

View File

@@ -1,81 +0,0 @@
//
// CPU.c
// CPU
//
// Created by Serhiy Mytrovtsiy on 13/10/2020.
// Using Swift 5.0.
// Running on macOS 10.15.
//
// Copyright © 2020 Serhiy Mytrovtsiy. All rights reserved.
//
#include "CPU.h"
#include <unistd.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <sched.h>
#include <IntelPowerGadget/PowerGadgetLib.h>
pthread_t thread_id;
double CPUFrequency;
bool stop;
double min;
double max;
PGSampleID sampleID_1;
PGSampleID sampleID_2;
extern bool PG_Initialize(void) __attribute__((weak_import));
static inline bool intelPowerGadgetIsAvailable() {
return (PG_Initialize != NULL);
}
void *listener () {
while(stop == false) {
PG_ReadSample(0, &sampleID_1);
sleep(1);
PG_ReadSample(0, &sampleID_2);
PGSample_GetIAFrequency(sampleID_1, sampleID_2, &CPUFrequency, &min, &max);
PGSample_Release(sampleID_2);
PGSample_Release(sampleID_1);
}
pthread_exit(NULL);
}
void PG_start() {
if (intelPowerGadgetIsAvailable() == false) {
return;
}
stop = false;
PG_Initialize();
pthread_create(&thread_id, NULL, listener, NULL);
}
void PG_stop() {
if (intelPowerGadgetIsAvailable() == false) {
return;
}
stop = true;
PG_Shutdown();
}
double* PG_getCPUFrequency() {
if (intelPowerGadgetIsAvailable() == false) {
return NULL;
}
if (stop == true || CPUFrequency == 0) {
return NULL;
} else {
return &CPUFrequency;
}
return NULL;
}

View File

@@ -1,15 +0,0 @@
//
// CPU.h
// CPU
//
// Created by Serhiy Mytrovtsiy on 13/10/2020.
// Using Swift 5.0.
// Running on macOS 10.15.
//
// Copyright © 2020 Serhiy Mytrovtsiy. All rights reserved.
//
void PG_start(void);
void PG_stop(void);
double* PG_getCPUFrequency(void);

View File

@@ -25,18 +25,14 @@ public struct CPU_Load: value_t {
}
}
public struct CPU_additional {
var temperature: Double?
var frequency: Double?
}
public class CPU: Module {
private var popupView: Popup
private var settingsView: Settings
private var loadReader: LoadReader? = nil
private var processReader: ProcessReader? = nil
private var additionalReader: AdditionalReader? = nil
private var temperatureReader: TemperatureReader? = nil
private var frequencyReader: FrequencyReader? = nil
private let smc: UnsafePointer<SMCService>?
private let store: UnsafePointer<Store>
@@ -59,12 +55,15 @@ public class CPU: Module {
)
guard self.available else { return }
PG_start()
self.loadReader = LoadReader()
self.loadReader?.store = store
self.processReader = ProcessReader(self.config.name, store: store)
self.additionalReader = AdditionalReader(smc)
self.temperatureReader = TemperatureReader(smc)
#if arch(x86_64)
self.frequencyReader = FrequencyReader()
#endif
self.settingsView.callback = { [unowned self] in
self.loadReader?.read()
@@ -92,9 +91,14 @@ public class CPU: Module {
}
}
self.additionalReader?.callbackHandler = { [unowned self] value in
self.temperatureReader?.callbackHandler = { [unowned self] value in
if value != nil {
self.popupView.additionalCallback(value!)
self.popupView.temperatureCallback(value!)
}
}
self.frequencyReader?.callbackHandler = { [unowned self] value in
if value != nil {
self.popupView.frequencyCallback(value!)
}
}
@@ -104,13 +108,12 @@ public class CPU: Module {
if let reader = self.processReader {
self.addReader(reader)
}
if let reader = self.additionalReader {
if let reader = self.temperatureReader {
self.addReader(reader)
}
if let reader = self.frequencyReader {
self.addReader(reader)
}
}
public override func willTerminate() {
PG_stop()
}
private func loadCallback(_ value: CPU_Load?) {

View File

@@ -35,8 +35,9 @@ internal class Popup: NSView, Popup_p {
private var temperatureCircle: HalfCircleGraphView? = nil
private var frequencyCircle: HalfCircleGraphView? = nil
private var initialized: Bool = false
private var initializedAdditional: Bool = false
private var processesInitialized: Bool = false
private var initializedTemperature: Bool = false
private var initializedFrequency: Bool = false
private var initializedProcesses: Bool = false
private var processes: [ProcessView] = []
private var maxFreq: Double = 0
@@ -107,7 +108,7 @@ internal class Popup: NSView, Popup_p {
self.grid?.row(at: 3).cell(at: 0).contentView?.removeFromSuperview()
self.grid?.removeRow(at: 3)
self.grid?.addRow(with: [self.initProcesses()])
self.processesInitialized = false
self.initializedProcesses = false
self.sizeCallback?(self.frame.size)
})
@@ -207,36 +208,40 @@ internal class Popup: NSView, Popup_p {
})
}
public func additionalCallback(_ value: CPU_additional) {
public func temperatureCallback(_ value: Double) {
DispatchQueue.main.async(execute: {
if value.frequency != nil && self.frequencyCircle != nil && (self.frequencyCircle! as NSView).isHidden {
if (self.window?.isVisible ?? false) || !self.initializedTemperature {
self.temperatureCircle?.setValue(value)
self.temperatureCircle?.setText(Temperature(value))
self.initializedTemperature = true
}
})
}
public func frequencyCallback(_ value: Double) {
DispatchQueue.main.async(execute: {
if self.frequencyCircle != nil && (self.frequencyCircle! as NSView).isHidden {
(self.frequencyCircle! as NSView).isHidden = false
}
if (self.window?.isVisible ?? false) || !self.initializedAdditional {
if let temperature = value.temperature {
self.temperatureCircle?.setValue(temperature)
self.temperatureCircle?.setText(Temperature(temperature))
}
if let freq = value.frequency {
if freq > self.maxFreq {
self.maxFreq = freq
}
if let freqCircle = self.frequencyCircle {
freqCircle.setValue((100*freq)/self.maxFreq)
freqCircle.setText("\((freq/1000).rounded(toPlaces: 2))\nGHz")
}
if (self.window?.isVisible ?? false) || !self.initializedFrequency {
if value > self.maxFreq {
self.maxFreq = value
}
self.initializedAdditional = true
if let freqCircle = self.frequencyCircle {
freqCircle.setValue((100*value)/self.maxFreq)
freqCircle.setText("\((value/1000).rounded(toPlaces: 2))\nGHz")
}
self.initializedFrequency = true
}
})
}
public func processCallback(_ list: [TopProcess]) {
DispatchQueue.main.async(execute: {
if !(self.window?.isVisible ?? false) && self.processesInitialized {
if !(self.window?.isVisible ?? false) && self.initializedProcesses {
return
}
@@ -253,7 +258,7 @@ internal class Popup: NSView, Popup_p {
self.processes[index].value = "\(process.usage)%"
}
self.processesInitialized = true
self.initializedProcesses = true
})
}
}

View File

@@ -230,9 +230,8 @@ public class ProcessReader: Reader<[TopProcess]> {
}
}
public class AdditionalReader: Reader<CPU_additional> {
public class TemperatureReader: Reader<Double> {
private let smc: UnsafePointer<SMCService>?
private var data: CPU_additional = CPU_additional()
init(_ smc: UnsafePointer<SMCService>) {
self.smc = smc
@@ -240,18 +239,123 @@ public class AdditionalReader: Reader<CPU_additional> {
self.popup = true
}
public override func read() {
let temperature = self.smc?.pointee.getValue("TC0C") ?? self.smc?.pointee.getValue("TC0D") ?? self.smc?.pointee.getValue("TC0P") ?? self.smc?.pointee.getValue("TC0E") ?? self.smc?.pointee.getValue("TC0F")
self.callback(temperature)
}
}
public class FrequencyReader: Reader<Double> {
private typealias PGSample = UInt64
private typealias UDouble = UnsafeMutablePointer<Double>
private typealias PG_InitializePointerFunction = @convention(c) () -> Bool
private typealias PG_ShutdownPointerFunction = @convention(c) () -> Bool
private typealias PG_ReadSamplePointerFunction = @convention(c) (Int, UnsafeMutablePointer<PGSample>) -> Bool
private typealias PGSample_GetIAFrequencyPointerFunction = @convention(c) (PGSample, PGSample, UDouble, UDouble, UDouble) -> Bool
private typealias PGSample_ReleasePointerFunction = @convention(c) (PGSample) -> Bool
private var bundle: CFBundle? = nil
private var PG_Shutdown: PG_ShutdownPointerFunction? = nil
private var PG_ReadSample: PG_ReadSamplePointerFunction? = nil
private var PGSample_GetIAFrequency: PGSample_GetIAFrequencyPointerFunction? = nil
private var PGSample_Release: PGSample_ReleasePointerFunction? = nil
private var sample: PGSample = 0
public override func setup() {
PG_getCPUFrequency()
PG_getCPUFrequency()
let path: CFString = "/Library/Frameworks/IntelPowerGadget.framework" as CFString
let bundleURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, path, CFURLPathStyle.cfurlposixPathStyle, true)
self.bundle = CFBundleCreate(kCFAllocatorDefault, bundleURL)
if self.bundle == nil {
os_log(.error, log: log, "IntelPowerGadget framework not found")
return
}
if !CFBundleLoadExecutable(self.bundle) {
os_log(.error, log: log, "failed to load IPG framework")
return
}
let PG_InitializePointer = CFBundleGetFunctionPointerForName(self.bundle, "PG_Initialize" as CFString)
let PG_ShutdownPointer = CFBundleGetFunctionPointerForName(self.bundle, "PG_Shutdown" as CFString)
let PG_ReadSamplePointer = CFBundleGetFunctionPointerForName(self.bundle, "PG_ReadSample" as CFString)
let PGSample_GetIAFrequencyPointer = CFBundleGetFunctionPointerForName(self.bundle, "PGSample_GetIAFrequency" as CFString)
let PGSample_ReleasePointer = CFBundleGetFunctionPointerForName(self.bundle, "PGSample_Release" as CFString)
let PG_Initialize = unsafeBitCast(PG_InitializePointer, to: PG_InitializePointerFunction.self)
self.PG_Shutdown = unsafeBitCast(PG_ShutdownPointer, to: PG_ShutdownPointerFunction.self)
self.PG_ReadSample = unsafeBitCast(PG_ReadSamplePointer, to: PG_ReadSamplePointerFunction.self)
self.PGSample_GetIAFrequency = unsafeBitCast(PGSample_GetIAFrequencyPointer, to: PGSample_GetIAFrequencyPointerFunction.self)
self.PGSample_Release = unsafeBitCast(PGSample_ReleasePointer, to: PGSample_ReleasePointerFunction.self)
if !PG_Initialize() {
os_log(.error, log: log, "IPG initialization failed")
return
}
}
deinit {
if let bundle = self.bundle {
CFBundleUnloadExecutable(bundle)
}
}
public override func terminate() {
if let shutdown = self.PG_Shutdown {
if !shutdown() {
os_log(.error, log: log, "IPG shutdown failed")
return
}
}
if let release = self.PGSample_Release {
if self.sample != 0 {
_ = release(self.sample)
return
}
}
}
public override func read() {
if let readFrequency = PG_getCPUFrequency() {
self.data.frequency = readFrequency.pointee
if self.PG_ReadSample == nil || self.PGSample_GetIAFrequency == nil || self.PGSample_Release == nil {
return
}
self.data.temperature = self.smc?.pointee.getValue("TC0C") ?? self.smc?.pointee.getValue("TC0D") ?? self.smc?.pointee.getValue("TC0P") ?? self.smc?.pointee.getValue("TC0E") ?? self.smc?.pointee.getValue("TC0F")
// first sample initlialization
if self.sample == 0 {
if !self.PG_ReadSample!(0, &self.sample) {
os_log(.error, log: log, "read self.sample failed")
}
return
}
self.callback(self.data)
var local: PGSample = 0
if !self.PG_ReadSample!(0, &local) {
os_log(.error, log: log, "read local sample failed")
return
}
var value: Double = 0
var min: Double = 0
var max: Double = 0
if !self.PGSample_GetIAFrequency!(self.sample, local, &value, &min, &max) {
os_log(.error, log: log, "read frequency failed")
return
}
self.callback(value)
if !self.PGSample_Release!(self.sample) {
os_log(.error, log: log, "release self.sample failed")
return
}
self.sample = local
}
}

View File

@@ -17,7 +17,6 @@
9A0C82EE2446124800FAE3D4 /* SystemKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A7D0CB62444C2C800B09070 /* SystemKit.swift */; };
9A1A7ABA24561F0B00A84F7A /* BarChart.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A1A7AB924561F0B00A84F7A /* BarChart.swift */; };
9A1D5E4B25235C8100B82BFC /* helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A1D5E4A25235C8100B82BFC /* helpers.swift */; };
9A27D49D25389E08001BB651 /* IntelPowerGadget.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9A97CE2A25371B2300742D8F /* IntelPowerGadget.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
9A27D4FD2538A3E5001BB651 /* Repeat in Frameworks */ = {isa = PBXBuildFile; productRef = 9A27D4FC2538A3E5001BB651 /* Repeat */; };
9A27D5352538A456001BB651 /* Reachability in Frameworks */ = {isa = PBXBuildFile; productRef = 9A27D5342538A456001BB651 /* Reachability */; };
9A34353B243E278D006B19F9 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A34353A243E278D006B19F9 /* main.swift */; };
@@ -69,7 +68,6 @@
9A944D5D24492A8B0058F32A /* popup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A944D5C24492A8B0058F32A /* popup.swift */; };
9A944D5F24492AA60058F32A /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A944D5E24492AA60058F32A /* Constants.swift */; };
9A953A1424B9D22D0038EF4B /* settings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A953A1324B9D22D0038EF4B /* settings.swift */; };
9A97CECE2537331B00742D8F /* CPU.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A97CECC2537331B00742D8F /* CPU.h */; settings = {ATTRIBUTES = (Public, ); }; };
9A97CED12537331B00742D8F /* CPU.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9A97CECA2537331B00742D8F /* CPU.framework */; };
9A97CED22537331B00742D8F /* CPU.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9A97CECA2537331B00742D8F /* CPU.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
9A97CEE92537338600742D8F /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A97CEE82537338600742D8F /* main.swift */; };
@@ -79,7 +77,6 @@
9A97CF002537340400742D8F /* config.plist in Resources */ = {isa = PBXBuildFile; fileRef = 9A97CEFF2537340400742D8F /* config.plist */; };
9A97CF072537351600742D8F /* ModuleKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9AABEADD243FB13500668CB0 /* ModuleKit.framework */; };
9A97CF0C2537351800742D8F /* StatsKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9A0C82DA24460F7200FAE3D4 /* StatsKit.framework */; };
9A97CF2A25373C8400742D8F /* CPU.c in Sources */ = {isa = PBXBuildFile; fileRef = 9A97CF2925373C8400742D8F /* CPU.c */; };
9A9B25BB24F7DE2B00C3CCE6 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 9A9B25BD24F7DE2B00C3CCE6 /* Localizable.strings */; };
9A9D728A24471FAE005CF997 /* SMC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A9D728924471FAE005CF997 /* SMC.swift */; };
9A9EA9452476D34500E3B883 /* Update.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A9EA9442476D34500E3B883 /* Update.swift */; };
@@ -432,14 +429,12 @@
9A953A1324B9D22D0038EF4B /* settings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = settings.swift; sourceTree = "<group>"; };
9A97CE2A25371B2300742D8F /* IntelPowerGadget.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IntelPowerGadget.framework; path = ../../../Library/Frameworks/IntelPowerGadget.framework; sourceTree = "<group>"; };
9A97CECA2537331B00742D8F /* CPU.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = CPU.framework; sourceTree = BUILT_PRODUCTS_DIR; };
9A97CECC2537331B00742D8F /* CPU.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CPU.h; sourceTree = "<group>"; };
9A97CECD2537331B00742D8F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
9A97CEE82537338600742D8F /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = "<group>"; };
9A97CEF0253733D200742D8F /* readers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = readers.swift; sourceTree = "<group>"; };
9A97CEF5253733E400742D8F /* popup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = popup.swift; sourceTree = "<group>"; };
9A97CEFA253733F300742D8F /* settings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = settings.swift; sourceTree = "<group>"; };
9A97CEFF2537340400742D8F /* config.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = config.plist; sourceTree = "<group>"; };
9A97CF2925373C8400742D8F /* CPU.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = CPU.c; sourceTree = "<group>"; };
9A998CD722A199920087ADE7 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
9A998CD922A199970087ADE7 /* ServiceManagement.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ServiceManagement.framework; path = System/Library/Frameworks/ServiceManagement.framework; sourceTree = SDKROOT; };
9A9B25BC24F7DE2B00C3CCE6 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
@@ -558,7 +553,6 @@
buildActionMask = 2147483647;
files = (
9A97CF072537351600742D8F /* ModuleKit.framework in Frameworks */,
9A27D49D25389E08001BB651 /* IntelPowerGadget.framework in Frameworks */,
9A97CF0C2537351800742D8F /* StatsKit.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -769,8 +763,6 @@
9A97CEFA253733F300742D8F /* settings.swift */,
9A97CECD2537331B00742D8F /* Info.plist */,
9A97CEFF2537340400742D8F /* config.plist */,
9A97CECC2537331B00742D8F /* CPU.h */,
9A97CF2925373C8400742D8F /* CPU.c */,
);
path = CPU;
sourceTree = "<group>";
@@ -906,7 +898,6 @@
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
9A97CECE2537331B00742D8F /* CPU.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1497,7 +1488,6 @@
9A97CEF6253733E400742D8F /* popup.swift in Sources */,
9A97CEFB253733F300742D8F /* settings.swift in Sources */,
9A97CEE92537338600742D8F /* main.swift in Sources */,
9A97CF2A25373C8400742D8F /* CPU.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1836,7 +1826,7 @@
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
EXCLUDED_ARCHS = arm64;
EXCLUDED_ARCHS = "";
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
@@ -1903,7 +1893,7 @@
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
EXCLUDED_ARCHS = arm64;
EXCLUDED_ARCHS = "";
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;