summaryrefslogtreecommitdiffstats
path: root/darwin
diff options
context:
space:
mode:
authorUeiWang <weiwang.ueiwaon@gmail.com>2023-04-16 23:11:20 +0800
committerBenBE <BenBE@geshi.org>2023-04-22 23:09:51 +0200
commited7eac5dfe8239f7942102f9d1a4f9ef5210f4d7 (patch)
tree8573e551f8fc841c6b39fc421b4ae634b87ef510 /darwin
parent7a7c6938aad999f33ceb1e4ec5ebaada4c461f29 (diff)
Darwin: add DiskIOMeter support
Diffstat (limited to 'darwin')
-rw-r--r--darwin/Platform.c108
1 files changed, 105 insertions, 3 deletions
diff --git a/darwin/Platform.c b/darwin/Platform.c
index 27bce551..deba7abb 100644
--- a/darwin/Platform.c
+++ b/darwin/Platform.c
@@ -14,10 +14,19 @@ in the source distribution for its full text.
#include <math.h>
#include <stdlib.h>
#include <unistd.h>
+#include <sys/_types/_mach_port_t.h>
+
+#include <CoreFoundation/CFBase.h>
+#include <CoreFoundation/CFDictionary.h>
+#include <CoreFoundation/CFNumber.h>
#include <CoreFoundation/CFString.h>
#include <CoreFoundation/CoreFoundation.h>
+
+#include <IOKit/IOKitLib.h>
+#include <IOKit/IOTypes.h>
#include <IOKit/ps/IOPowerSources.h>
#include <IOKit/ps/IOPSKeys.h>
+#include <IOKit/storage/IOBlockStorageDriver.h>
#include "ClockMeter.h"
#include "CPUMeter.h"
@@ -128,6 +137,7 @@ const MeterClass* const Platform_meterTypes[] = {
&RightCPUs8Meter_class,
&ZfsArcMeter_class,
&ZfsCompressedArcMeter_class,
+ &DiskIOMeter_class,
&FileDescriptorMeter_class,
&BlankMeter_class,
NULL
@@ -137,6 +147,9 @@ static double Platform_nanosecondsPerMachTick = 1.0;
static double Platform_nanosecondsPerSchedulerTick = -1;
+static bool iokit_available = false;
+static mach_port_t iokit_port; // the mach port used to initiate communication with IOKit
+
bool Platform_init(void) {
Platform_nanosecondsPerMachTick = Platform_calculateNanosecondsPerMachTick();
@@ -151,6 +164,17 @@ bool Platform_init(void) {
const double nanos_per_sec = 1e9;
Platform_nanosecondsPerSchedulerTick = nanos_per_sec / scheduler_ticks_per_sec;
+ // Since macOS 12.0, IOMasterPort is deprecated, and one should use IOMainPort instead
+ #if defined(HAVE_DECL_IOMAINPORT) && HAVE_DECL_IOMAINPORT
+ if (!IOMainPort(bootstrap_port, &iokit_port)) {
+ iokit_available = true;
+ }
+ #elif defined(HAVE_DECL_IOMASTERPORT) && HAVE_DECL_IOMASTERPORT
+ if (!IOMasterPort(bootstrap_port, &iokit_port)) {
+ iokit_available = true;
+ }
+ #endif
+
return true;
}
@@ -357,9 +381,87 @@ void Platform_getFileDescriptors(double* used, double* max) {
}
bool Platform_getDiskIO(DiskIOData* data) {
- // TODO
- (void)data;
- return false;
+ if (!iokit_available)
+ return false;
+
+ io_iterator_t drive_list;
+
+ /* Get the list of all drives */
+ if (IOServiceGetMatchingServices(iokit_port, IOServiceMatching("IOBlockStorageDriver"), &drive_list))
+ return false;
+
+ unsigned long long int read_sum = 0, write_sum = 0, timeSpend_sum = 0;
+
+ io_registry_entry_t drive;
+ while ((drive = IOIteratorNext(drive_list)) != 0) {
+ CFMutableDictionaryRef properties_tmp = NULL;
+
+ /* Get the properties of this drive */
+ if (IORegistryEntryCreateCFProperties(drive, &properties_tmp, kCFAllocatorDefault, 0)) {
+ IOObjectRelease(drive);
+ IOObjectRelease(drive_list);
+ return false;
+ }
+
+ if (!properties_tmp) {
+ IOObjectRelease(drive);
+ continue;
+ }
+
+ CFDictionaryRef properties = properties_tmp;
+
+ /* Get the statistics of this drive */
+ CFDictionaryRef statistics = (CFDictionaryRef) CFDictionaryGetValue(properties, CFSTR(kIOBlockStorageDriverStatisticsKey));
+
+ if (!statistics) {
+ CFRelease(properties);
+ IOObjectRelease(drive);
+ continue;
+ }
+
+ CFNumberRef number;
+ unsigned long long int value;
+
+ /* Get bytes read */
+ number = (CFNumberRef) CFDictionaryGetValue(statistics, CFSTR(kIOBlockStorageDriverStatisticsBytesReadKey));
+ if (number != 0) {
+ CFNumberGetValue(number, kCFNumberSInt64Type, &value);
+ read_sum += value;
+ }
+
+ /* Get bytes written */
+ number = (CFNumberRef) CFDictionaryGetValue(statistics, CFSTR(kIOBlockStorageDriverStatisticsBytesWrittenKey));
+ if (number != 0) {
+ CFNumberGetValue(number, kCFNumberSInt64Type, &value);
+ write_sum += value;
+ }
+
+ /* Get total read time (in ns) */
+ number = (CFNumberRef) CFDictionaryGetValue(statistics, CFSTR(kIOBlockStorageDriverStatisticsTotalReadTimeKey));
+ if (number != 0) {
+ CFNumberGetValue(number, kCFNumberSInt64Type, &value);
+ timeSpend_sum += value;
+ }
+
+ /* Get total write time (in ns) */
+ number = (CFNumberRef) CFDictionaryGetValue(statistics, CFSTR(kIOBlockStorageDriverStatisticsTotalWriteTimeKey));
+ if (number != 0) {
+ CFNumberGetValue(number, kCFNumberSInt64Type, &value);
+ timeSpend_sum += value;
+ }
+
+ CFRelease(properties);
+ IOObjectRelease(drive);
+ }
+
+ data->totalBytesRead = read_sum;
+ data->totalBytesWritten = write_sum;
+ data->totalMsTimeSpend = timeSpend_sum / 1e6; /* Convert from ns to ms */
+
+ if (drive_list)
+ IOObjectRelease(drive_list);
+
+ return true;
}
bool Platform_getNetworkIO(NetworkIOData* data) {

© 2014-2024 Faster IT GmbH | imprint | privacy policy