Skip to content

Commit

Permalink
Add GPUMeter code for Darwin
Browse files Browse the repository at this point in the history
Co-authored-by: Matteo Nicoli <[email protected]>
Signed-off-by: Kang-Che Sung <[email protected]>
  • Loading branch information
Explorer09 and aestriplex committed Feb 23, 2025
1 parent 33fd5be commit a2b80a7
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 0 deletions.
1 change: 1 addition & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,7 @@ darwin_platform_headers = \
zfs/ZfsCompressedArcMeter.h

darwin_platform_sources = \
GPUMeter.c \
darwin/Platform.c \
darwin/PlatformHelpers.c \
darwin/DarwinMachine.c \
Expand Down
7 changes: 7 additions & 0 deletions darwin/DarwinMachine.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,12 +105,19 @@ Machine* Machine_new(UsersTable* usersTable, uid_t userId) {
openzfs_sysctl_init(&this->zfs);
openzfs_sysctl_updateArcStats(&this->zfs);

this->GPUService = IOServiceGetMatchingService(kIOMainPortDefault, IOServiceMatching("IOGPU"));
if (!this->GPUService) {
CRT_debug("Cannot initialize IOGPU service");
}

return super;
}

void Machine_delete(Machine* super) {
DarwinMachine* this = (DarwinMachine*) super;

IOObjectRelease(this->GPUService);

DarwinMachine_freeCPULoadInfo(&this->prev_load);

Machine_done(super);
Expand Down
3 changes: 3 additions & 0 deletions darwin/DarwinMachine.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Released under the GNU GPLv2+, see the COPYING file
in the source distribution for its full text.
*/

#include <IOKit/IOKitLib.h>
#include <mach/mach_host.h>
#include <sys/sysctl.h>

Expand All @@ -26,6 +27,8 @@ typedef struct DarwinMachine_ {
processor_cpu_load_info_t prev_load;
processor_cpu_load_info_t curr_load;

io_service_t GPUService;

ZfsArcStats zfs;
} DarwinMachine;

Expand Down
54 changes: 54 additions & 0 deletions darwin/Platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ in the source distribution for its full text.

#include "darwin/Platform.h"

#include <assert.h>
#include <errno.h>
#include <math.h>
#include <stdlib.h>
Expand Down Expand Up @@ -38,6 +39,7 @@ in the source distribution for its full text.
#include "DateMeter.h"
#include "DateTimeMeter.h"
#include "FileDescriptorMeter.h"
#include "GPUMeter.h"
#include "HostnameMeter.h"
#include "LoadAverageMeter.h"
#include "Macros.h"
Expand Down Expand Up @@ -144,6 +146,7 @@ const MeterClass* const Platform_meterTypes[] = {
&DiskIOMeter_class,
&NetworkIOMeter_class,
&FileDescriptorMeter_class,
&GPUMeter_class,
&BlankMeter_class,
NULL
};
Expand Down Expand Up @@ -284,6 +287,57 @@ double Platform_setCPUValues(Meter* mtr, unsigned int cpu) {
return CLAMP(total, 0.0, 100.0);
}

void Platform_setGPUValues(Meter* mtr, double* totalUsage, unsigned long long* totalGPUTimeDiff) {
const Machine* host = mtr->host;
const DarwinMachine* dhost = (const DarwinMachine *)host;

assert(*totalGPUTimeDiff == -1ULL);
(void)totalGPUTimeDiff;

mtr->curItems = 1;
mtr->values[0] = NAN;

if (!dhost->GPUService)
return;

static uint64_t prevMonotonicMs;

// Ensure there is a small time interval between the creation of the
// CF property tables. If this function is called in quick successions
// (e.g. for multiple meter instances), we might get "0% utilization"
// as a result.
if (host->monotonicMs <= prevMonotonicMs) {
mtr->values[0] = *totalUsage;
return;
}

CFMutableDictionaryRef properties = NULL;
kern_return_t ret = IORegistryEntryCreateCFProperties(dhost->GPUService, &properties, kCFAllocatorDefault, kNilOptions);
if (ret != KERN_SUCCESS || !properties)
return;

CFDictionaryRef perfStats = CFDictionaryGetValue(properties, CFSTR("PerformanceStatistics"));
if (!perfStats)
goto cleanup;

assert(CFGetTypeID(perfStats) == CFDictionaryGetTypeID());

CFNumberRef deviceUtil = CFDictionaryGetValue(perfStats, CFSTR("Device Utilization %"));
if (!deviceUtil)
goto cleanup;

int device = -1;
CFNumberGetValue(deviceUtil, kCFNumberIntType, &device);
*totalUsage = (double)device;

prevMonotonicMs = host->monotonicMs;

cleanup:
CFRelease(properties);

mtr->values[0] = *totalUsage;
}

void Platform_setMemoryValues(Meter* mtr) {
const DarwinMachine* dhost = (const DarwinMachine*) mtr->host;
#ifdef HAVE_STRUCT_VM_STATISTICS64
Expand Down
2 changes: 2 additions & 0 deletions darwin/Platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ pid_t Platform_getMaxPid(void);

double Platform_setCPUValues(Meter* mtr, unsigned int cpu);

void Platform_setGPUValues(Meter* mtr, double* totalUsage, unsigned long long* totalGPUTimeDiff);

void Platform_setMemoryValues(Meter* mtr);

void Platform_setSwapValues(Meter* mtr);
Expand Down

0 comments on commit a2b80a7

Please sign in to comment.