2015-07-12 18:47:43 +00:00
|
|
|
/*
|
|
|
|
htop - darwin/Platform.c
|
|
|
|
(C) 2014 Hisham H. Muhammad
|
|
|
|
(C) 2015 David C. Hunt
|
2020-10-05 07:51:32 +00:00
|
|
|
Released under the GNU GPLv2, see the COPYING file
|
2015-07-12 18:47:43 +00:00
|
|
|
in the source distribution for its full text.
|
|
|
|
*/
|
|
|
|
|
2020-12-12 19:43:08 +00:00
|
|
|
#include "config.h" // IWYU pragma: keep
|
|
|
|
|
2021-04-29 18:13:36 +00:00
|
|
|
#include "darwin/Platform.h"
|
2020-12-12 19:41:19 +00:00
|
|
|
|
2020-12-09 04:12:44 +00:00
|
|
|
#include <errno.h>
|
2020-12-12 19:41:19 +00:00
|
|
|
#include <math.h>
|
|
|
|
#include <stdlib.h>
|
2020-12-09 04:12:44 +00:00
|
|
|
#include <unistd.h>
|
2020-12-12 19:41:19 +00:00
|
|
|
#include <CoreFoundation/CFString.h>
|
2020-12-09 04:12:44 +00:00
|
|
|
#include <CoreFoundation/CoreFoundation.h>
|
2020-12-12 19:41:19 +00:00
|
|
|
#include <IOKit/ps/IOPowerSources.h>
|
|
|
|
#include <IOKit/ps/IOPSKeys.h>
|
|
|
|
|
2015-07-12 18:47:43 +00:00
|
|
|
#include "ClockMeter.h"
|
2020-12-12 19:41:19 +00:00
|
|
|
#include "CPUMeter.h"
|
2020-12-09 04:12:44 +00:00
|
|
|
#include "CRT.h"
|
2020-10-05 11:52:58 +00:00
|
|
|
#include "DateMeter.h"
|
|
|
|
#include "DateTimeMeter.h"
|
2015-07-12 18:47:43 +00:00
|
|
|
#include "HostnameMeter.h"
|
2020-12-12 19:41:19 +00:00
|
|
|
#include "LoadAverageMeter.h"
|
|
|
|
#include "Macros.h"
|
|
|
|
#include "MemoryMeter.h"
|
2021-08-10 19:32:05 +00:00
|
|
|
#include "MemorySwapMeter.h"
|
2020-11-11 21:15:35 +00:00
|
|
|
#include "ProcessLocksScreen.h"
|
2020-12-12 19:41:19 +00:00
|
|
|
#include "SwapMeter.h"
|
2021-01-27 09:45:48 +00:00
|
|
|
#include "SysArchMeter.h"
|
2020-12-12 19:41:19 +00:00
|
|
|
#include "TasksMeter.h"
|
2015-07-12 18:47:43 +00:00
|
|
|
#include "UptimeMeter.h"
|
2021-04-29 18:13:36 +00:00
|
|
|
#include "darwin/DarwinProcessList.h"
|
2019-07-07 21:30:37 +00:00
|
|
|
#include "zfs/ZfsArcMeter.h"
|
2019-09-03 18:26:02 +00:00
|
|
|
#include "zfs/ZfsCompressedArcMeter.h"
|
2015-07-12 18:47:43 +00:00
|
|
|
|
2021-03-30 04:55:48 +00:00
|
|
|
#ifdef HAVE_HOST_GET_CLOCK_SERVICE
|
|
|
|
#include <mach/clock.h>
|
|
|
|
#include <mach/mach.h>
|
|
|
|
#endif
|
2020-12-12 19:43:08 +00:00
|
|
|
#ifdef HAVE_MACH_MACH_TIME_H
|
|
|
|
#include <mach/mach_time.h>
|
|
|
|
#endif
|
2015-07-13 06:17:14 +00:00
|
|
|
|
2015-07-12 18:47:43 +00:00
|
|
|
|
2020-12-19 17:10:03 +00:00
|
|
|
const ProcessField Platform_defaultFields[] = { PID, USER, PRIORITY, NICE, M_VIRT, M_RESIDENT, STATE, PERCENT_CPU, PERCENT_MEM, TIME, COMM, 0 };
|
2015-07-12 18:47:43 +00:00
|
|
|
|
2016-08-30 12:41:17 +00:00
|
|
|
const SignalItem Platform_signals[] = {
|
2015-10-06 16:03:47 +00:00
|
|
|
{ .name = " 0 Cancel", .number = 0 },
|
|
|
|
{ .name = " 1 SIGHUP", .number = 1 },
|
|
|
|
{ .name = " 2 SIGINT", .number = 2 },
|
|
|
|
{ .name = " 3 SIGQUIT", .number = 3 },
|
|
|
|
{ .name = " 4 SIGILL", .number = 4 },
|
|
|
|
{ .name = " 5 SIGTRAP", .number = 5 },
|
|
|
|
{ .name = " 6 SIGABRT", .number = 6 },
|
|
|
|
{ .name = " 6 SIGIOT", .number = 6 },
|
|
|
|
{ .name = " 7 SIGEMT", .number = 7 },
|
|
|
|
{ .name = " 8 SIGFPE", .number = 8 },
|
|
|
|
{ .name = " 9 SIGKILL", .number = 9 },
|
|
|
|
{ .name = "10 SIGBUS", .number = 10 },
|
|
|
|
{ .name = "11 SIGSEGV", .number = 11 },
|
|
|
|
{ .name = "12 SIGSYS", .number = 12 },
|
|
|
|
{ .name = "13 SIGPIPE", .number = 13 },
|
|
|
|
{ .name = "14 SIGALRM", .number = 14 },
|
|
|
|
{ .name = "15 SIGTERM", .number = 15 },
|
|
|
|
{ .name = "16 SIGURG", .number = 16 },
|
|
|
|
{ .name = "17 SIGSTOP", .number = 17 },
|
|
|
|
{ .name = "18 SIGTSTP", .number = 18 },
|
|
|
|
{ .name = "19 SIGCONT", .number = 19 },
|
|
|
|
{ .name = "20 SIGCHLD", .number = 20 },
|
|
|
|
{ .name = "21 SIGTTIN", .number = 21 },
|
|
|
|
{ .name = "22 SIGTTOU", .number = 22 },
|
|
|
|
{ .name = "23 SIGIO", .number = 23 },
|
|
|
|
{ .name = "24 SIGXCPU", .number = 24 },
|
|
|
|
{ .name = "25 SIGXFSZ", .number = 25 },
|
|
|
|
{ .name = "26 SIGVTALRM", .number = 26 },
|
|
|
|
{ .name = "27 SIGPROF", .number = 27 },
|
|
|
|
{ .name = "28 SIGWINCH", .number = 28 },
|
|
|
|
{ .name = "29 SIGINFO", .number = 29 },
|
|
|
|
{ .name = "30 SIGUSR1", .number = 30 },
|
|
|
|
{ .name = "31 SIGUSR2", .number = 31 },
|
|
|
|
};
|
|
|
|
|
2020-10-03 20:00:27 +00:00
|
|
|
const unsigned int Platform_numberOfSignals = ARRAYSIZE(Platform_signals);
|
2015-10-06 16:03:47 +00:00
|
|
|
|
2020-10-05 11:19:50 +00:00
|
|
|
const MeterClass* const Platform_meterTypes[] = {
|
2015-07-12 18:47:43 +00:00
|
|
|
&CPUMeter_class,
|
|
|
|
&ClockMeter_class,
|
2020-10-05 11:52:58 +00:00
|
|
|
&DateMeter_class,
|
|
|
|
&DateTimeMeter_class,
|
2015-07-12 18:47:43 +00:00
|
|
|
&LoadAverageMeter_class,
|
|
|
|
&LoadMeter_class,
|
|
|
|
&MemoryMeter_class,
|
2015-11-16 17:32:22 +00:00
|
|
|
&SwapMeter_class,
|
2021-08-10 19:32:05 +00:00
|
|
|
&MemorySwapMeter_class,
|
2015-07-12 18:47:43 +00:00
|
|
|
&TasksMeter_class,
|
|
|
|
&BatteryMeter_class,
|
|
|
|
&HostnameMeter_class,
|
2021-01-27 09:45:48 +00:00
|
|
|
&SysArchMeter_class,
|
2015-07-12 18:47:43 +00:00
|
|
|
&UptimeMeter_class,
|
|
|
|
&AllCPUsMeter_class,
|
|
|
|
&AllCPUs2Meter_class,
|
2020-09-24 19:50:29 +00:00
|
|
|
&AllCPUs4Meter_class,
|
2020-09-24 19:56:40 +00:00
|
|
|
&AllCPUs8Meter_class,
|
2015-07-12 18:47:43 +00:00
|
|
|
&LeftCPUsMeter_class,
|
|
|
|
&RightCPUsMeter_class,
|
|
|
|
&LeftCPUs2Meter_class,
|
|
|
|
&RightCPUs2Meter_class,
|
2020-09-24 19:50:29 +00:00
|
|
|
&LeftCPUs4Meter_class,
|
|
|
|
&RightCPUs4Meter_class,
|
2020-09-24 19:56:40 +00:00
|
|
|
&LeftCPUs8Meter_class,
|
|
|
|
&RightCPUs8Meter_class,
|
2019-07-07 21:30:37 +00:00
|
|
|
&ZfsArcMeter_class,
|
2019-09-03 18:26:02 +00:00
|
|
|
&ZfsCompressedArcMeter_class,
|
2015-07-12 18:47:43 +00:00
|
|
|
&BlankMeter_class,
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
2021-08-22 14:47:11 +00:00
|
|
|
static double Platform_nanosecondsPerMachTick = 1.0;
|
2020-12-12 19:43:08 +00:00
|
|
|
|
2021-08-25 18:45:00 +00:00
|
|
|
static double Platform_nanosecondsPerSchedulerTick = -1;
|
2020-12-09 04:12:44 +00:00
|
|
|
|
2020-11-19 01:32:07 +00:00
|
|
|
void Platform_init(void) {
|
2020-12-12 19:43:08 +00:00
|
|
|
// Check if we can determine the timebase used on this system.
|
|
|
|
// If the API is unavailable assume we get our timebase in nanoseconds.
|
|
|
|
#ifdef HAVE_MACH_TIMEBASE_INFO
|
|
|
|
mach_timebase_info_data_t info;
|
|
|
|
mach_timebase_info(&info);
|
2021-08-22 14:47:11 +00:00
|
|
|
Platform_nanosecondsPerMachTick = (double)info.numer / (double)info.denom;
|
2020-12-12 19:43:08 +00:00
|
|
|
#else
|
2021-08-22 14:47:11 +00:00
|
|
|
Platform_nanosecondsPerMachTick = 1.0;
|
2020-12-12 19:43:08 +00:00
|
|
|
#endif
|
2020-12-09 04:12:44 +00:00
|
|
|
|
2021-08-22 14:47:11 +00:00
|
|
|
// Determine the number of scheduler clock ticks per second
|
2020-12-09 04:12:44 +00:00
|
|
|
errno = 0;
|
2021-08-22 14:47:11 +00:00
|
|
|
long scheduler_ticks_per_sec = sysconf(_SC_CLK_TCK);
|
2020-12-09 04:12:44 +00:00
|
|
|
|
2021-08-22 14:47:11 +00:00
|
|
|
if (errno || scheduler_ticks_per_sec < 1) {
|
2020-12-09 04:12:44 +00:00
|
|
|
CRT_fatalError("Unable to retrieve clock tick rate");
|
|
|
|
}
|
2021-08-22 14:47:11 +00:00
|
|
|
|
|
|
|
const double nanos_per_sec = 1e9;
|
2021-08-25 18:45:00 +00:00
|
|
|
Platform_nanosecondsPerSchedulerTick = nanos_per_sec / scheduler_ticks_per_sec;
|
2021-08-22 14:47:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Converts ticks in the Mach "timebase" to nanoseconds.
|
|
|
|
// See `mach_timebase_info`, as used to define the `Platform_nanosecondsPerMachTick` constant.
|
|
|
|
uint64_t Platform_machTicksToNanoseconds(uint64_t mach_ticks) {
|
|
|
|
return (uint64_t) ((double) mach_ticks * Platform_nanosecondsPerMachTick);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Converts "scheduler ticks" to nanoseconds.
|
2021-08-25 18:45:00 +00:00
|
|
|
// See `sysconf(_SC_CLK_TCK)`, as used to define the `Platform_nanosecondsPerSchedulerTick` constant.
|
2021-08-22 14:47:11 +00:00
|
|
|
double Platform_schedulerTicksToNanoseconds(const double scheduler_ticks) {
|
2021-08-25 18:45:00 +00:00
|
|
|
return scheduler_ticks * Platform_nanosecondsPerSchedulerTick;
|
2020-11-19 01:32:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Platform_done(void) {
|
|
|
|
/* no platform-specific cleanup needed */
|
|
|
|
}
|
|
|
|
|
2015-07-12 18:47:43 +00:00
|
|
|
void Platform_setBindings(Htop_Action* keys) {
|
2020-11-19 01:32:07 +00:00
|
|
|
/* no platform-specific key bindings */
|
2015-07-12 18:47:43 +00:00
|
|
|
(void) keys;
|
|
|
|
}
|
|
|
|
|
|
|
|
int Platform_getUptime() {
|
2015-08-19 16:56:46 +00:00
|
|
|
struct timeval bootTime, currTime;
|
|
|
|
int mib[2] = { CTL_KERN, KERN_BOOTTIME };
|
|
|
|
size_t size = sizeof(bootTime);
|
2015-07-14 02:02:40 +00:00
|
|
|
|
2015-08-19 16:56:46 +00:00
|
|
|
int err = sysctl(mib, 2, &bootTime, &size, NULL, 0);
|
|
|
|
if (err) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
gettimeofday(&currTime, NULL);
|
2015-07-14 02:02:40 +00:00
|
|
|
|
2015-08-19 16:56:46 +00:00
|
|
|
return (int) difftime(currTime.tv_sec, bootTime.tv_sec);
|
2015-07-12 18:47:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Platform_getLoadAverage(double* one, double* five, double* fifteen) {
|
2015-07-13 06:17:14 +00:00
|
|
|
double results[3];
|
|
|
|
|
2020-10-31 19:52:20 +00:00
|
|
|
if (3 == getloadavg(results, 3)) {
|
2015-07-13 06:17:14 +00:00
|
|
|
*one = results[0];
|
|
|
|
*five = results[1];
|
|
|
|
*fifteen = results[2];
|
|
|
|
} else {
|
|
|
|
*one = 0;
|
|
|
|
*five = 0;
|
|
|
|
*fifteen = 0;
|
|
|
|
}
|
2015-07-12 18:47:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int Platform_getMaxPid() {
|
2015-07-13 06:17:14 +00:00
|
|
|
/* http://opensource.apple.com/source/xnu/xnu-2782.1.97/bsd/sys/proc_internal.hh */
|
|
|
|
return 99999;
|
2015-07-12 18:47:43 +00:00
|
|
|
}
|
|
|
|
|
2015-10-23 15:46:21 +00:00
|
|
|
static double Platform_setCPUAverageValues(Meter* mtr) {
|
2020-10-31 22:28:02 +00:00
|
|
|
const ProcessList* dpl = mtr->pl;
|
2021-06-12 16:17:28 +00:00
|
|
|
unsigned int activeCPUs = dpl->activeCPUs;
|
2015-10-25 03:28:29 +00:00
|
|
|
double sumNice = 0.0;
|
|
|
|
double sumNormal = 0.0;
|
|
|
|
double sumKernel = 0.0;
|
|
|
|
double sumPercent = 0.0;
|
2021-06-12 16:17:28 +00:00
|
|
|
for (unsigned int i = 1; i <= dpl->existingCPUs; i++) {
|
2015-10-23 15:46:21 +00:00
|
|
|
sumPercent += Platform_setCPUValues(mtr, i);
|
|
|
|
sumNice += mtr->values[CPU_METER_NICE];
|
|
|
|
sumNormal += mtr->values[CPU_METER_NORMAL];
|
|
|
|
sumKernel += mtr->values[CPU_METER_KERNEL];
|
|
|
|
}
|
2021-06-12 16:17:28 +00:00
|
|
|
mtr->values[CPU_METER_NICE] = sumNice / activeCPUs;
|
|
|
|
mtr->values[CPU_METER_NORMAL] = sumNormal / activeCPUs;
|
|
|
|
mtr->values[CPU_METER_KERNEL] = sumKernel / activeCPUs;
|
|
|
|
return sumPercent / activeCPUs;
|
2015-10-23 15:46:21 +00:00
|
|
|
}
|
|
|
|
|
2021-02-17 16:38:35 +00:00
|
|
|
double Platform_setCPUValues(Meter* mtr, unsigned int cpu) {
|
2015-10-23 15:46:21 +00:00
|
|
|
|
|
|
|
if (cpu == 0) {
|
|
|
|
return Platform_setCPUAverageValues(mtr);
|
|
|
|
}
|
2015-08-19 16:56:46 +00:00
|
|
|
|
2020-10-31 22:28:02 +00:00
|
|
|
const DarwinProcessList* dpl = (const DarwinProcessList*)mtr->pl;
|
|
|
|
const processor_cpu_load_info_t prev = &dpl->prev_load[cpu - 1];
|
|
|
|
const processor_cpu_load_info_t curr = &dpl->curr_load[cpu - 1];
|
2015-08-19 16:56:46 +00:00
|
|
|
double total = 0;
|
|
|
|
|
|
|
|
/* Take the sums */
|
2020-10-31 19:55:36 +00:00
|
|
|
for (size_t i = 0; i < CPU_STATE_MAX; ++i) {
|
2015-08-19 16:56:46 +00:00
|
|
|
total += (double)curr->cpu_ticks[i] - (double)prev->cpu_ticks[i];
|
|
|
|
}
|
2015-07-12 18:47:43 +00:00
|
|
|
|
2015-08-19 16:56:46 +00:00
|
|
|
mtr->values[CPU_METER_NICE]
|
2020-10-31 21:14:27 +00:00
|
|
|
= ((double)curr->cpu_ticks[CPU_STATE_NICE] - (double)prev->cpu_ticks[CPU_STATE_NICE]) * 100.0 / total;
|
2015-08-19 16:56:46 +00:00
|
|
|
mtr->values[CPU_METER_NORMAL]
|
2020-10-31 21:14:27 +00:00
|
|
|
= ((double)curr->cpu_ticks[CPU_STATE_USER] - (double)prev->cpu_ticks[CPU_STATE_USER]) * 100.0 / total;
|
2015-08-19 16:56:46 +00:00
|
|
|
mtr->values[CPU_METER_KERNEL]
|
2020-10-31 21:14:27 +00:00
|
|
|
= ((double)curr->cpu_ticks[CPU_STATE_SYSTEM] - (double)prev->cpu_ticks[CPU_STATE_SYSTEM]) * 100.0 / total;
|
2015-07-14 02:02:40 +00:00
|
|
|
|
2020-10-04 15:55:08 +00:00
|
|
|
mtr->curItems = 3;
|
2015-07-14 02:02:40 +00:00
|
|
|
|
2015-08-19 16:56:46 +00:00
|
|
|
/* Convert to percent and return */
|
|
|
|
total = mtr->values[CPU_METER_NICE] + mtr->values[CPU_METER_NORMAL] + mtr->values[CPU_METER_KERNEL];
|
|
|
|
|
2020-09-07 10:24:32 +00:00
|
|
|
mtr->values[CPU_METER_FREQUENCY] = NAN;
|
2020-09-10 17:56:33 +00:00
|
|
|
mtr->values[CPU_METER_TEMPERATURE] = NAN;
|
2019-08-11 00:17:45 +00:00
|
|
|
|
Introduce CLAMP macro. Unify all MIN(MAX(a,b),c) uses.
With the CLAMP macro replacing the combination of MIN and MAX, we will
have at least two advantages:
1. It's more obvious semantically.
2. There are no more mixes of confusing uses like MIN(MAX(a,b),c) and
MAX(MIN(a,b),c) and MIN(a,MAX(b,c)) appearing everywhere. We unify
the 'clamping' with a single macro.
Note that the behavior of this CLAMP macro is different from
the combination `MAX(low,MIN(x,high))`.
* This CLAMP macro expands to two comparisons instead of three from
MAX and MIN combination. In theory, this makes the code slightly
smaller, in case that (low) or (high) or both are computed at
runtime, so that compilers cannot optimize them. (The third
comparison will matter if (low)>(high); see below.)
* CLAMP has a side effect, that if (low)>(high) it will produce weird
results. Unlike MIN & MAX which will force either (low) or (high) to
win. No assertion of ((low)<=(high)) is done in this macro, for now.
This CLAMP macro is implemented like described in glib
<http://developer.gnome.org/glib/stable/glib-Standard-Macros.html>
and does not handle weird uses like CLAMP(a++, low++, high--) .
2016-01-15 12:26:01 +00:00
|
|
|
return CLAMP(total, 0.0, 100.0);
|
2015-08-19 16:56:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Platform_setMemoryValues(Meter* mtr) {
|
2020-10-31 22:28:02 +00:00
|
|
|
const DarwinProcessList* dpl = (const DarwinProcessList*)mtr->pl;
|
2020-10-21 19:25:50 +00:00
|
|
|
const struct vm_statistics* vm = &dpl->vm_stats;
|
2015-08-19 16:56:46 +00:00
|
|
|
double page_K = (double)vm_page_size / (double)1024;
|
|
|
|
|
|
|
|
mtr->total = dpl->host_info.max_mem / 1024;
|
|
|
|
mtr->values[0] = (double)(vm->active_count + vm->wire_count) * page_K;
|
|
|
|
mtr->values[1] = (double)vm->purgeable_count * page_K;
|
2021-03-17 15:32:16 +00:00
|
|
|
// mtr->values[2] = "shared memory, like tmpfs and shm"
|
|
|
|
mtr->values[3] = (double)vm->inactive_count * page_K;
|
|
|
|
// mtr->values[4] = "available memory"
|
2015-07-12 18:47:43 +00:00
|
|
|
}
|
|
|
|
|
2015-11-16 17:32:22 +00:00
|
|
|
void Platform_setSwapValues(Meter* mtr) {
|
2020-10-31 21:14:27 +00:00
|
|
|
int mib[2] = {CTL_VM, VM_SWAPUSAGE};
|
|
|
|
struct xsw_usage swapused;
|
|
|
|
size_t swlen = sizeof(swapused);
|
|
|
|
sysctl(mib, 2, &swapused, &swlen, NULL, 0);
|
2015-07-12 18:47:43 +00:00
|
|
|
|
2020-10-31 21:14:27 +00:00
|
|
|
mtr->total = swapused.xsu_total / 1024;
|
|
|
|
mtr->values[0] = swapused.xsu_used / 1024;
|
2015-11-16 17:32:22 +00:00
|
|
|
}
|
2015-12-03 21:16:10 +00:00
|
|
|
|
2019-07-07 21:30:37 +00:00
|
|
|
void Platform_setZfsArcValues(Meter* this) {
|
2020-10-21 19:25:50 +00:00
|
|
|
const DarwinProcessList* dpl = (const DarwinProcessList*) this->pl;
|
2019-07-07 21:30:37 +00:00
|
|
|
|
2019-09-03 18:21:33 +00:00
|
|
|
ZfsArcMeter_readStats(this, &(dpl->zfs));
|
2019-07-07 21:30:37 +00:00
|
|
|
}
|
|
|
|
|
2019-09-03 18:26:02 +00:00
|
|
|
void Platform_setZfsCompressedArcValues(Meter* this) {
|
2020-10-21 19:25:50 +00:00
|
|
|
const DarwinProcessList* dpl = (const DarwinProcessList*) this->pl;
|
2019-09-03 18:26:02 +00:00
|
|
|
|
|
|
|
ZfsCompressedArcMeter_readStats(this, &(dpl->zfs));
|
|
|
|
}
|
|
|
|
|
2015-12-03 21:16:10 +00:00
|
|
|
char* Platform_getProcessEnv(pid_t pid) {
|
|
|
|
char* env = NULL;
|
|
|
|
|
|
|
|
int argmax;
|
|
|
|
size_t bufsz = sizeof(argmax);
|
|
|
|
|
|
|
|
int mib[3];
|
|
|
|
mib[0] = CTL_KERN;
|
|
|
|
mib[1] = KERN_ARGMAX;
|
|
|
|
if (sysctl(mib, 2, &argmax, &bufsz, 0, 0) == 0) {
|
2016-02-02 14:53:02 +00:00
|
|
|
char* buf = xMalloc(argmax);
|
2015-12-03 21:16:10 +00:00
|
|
|
if (buf) {
|
|
|
|
mib[0] = CTL_KERN;
|
|
|
|
mib[1] = KERN_PROCARGS2;
|
|
|
|
mib[2] = pid;
|
2020-09-08 14:17:31 +00:00
|
|
|
bufsz = argmax;
|
2015-12-03 21:16:10 +00:00
|
|
|
if (sysctl(mib, 3, buf, &bufsz, 0, 0) == 0) {
|
|
|
|
if (bufsz > sizeof(int)) {
|
|
|
|
char *p = buf, *endp = buf + bufsz;
|
2020-09-08 14:17:31 +00:00
|
|
|
int argc = *(int*)(void*)p;
|
2015-12-03 21:16:10 +00:00
|
|
|
p += sizeof(int);
|
|
|
|
|
|
|
|
// skip exe
|
2020-10-31 22:28:02 +00:00
|
|
|
p = strchr(p, 0) + 1;
|
2015-12-03 21:16:10 +00:00
|
|
|
|
|
|
|
// skip padding
|
2020-10-31 19:39:01 +00:00
|
|
|
while (!*p && p < endp)
|
2015-12-03 21:16:10 +00:00
|
|
|
++p;
|
|
|
|
|
|
|
|
// skip argv
|
2020-10-31 22:28:02 +00:00
|
|
|
for (; argc-- && p < endp; p = strrchr(p, 0) + 1)
|
2015-12-03 21:16:10 +00:00
|
|
|
;
|
|
|
|
|
|
|
|
// skip padding
|
2020-10-31 19:39:01 +00:00
|
|
|
while (!*p && p < endp)
|
2015-12-03 21:16:10 +00:00
|
|
|
++p;
|
|
|
|
|
|
|
|
size_t size = endp - p;
|
2020-10-31 22:28:02 +00:00
|
|
|
env = xMalloc(size + 2);
|
2016-04-30 01:10:05 +00:00
|
|
|
memcpy(env, p, size);
|
|
|
|
env[size] = 0;
|
2020-10-31 22:28:02 +00:00
|
|
|
env[size + 1] = 0;
|
2015-12-03 21:16:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
free(buf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return env;
|
|
|
|
}
|
2020-09-13 17:46:34 +00:00
|
|
|
|
2020-11-11 21:15:35 +00:00
|
|
|
char* Platform_getInodeFilename(pid_t pid, ino_t inode) {
|
2021-07-14 17:15:09 +00:00
|
|
|
(void)pid;
|
|
|
|
(void)inode;
|
|
|
|
return NULL;
|
2020-11-11 21:15:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid) {
|
2021-07-14 17:15:09 +00:00
|
|
|
(void)pid;
|
|
|
|
return NULL;
|
2020-11-11 21:15:35 +00:00
|
|
|
}
|
|
|
|
|
2020-10-21 15:06:32 +00:00
|
|
|
bool Platform_getDiskIO(DiskIOData* data) {
|
2020-09-13 17:46:34 +00:00
|
|
|
// TODO
|
2020-10-21 15:06:32 +00:00
|
|
|
(void)data;
|
2020-10-20 19:40:51 +00:00
|
|
|
return false;
|
2020-09-13 17:46:34 +00:00
|
|
|
}
|
2020-10-08 14:34:54 +00:00
|
|
|
|
2021-03-01 00:55:15 +00:00
|
|
|
bool Platform_getNetworkIO(NetworkIOData* data) {
|
2020-10-08 14:34:54 +00:00
|
|
|
// TODO
|
2021-03-01 00:55:15 +00:00
|
|
|
(void)data;
|
2020-10-20 19:40:51 +00:00
|
|
|
return false;
|
2020-10-08 14:34:54 +00:00
|
|
|
}
|
2020-11-17 07:12:38 +00:00
|
|
|
|
2020-11-25 11:46:00 +00:00
|
|
|
void Platform_getBattery(double* percent, ACPresence* isOnAC) {
|
|
|
|
*percent = NAN;
|
2020-11-17 07:12:38 +00:00
|
|
|
*isOnAC = AC_ERROR;
|
|
|
|
|
2021-07-29 21:53:58 +00:00
|
|
|
CFArrayRef list = NULL;
|
2020-11-17 07:12:38 +00:00
|
|
|
|
2021-07-29 21:53:58 +00:00
|
|
|
CFTypeRef power_sources = IOPSCopyPowerSourcesInfo();
|
|
|
|
if (!power_sources)
|
|
|
|
goto cleanup;
|
2020-11-17 07:12:38 +00:00
|
|
|
|
2021-07-29 21:53:58 +00:00
|
|
|
list = IOPSCopyPowerSourcesList(power_sources);
|
|
|
|
if (!list)
|
|
|
|
goto cleanup;
|
2020-11-17 07:12:38 +00:00
|
|
|
|
2021-07-29 21:53:58 +00:00
|
|
|
double cap_current = 0.0;
|
|
|
|
double cap_max = 0.0;
|
2020-11-17 07:12:38 +00:00
|
|
|
|
|
|
|
/* Get the battery */
|
2021-07-29 21:53:58 +00:00
|
|
|
for (int i = 0, len = CFArrayGetCount(list); i < len; ++i) {
|
|
|
|
CFDictionaryRef power_source = IOPSGetPowerSourceDescription(power_sources, CFArrayGetValueAtIndex(list, i)); /* GET rule */
|
2020-11-17 07:12:38 +00:00
|
|
|
|
2021-07-29 21:53:58 +00:00
|
|
|
if (!power_source)
|
|
|
|
continue;
|
2020-11-17 07:12:38 +00:00
|
|
|
|
2021-07-29 21:53:58 +00:00
|
|
|
CFStringRef power_type = CFDictionaryGetValue(power_source, CFSTR(kIOPSTransportTypeKey)); /* GET rule */
|
2020-11-17 07:12:38 +00:00
|
|
|
|
2021-07-29 21:53:58 +00:00
|
|
|
if (kCFCompareEqualTo != CFStringCompare(power_type, CFSTR(kIOPSInternalType), 0))
|
|
|
|
continue;
|
2020-11-17 07:12:38 +00:00
|
|
|
|
2021-07-29 21:53:58 +00:00
|
|
|
/* Determine the AC state */
|
|
|
|
CFStringRef power_state = CFDictionaryGetValue(power_source, CFSTR(kIOPSPowerSourceStateKey));
|
2020-11-17 07:12:38 +00:00
|
|
|
|
2021-07-29 21:53:58 +00:00
|
|
|
if (*isOnAC != AC_PRESENT)
|
|
|
|
*isOnAC = (kCFCompareEqualTo == CFStringCompare(power_state, CFSTR(kIOPSACPowerValue), 0)) ? AC_PRESENT : AC_ABSENT;
|
2020-11-17 07:12:38 +00:00
|
|
|
|
2021-07-29 21:53:58 +00:00
|
|
|
/* Get the percentage remaining */
|
|
|
|
double tmp;
|
|
|
|
CFNumberGetValue(CFDictionaryGetValue(power_source, CFSTR(kIOPSCurrentCapacityKey)), kCFNumberDoubleType, &tmp);
|
|
|
|
cap_current += tmp;
|
|
|
|
CFNumberGetValue(CFDictionaryGetValue(power_source, CFSTR(kIOPSMaxCapacityKey)), kCFNumberDoubleType, &tmp);
|
|
|
|
cap_max += tmp;
|
2020-11-17 07:12:38 +00:00
|
|
|
}
|
|
|
|
|
2021-07-29 21:53:58 +00:00
|
|
|
if (cap_max > 0.0)
|
|
|
|
*percent = 100.0 * cap_current / cap_max;
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (list)
|
|
|
|
CFRelease(list);
|
|
|
|
|
|
|
|
if (power_sources)
|
|
|
|
CFRelease(power_sources);
|
2020-11-17 07:12:38 +00:00
|
|
|
}
|
2021-03-30 04:55:48 +00:00
|
|
|
|
|
|
|
void Platform_gettime_monotonic(uint64_t* msec) {
|
|
|
|
|
|
|
|
#ifdef HAVE_HOST_GET_CLOCK_SERVICE
|
|
|
|
|
|
|
|
clock_serv_t cclock;
|
|
|
|
mach_timespec_t mts;
|
|
|
|
|
|
|
|
host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock);
|
|
|
|
clock_get_time(cclock, &mts);
|
|
|
|
mach_port_deallocate(mach_task_self(), cclock);
|
|
|
|
|
|
|
|
*msec = ((uint64_t)mts.tv_sec * 1000) + ((uint64_t)mts.tv_nsec / 1000000);
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
Generic_gettime_monotomic(msec);
|
|
|
|
|
|
|
|
#endif
|
|
|
|
}
|