Skip to content
Closed
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
84 changes: 19 additions & 65 deletions linux/GPUMeter.c → GPUMeter.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,29 +7,15 @@ in the source distribution for its full text.

#include "config.h" // IWYU pragma: keep

#include "linux/GPUMeter.h"
#include "GPUMeter.h"

#include "CRT.h"
#include "Platform.h"
#include "RichString.h"
#include "linux/LinuxMachine.h"
#include "XUtils.h"


static size_t activeMeters;

bool GPUMeter_active(void) {
return activeMeters > 0;
}

struct EngineData {
const char* key; /* owned by LinuxMachine */
unsigned long long int timeDiff;
};

static struct EngineData GPUMeter_engineData[4];
static unsigned long long int prevResidueTime, curResidueTime;
static double totalUsage;
static unsigned long long int totalGPUTimeDiff;

static const int GPUMeter_attributes[] = {
GPU_ENGINE_1,
GPU_ENGINE_2,
Expand All @@ -38,6 +24,10 @@ static const int GPUMeter_attributes[] = {
GPU_RESIDUE,
};

bool GPUMeter_active(void) {
return activeMeters > 0;
}

static int humanTimeUnit(char* buffer, size_t size, unsigned long long int value) {

if (value < 1000)
Expand Down Expand Up @@ -84,71 +74,35 @@ static int humanTimeUnit(char* buffer, size_t size, unsigned long long int value

static void GPUMeter_updateValues(Meter* this) {
const Machine* host = this->host;
const LinuxMachine* lhost = (const LinuxMachine*) host;
const GPUEngineData* gpuEngineData;
char* buffer = this->txtBuffer;
size_t size = sizeof(this->txtBuffer);
int written;
unsigned int i;
uint64_t monotonictimeDelta;

assert(ARRAYSIZE(GPUMeter_engineData) + 1 == ARRAYSIZE(GPUMeter_attributes));

totalGPUTimeDiff = saturatingSub(lhost->curGpuTime, lhost->prevGpuTime);
monotonictimeDelta = host->monotonicMs - host->prevMonotonicMs;

prevResidueTime = curResidueTime;
curResidueTime = lhost->curGpuTime;

for (gpuEngineData = lhost->gpuEngineData, i = 0; gpuEngineData && i < ARRAYSIZE(GPUMeter_engineData); gpuEngineData = gpuEngineData->next, i++) {
GPUMeter_engineData[i].key = gpuEngineData->key;
GPUMeter_engineData[i].timeDiff = saturatingSub(gpuEngineData->curTime, gpuEngineData->prevTime);

curResidueTime = saturatingSub(curResidueTime, gpuEngineData->curTime);

this->values[i] = 100.0 * GPUMeter_engineData[i].timeDiff / (1000 * 1000) / monotonictimeDelta;
if (!isNonnegative(host->totalGPUUsage)) {
this->values[0] = 0;
int written = xSnprintf(buffer, size, "N/A");
METER_BUFFER_CHECK(buffer, size, written);
return;
}

this->values[ARRAYSIZE(GPUMeter_engineData)] = 100.0 * saturatingSub(curResidueTime, prevResidueTime) / (1000 * 1000) / monotonictimeDelta;

totalUsage = 100.0 * totalGPUTimeDiff / (1000 * 1000) / monotonictimeDelta;
written = snprintf(buffer, size, "%.1f", totalUsage);
int written = xSnprintf(buffer, size, "%.1f", host->totalGPUUsage);
METER_BUFFER_CHECK(buffer, size, written);

METER_BUFFER_APPEND_CHR(buffer, size, '%');
}

static void GPUMeter_display(const Object* cast, RichString* out) {
const Meter* this = (const Meter*)cast;
const Machine* host = this->host;

char buffer[50];
int written;
const Meter* this = (const Meter*)cast;
unsigned int i;

RichString_writeAscii(out, CRT_colors[METER_TEXT], ":");
written = xSnprintf(buffer, sizeof(buffer), "%4.1f", totalUsage);
written = xSnprintf(buffer, sizeof(buffer), "%4.1f", host->totalGPUUsage);
RichString_appendnAscii(out, CRT_colors[METER_VALUE], buffer, written);
RichString_appendnAscii(out, CRT_colors[METER_TEXT], "%(", 2);
written = humanTimeUnit(buffer, sizeof(buffer), totalGPUTimeDiff);
written = humanTimeUnit(buffer, sizeof(buffer), host->totalGPUTimeDiff);
RichString_appendnAscii(out, CRT_colors[METER_VALUE], buffer, written);
RichString_appendnAscii(out, CRT_colors[METER_TEXT], ")", 1);

for (i = 0; i < ARRAYSIZE(GPUMeter_engineData); i++) {
if (!GPUMeter_engineData[i].key)
break;

RichString_appendnAscii(out, CRT_colors[METER_TEXT], " ", 1);
RichString_appendAscii(out, CRT_colors[METER_TEXT], GPUMeter_engineData[i].key);
RichString_appendnAscii(out, CRT_colors[METER_TEXT], ":", 1);
if (isNonnegative(this->values[i]))
written = xSnprintf(buffer, sizeof(buffer), "%4.1f", this->values[i]);
else
written = xSnprintf(buffer, sizeof(buffer), " N/A");
RichString_appendnAscii(out, CRT_colors[METER_VALUE], buffer, written);
RichString_appendnAscii(out, CRT_colors[METER_TEXT], "%(", 2);
written = humanTimeUnit(buffer, sizeof(buffer), GPUMeter_engineData[i].timeDiff);
RichString_appendnAscii(out, CRT_colors[METER_VALUE], buffer, written);
RichString_appendnAscii(out, CRT_colors[METER_TEXT], ")", 1);
}
}

static void GPUMeter_init(Meter* this ATTR_UNUSED) {
Expand All @@ -171,7 +125,7 @@ const MeterClass GPUMeter_class = {
.updateValues = GPUMeter_updateValues,
.defaultMode = BAR_METERMODE,
.supportedModes = METERMODE_DEFAULT_SUPPORTED,
.maxItems = ARRAYSIZE(GPUMeter_engineData) + 1,
.maxItems = ARRAYSIZE(GPUMeter_attributes),
.total = 100.0,
.attributes = GPUMeter_attributes,
.name = "GPU",
Expand Down
4 changes: 4 additions & 0 deletions linux/GPUMeter.h → GPUMeter.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ in the source distribution for its full text.

#include "Meter.h"

struct EngineData {
const char* key;
unsigned long long int timeDiff;
};

extern const MeterClass GPUMeter_class;

Expand Down
5 changes: 5 additions & 0 deletions Machine.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ typedef struct Machine_ {
unsigned int activeCPUs;
unsigned int existingCPUs;

double totalGPUUsage;
unsigned long long int totalGPUTimeDiff;

UsersTable* usersTable;
uid_t htopUserId;
uid_t maxUserId; /* recently observed */
Expand Down Expand Up @@ -94,4 +97,6 @@ void Machine_scan(Machine* this);

void Machine_scanTables(Machine* this);

void Machine_scanGPUUsage(Machine* super);

#endif
4 changes: 2 additions & 2 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ myhtopsources = \
EnvScreen.c \
FileDescriptorMeter.c \
FunctionBar.c \
GPUMeter.c \
Hashtable.c \
Header.c \
HeaderOptionsPanel.c \
Expand Down Expand Up @@ -119,6 +120,7 @@ myhtopheaders = \
EnvScreen.h \
FileDescriptorMeter.h \
FunctionBar.h \
GPUMeter.h \
Hashtable.h \
Header.h \
HeaderLayout.h \
Expand Down Expand Up @@ -174,7 +176,6 @@ linux_platform_headers = \
generic/uname.h \
linux/CGroupUtils.h \
linux/GPU.h \
linux/GPUMeter.h \
linux/HugePageMeter.h \
linux/IOPriority.h \
linux/IOPriorityPanel.h \
Expand All @@ -200,7 +201,6 @@ linux_platform_sources = \
generic/uname.c \
linux/CGroupUtils.c \
linux/GPU.c \
linux/GPUMeter.c \
linux/HugePageMeter.c \
linux/IOPriorityPanel.c \
linux/LibSensors.c \
Expand Down
48 changes: 48 additions & 0 deletions darwin/DarwinMachine.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ in the source distribution for its full text.
#include <unistd.h>
#include <sys/mman.h>
#include <sys/sysctl.h>
#include <CoreFoundation/CoreFoundation.h>
#include <IOKit/IOKitLib.h>

#include "CRT.h"
#include "Machine.h"
Expand Down Expand Up @@ -84,6 +86,7 @@ void Machine_scan(Machine* super) {
DarwinMachine_allocateCPULoadInfo(&host->curr_load);
DarwinMachine_getVMStats(host);
openzfs_sysctl_updateArcStats(&host->zfs);
Machine_scanGPUUsage(super);
}

Machine* Machine_new(UsersTable* usersTable, uid_t userId) {
Expand All @@ -105,12 +108,23 @@ 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) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A space

Suggested change
if(!this->GPUService) {
if (!this->GPUService) {

CRT_debug("Cannot create macOS GPUService");
}

/* Initialize GPU metric read-out */
super->totalGPUUsage = NAN;
super->totalGPUTimeDiff = (unsigned long long)-1;

return super;
}

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

IOObjectRelease(this->GPUService);

DarwinMachine_freeCPULoadInfo(&this->prev_load);

Machine_done(super);
Expand All @@ -125,3 +139,37 @@ bool Machine_isCPUonline(const Machine* host, unsigned int id) {

return true;
}

void Machine_scanGPUUsage(Machine* super) {
DarwinMachine* dhost = (DarwinMachine *)super;

if (!dhost->GPUService) {
return;
}

CFMutableDictionaryRef properties = NULL;
kern_return_t ret = IORegistryEntryCreateCFProperties(dhost->GPUService, &properties, kCFAllocatorDefault, kNilOptions);
if (ret != KERN_SUCCESS) {
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);
super->totalGPUUsage = (double)device;

cleanup:
CFRelease(properties);
}
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
2 changes: 2 additions & 0 deletions darwin/Platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,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 +145,7 @@ const MeterClass* const Platform_meterTypes[] = {
&DiskIOMeter_class,
&NetworkIOMeter_class,
&FileDescriptorMeter_class,
&GPUMeter_class,
&BlankMeter_class,
NULL
};
Expand Down
6 changes: 6 additions & 0 deletions dragonflybsd/DragonFlyBSDMachine.c
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,7 @@ void Machine_scan(Machine* super) {
DragonFlyBSDMachine_scanMemoryInfo(super);
DragonFlyBSDMachine_scanCPUTime(super);
DragonFlyBSDMachine_scanJails(this);
Machine_scanGPUUsage(super);
}

bool Machine_isCPUonline(const Machine* host, unsigned int id) {
Expand All @@ -349,3 +350,8 @@ bool Machine_isCPUonline(const Machine* host, unsigned int id) {
// TODO: Support detecting online / offline CPUs.
return true;
}

void Machine_scanGPUUsage(Machine* super) {
/* Not supported yet */
super->totalGPUUsage = -1.0;
}
6 changes: 6 additions & 0 deletions freebsd/FreeBSDMachine.c
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,7 @@ void Machine_scan(Machine* super) {
openzfs_sysctl_updateArcStats(&this->zfs);
FreeBSDMachine_scanMemoryInfo(super);
FreeBSDMachine_scanCPU(super);
Machine_scanGPUUsage(super);
}

bool Machine_isCPUonline(const Machine* host, unsigned int id) {
Expand All @@ -397,3 +398,8 @@ bool Machine_isCPUonline(const Machine* host, unsigned int id) {

return true;
}

void Machine_scanGPUUsage(Machine* super) {
/* Not supported yet */
super->totalGPUUsage = -1.0;
}
22 changes: 22 additions & 0 deletions linux/LinuxMachine.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ in the source distribution for its full text.
#define O_PATH 010000000 // declare for ancient glibc versions
#endif


/* Similar to get_nprocs_conf(3) / _SC_NPROCESSORS_CONF
* https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/getsysstats.c;hb=HEAD
*/
Expand Down Expand Up @@ -732,6 +733,7 @@ void Machine_scan(Machine* super) {
LinuxMachine_scanZfsArcstats(this);
LinuxMachine_scanZramInfo(this);
LinuxMachine_scanCPUTime(this);
Machine_scanGPUUsage(super);

const Settings* settings = super->settings;
if (settings->showCPUFrequency
Expand Down Expand Up @@ -820,3 +822,23 @@ bool Machine_isCPUonline(const Machine* super, unsigned int id) {
assert(id < super->existingCPUs);
return this->cpuData[id + 1].online;
}

void Machine_scanGPUUsage(Machine* super) {
LinuxMachine* this = (LinuxMachine*) super;

const uint64_t monotonictimeDelta = super->monotonicMs - super->prevMonotonicMs;

GPUEngineData *gpuEngineData;
size_t i;

super->totalGPUTimeDiff = saturatingSub(this->curGpuTime, this->prevGpuTime);

this->prevResidueTime = this->curResidueTime;
this->curResidueTime = this->curGpuTime;

for (gpuEngineData = this->gpuEngineData, i = 0; gpuEngineData; gpuEngineData = gpuEngineData->next, i++) {
this->curResidueTime = saturatingSub(this->curResidueTime, gpuEngineData->curTime);
}

super->totalGPUUsage = 100.0 * super->totalGPUTimeDiff / (1000 * 1000) / monotonictimeDelta;
}
1 change: 1 addition & 0 deletions linux/LinuxMachine.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ typedef struct LinuxMachine_ {
memory_t availableMem;

unsigned long long int prevGpuTime, curGpuTime; /* total absolute GPU time in nano seconds */
unsigned long long int prevResidueTime, curResidueTime;
GPUEngineData* gpuEngineData;

ZfsArcStats zfs;
Expand Down
Loading