aboutsummaryrefslogtreecommitdiffstats
path: root/darwin
diff options
context:
space:
mode:
authorDaniel Lange <DLange@git.local>2021-09-21 08:35:19 +0200
committerDaniel Lange <DLange@git.local>2021-09-21 08:35:19 +0200
commit69f439eff387a6ecb52734e400b297a3c85f2285 (patch)
tree2a988b7868b749654796183ba70b4272965da1bf /darwin
parentc55320e9e2a8916e911bcd39ab37b79e3a7d03b2 (diff)
downloaddebian_htop-69f439eff387a6ecb52734e400b297a3c85f2285.tar.gz
debian_htop-69f439eff387a6ecb52734e400b297a3c85f2285.tar.bz2
debian_htop-69f439eff387a6ecb52734e400b297a3c85f2285.zip
New upstream version 3.1.0upstream/3.1.0
Diffstat (limited to 'darwin')
-rw-r--r--darwin/DarwinProcess.c131
-rw-r--r--darwin/DarwinProcess.h7
-rw-r--r--darwin/DarwinProcessList.c43
-rw-r--r--darwin/DarwinProcessList.h4
-rw-r--r--darwin/Platform.c178
-rw-r--r--darwin/Platform.h68
-rw-r--r--darwin/ProcessField.h2
7 files changed, 284 insertions, 149 deletions
diff --git a/darwin/DarwinProcess.c b/darwin/DarwinProcess.c
index bedfefe..20e91f7 100644
--- a/darwin/DarwinProcess.c
+++ b/darwin/DarwinProcess.c
@@ -5,7 +5,7 @@ Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
-#include "DarwinProcess.h"
+#include "darwin/DarwinProcess.h"
#include <libproc.h>
#include <stdio.h>
@@ -14,8 +14,8 @@ in the source distribution for its full text.
#include <mach/mach.h>
#include "CRT.h"
-#include "Platform.h"
#include "Process.h"
+#include "darwin/Platform.h"
const ProcessFieldData Process_fields[LAST_PROCESSFIELD] = {
@@ -26,24 +26,27 @@ const ProcessFieldData Process_fields[LAST_PROCESSFIELD] = {
[PPID] = { .name = "PPID", .title = "PPID", .description = "Parent process ID", .flags = 0, .pidColumn = true, },
[PGRP] = { .name = "PGRP", .title = "PGRP", .description = "Process group ID", .flags = 0, .pidColumn = true, },
[SESSION] = { .name = "SESSION", .title = "SID", .description = "Process's session ID", .flags = 0, .pidColumn = true, },
- [TTY_NR] = { .name = "TTY_NR", .title = " TTY ", .description = "Controlling terminal", .flags = 0, },
+ [TTY] = { .name = "TTY", .title = "TTY ", .description = "Controlling terminal", .flags = 0, },
[TPGID] = { .name = "TPGID", .title = "TPGID", .description = "Process ID of the fg process group of the controlling terminal", .flags = 0, .pidColumn = true, },
- [MINFLT] = { .name = "MINFLT", .title = " MINFLT ", .description = "Number of minor faults which have not required loading a memory page from disk", .flags = 0, },
- [MAJFLT] = { .name = "MAJFLT", .title = " MAJFLT ", .description = "Number of major faults which have required loading a memory page from disk", .flags = 0, },
+ [MINFLT] = { .name = "MINFLT", .title = " MINFLT ", .description = "Number of minor faults which have not required loading a memory page from disk", .flags = 0, .defaultSortDesc = true, },
+ [MAJFLT] = { .name = "MAJFLT", .title = " MAJFLT ", .description = "Number of major faults which have required loading a memory page from disk", .flags = 0, .defaultSortDesc = true, },
[PRIORITY] = { .name = "PRIORITY", .title = "PRI ", .description = "Kernel's internal priority for the process", .flags = 0, },
[NICE] = { .name = "NICE", .title = " NI ", .description = "Nice value (the higher the value, the more it lets other processes take priority)", .flags = 0, },
[STARTTIME] = { .name = "STARTTIME", .title = "START ", .description = "Time the process was started", .flags = 0, },
-
+ [ELAPSED] = { .name = "ELAPSED", .title = "ELAPSED ", .description = "Time since the process was started", .flags = 0, },
[PROCESSOR] = { .name = "PROCESSOR", .title = "CPU ", .description = "Id of the CPU the process last executed on", .flags = 0, },
- [M_VIRT] = { .name = "M_VIRT", .title = " VIRT ", .description = "Total program size in virtual memory", .flags = 0, },
- [M_RESIDENT] = { .name = "M_RESIDENT", .title = " RES ", .description = "Resident set size, size of the text and data sections, plus stack usage", .flags = 0, },
+ [M_VIRT] = { .name = "M_VIRT", .title = " VIRT ", .description = "Total program size in virtual memory", .flags = 0, .defaultSortDesc = true, },
+ [M_RESIDENT] = { .name = "M_RESIDENT", .title = " RES ", .description = "Resident set size, size of the text and data sections, plus stack usage", .flags = 0, .defaultSortDesc = true, },
[ST_UID] = { .name = "ST_UID", .title = " UID ", .description = "User ID of the process owner", .flags = 0, },
- [PERCENT_CPU] = { .name = "PERCENT_CPU", .title = "CPU% ", .description = "Percentage of the CPU time the process used in the last sampling", .flags = 0, },
- [PERCENT_MEM] = { .name = "PERCENT_MEM", .title = "MEM% ", .description = "Percentage of the memory the process is using, based on resident memory size", .flags = 0, },
+ [PERCENT_CPU] = { .name = "PERCENT_CPU", .title = "CPU% ", .description = "Percentage of the CPU time the process used in the last sampling", .flags = 0, .defaultSortDesc = true, },
+ [PERCENT_NORM_CPU] = { .name = "PERCENT_NORM_CPU", .title = "NCPU%", .description = "Normalized percentage of the CPU time the process used in the last sampling (normalized by cpu count)", .flags = 0, .defaultSortDesc = true, },
+ [PERCENT_MEM] = { .name = "PERCENT_MEM", .title = "MEM% ", .description = "Percentage of the memory the process is using, based on resident memory size", .flags = 0, .defaultSortDesc = true, },
[USER] = { .name = "USER", .title = "USER ", .description = "Username of the process owner (or user ID if name cannot be determined)", .flags = 0, },
- [TIME] = { .name = "TIME", .title = " TIME+ ", .description = "Total time the process has spent in user and system time", .flags = 0, },
+ [TIME] = { .name = "TIME", .title = " TIME+ ", .description = "Total time the process has spent in user and system time", .flags = 0, .defaultSortDesc = true, },
[NLWP] = { .name = "NLWP", .title = "NLWP ", .description = "Number of threads in the process", .flags = 0, },
[TGID] = { .name = "TGID", .title = "TGID", .description = "Thread group ID (i.e. process ID)", .flags = 0, .pidColumn = true, },
+ [PROC_EXE] = { .name = "EXE", .title = "EXE ", .description = "Basename of exe of the process from /proc/[pid]/exe", .flags = 0, },
+ [CWD] = { .name = "CWD", .title = "CWD ", .description = "The current working directory of the process", .flags = PROCESS_FLAG_CWD, },
[TRANSLATED] = { .name = "TRANSLATED", .title = "T ", .description = "Translation info (T translated, N native)", .flags = 0, },
};
@@ -95,16 +98,42 @@ static int DarwinProcess_compareByKey(const Process* v1, const Process* v2, Proc
}
}
-bool Process_isThread(const Process* this) {
- (void) this;
- return false;
+static void DarwinProcess_updateExe(pid_t pid, Process* proc) {
+ char path[PROC_PIDPATHINFO_MAXSIZE];
+
+ int r = proc_pidpath(pid, path, sizeof(path));
+ if (r <= 0)
+ return;
+
+ Process_updateExe(proc, path);
}
-static char* DarwinProcess_getCmdLine(const struct kinfo_proc* k, int* basenameOffset) {
+static void DarwinProcess_updateCwd(pid_t pid, Process* proc) {
+ struct proc_vnodepathinfo vpi;
+
+ int r = proc_pidinfo(pid, PROC_PIDVNODEPATHINFO, 0, &vpi, sizeof(vpi));
+ if (r <= 0) {
+ free(proc->procCwd);
+ proc->procCwd = NULL;
+ return;
+ }
+
+ if (!vpi.pvi_cdir.vip_path[0]) {
+ free(proc->procCwd);
+ proc->procCwd = NULL;
+ return;
+ }
+
+ free_and_xStrdup(&proc->procCwd, vpi.pvi_cdir.vip_path);
+}
+
+static void DarwinProcess_updateCmdLine(const struct kinfo_proc* k, Process* proc) {
+ Process_updateComm(proc, k->kp_proc.p_comm);
+
/* This function is from the old Mac version of htop. Originally from ps? */
int mib[3], argmax, nargs, c = 0;
size_t size;
- char *procargs, *sp, *np, *cp, *retval;
+ char *procargs, *sp, *np, *cp;
/* Get the maximum process arguments size. */
mib[0] = CTL_KERN;
@@ -198,7 +227,7 @@ static char* DarwinProcess_getCmdLine(const struct kinfo_proc* k, int* basenameO
/* Save where the argv[0] string starts. */
sp = cp;
- *basenameOffset = 0;
+ int end = 0;
for ( np = NULL; c < nargs && cp < &procargs[size]; cp++ ) {
if ( *cp == '\0' ) {
c++;
@@ -208,8 +237,8 @@ static char* DarwinProcess_getCmdLine(const struct kinfo_proc* k, int* basenameO
}
/* Note location of current '\0'. */
np = cp;
- if (*basenameOffset == 0) {
- *basenameOffset = cp - sp;
+ if (end == 0) {
+ end = cp - sp;
}
}
}
@@ -222,25 +251,29 @@ static char* DarwinProcess_getCmdLine(const struct kinfo_proc* k, int* basenameO
/* Empty or unterminated string. */
goto ERROR_B;
}
- if (*basenameOffset == 0) {
- *basenameOffset = np - sp;
+ if (end == 0) {
+ end = np - sp;
}
- /* Make a copy of the string. */
- retval = xStrdup(sp);
+ Process_updateCmdline(proc, sp, 0, end);
/* Clean up. */
free( procargs );
- return retval;
+ return;
ERROR_B:
free( procargs );
+
ERROR_A:
- retval = xStrdup(k->kp_proc.p_comm);
- *basenameOffset = strlen(retval);
+ Process_updateCmdline(proc, k->kp_proc.p_comm, 0, strlen(k->kp_proc.p_comm));
+}
- return retval;
+// Converts nanoseconds to hundredths of a second (centiseconds) as needed by the "time" field of the Process struct.
+static long long int nanosecondsToCentiseconds(uint64_t nanoseconds) {
+ const uint64_t centiseconds_per_second = 100;
+ const uint64_t nanoseconds_per_second = 1e9;
+ return nanoseconds / nanoseconds_per_second * centiseconds_per_second;
}
void DarwinProcess_setFromKInfoProc(Process* proc, const struct kinfo_proc* ps, bool exists) {
@@ -270,16 +303,28 @@ void DarwinProcess_setFromKInfoProc(Process* proc, const struct kinfo_proc* ps,
proc->session = 0; /* TODO Get the session id */
proc->tpgid = ps->kp_eproc.e_tpgid;
proc->tgid = proc->pid;
- proc->st_uid = ps->kp_eproc.e_ucred.cr_uid;
- /* e_tdev = (major << 24) | (minor & 0xffffff) */
- /* e_tdev == -1 for "no device" */
- proc->tty_nr = ps->kp_eproc.e_tdev & 0xff; /* TODO tty_nr is unsigned */
+ proc->isKernelThread = false;
+ proc->isUserlandThread = false;
dp->translated = ps->kp_proc.p_flag & P_TRANSLATED;
+ proc->tty_nr = ps->kp_eproc.e_tdev;
+ const char* name = (ps->kp_eproc.e_tdev != NODEV) ? devname(ps->kp_eproc.e_tdev, S_IFCHR) : NULL;
+ if (!name) {
+ free(proc->tty_name);
+ proc->tty_name = NULL;
+ } else {
+ free_and_xStrdup(&proc->tty_name, name);
+ }
+
proc->starttime_ctime = ep->p_starttime.tv_sec;
Process_fillStarttimeBuffer(proc);
- proc->comm = DarwinProcess_getCmdLine(ps, &(proc->basenameOffset));
+ DarwinProcess_updateExe(ep->p_pid, proc);
+ DarwinProcess_updateCmdLine(ps, proc);
+
+ if (proc->settings->flags & PROCESS_FLAG_CWD) {
+ DarwinProcess_updateCwd(ep->p_pid, proc);
+ }
}
/* Mutable information */
@@ -292,21 +337,25 @@ void DarwinProcess_setFromKInfoProc(Process* proc, const struct kinfo_proc* ps,
proc->updated = true;
}
-void DarwinProcess_setFromLibprocPidinfo(DarwinProcess* proc, DarwinProcessList* dpl, double time_interval) {
+void DarwinProcess_setFromLibprocPidinfo(DarwinProcess* proc, DarwinProcessList* dpl, double timeIntervalNS) {
struct proc_taskinfo pti;
if (sizeof(pti) == proc_pidinfo(proc->super.pid, PROC_PIDTASKINFO, 0, &pti, sizeof(pti))) {
- uint64_t total_existing_time = proc->stime + proc->utime;
- uint64_t total_current_time = pti.pti_total_system + pti.pti_total_user;
+ uint64_t total_existing_time_ns = proc->stime + proc->utime;
+
+ uint64_t user_time_ns = Platform_machTicksToNanoseconds(pti.pti_total_user);
+ uint64_t system_time_ns = Platform_machTicksToNanoseconds(pti.pti_total_system);
+
+ uint64_t total_current_time_ns = user_time_ns + system_time_ns;
- if (total_existing_time && 1E-6 < time_interval) {
- uint64_t total_time_diff = total_current_time - total_existing_time;
- proc->super.percent_cpu = ((double)total_time_diff / time_interval) * 100.0;
+ if (total_existing_time_ns && 1E-6 < timeIntervalNS) {
+ uint64_t total_time_diff_ns = total_current_time_ns - total_existing_time_ns;
+ proc->super.percent_cpu = ((double)total_time_diff_ns / timeIntervalNS) * 100.0;
} else {
proc->super.percent_cpu = 0.0;
}
- proc->super.time = total_current_time / 10000000;
+ proc->super.time = nanosecondsToCentiseconds(total_current_time_ns);
proc->super.nlwp = pti.pti_threadnum;
proc->super.m_virt = pti.pti_virtual_size / ONE_K;
proc->super.m_resident = pti.pti_resident_size / ONE_K;
@@ -314,8 +363,8 @@ void DarwinProcess_setFromLibprocPidinfo(DarwinProcess* proc, DarwinProcessList*
proc->super.percent_mem = (double)pti.pti_resident_size * 100.0
/ (double)dpl->host_info.max_mem;
- proc->stime = pti.pti_total_system;
- proc->utime = pti.pti_total_user;
+ proc->stime = system_time_ns;
+ proc->utime = user_time_ns;
dpl->super.kernelThreads += 0; /*pti.pti_threads_system;*/
dpl->super.userlandThreads += pti.pti_threadnum; /*pti.pti_threads_user;*/
diff --git a/darwin/DarwinProcess.h b/darwin/DarwinProcess.h
index f87dd18..0a49eea 100644
--- a/darwin/DarwinProcess.h
+++ b/darwin/DarwinProcess.h
@@ -9,9 +9,8 @@ in the source distribution for its full text.
#include <sys/sysctl.h>
-#include "DarwinProcessList.h"
#include "Settings.h"
-
+#include "darwin/DarwinProcessList.h"
typedef struct DarwinProcess_ {
Process super;
@@ -30,11 +29,9 @@ Process* DarwinProcess_new(const Settings* settings);
void Process_delete(Object* cast);
-bool Process_isThread(const Process* this);
-
void DarwinProcess_setFromKInfoProc(Process* proc, const struct kinfo_proc* ps, bool exists);
-void DarwinProcess_setFromLibprocPidinfo(DarwinProcess* proc, DarwinProcessList* dpl, double time_interval);
+void DarwinProcess_setFromLibprocPidinfo(DarwinProcess* proc, DarwinProcessList* dpl, double timeIntervalNS);
/*
* Scan threads for process state information.
diff --git a/darwin/DarwinProcessList.c b/darwin/DarwinProcessList.c
index 4333710..7dd86ff 100644
--- a/darwin/DarwinProcessList.c
+++ b/darwin/DarwinProcessList.c
@@ -5,7 +5,7 @@ Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text.
*/
-#include "DarwinProcessList.h"
+#include "darwin/DarwinProcessList.h"
#include <errno.h>
#include <libproc.h>
@@ -19,10 +19,10 @@ in the source distribution for its full text.
#include <sys/sysctl.h>
#include "CRT.h"
-#include "DarwinProcess.h"
-#include "Platform.h"
#include "ProcessList.h"
-#include "zfs/openzfs_sysctl.h"
+#include "darwin/DarwinProcess.h"
+#include "darwin/Platform.h"
+#include "generic/openzfs_sysctl.h"
#include "zfs/ZfsArcStats.h"
@@ -128,13 +128,15 @@ static struct kinfo_proc* ProcessList_getKInfoProcs(size_t* count) {
CRT_fatalError("Unable to get kinfo_procs");
}
-ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidMatchList, uid_t userId) {
+ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* dynamicMeters, Hashtable* dynamicColumns, Hashtable* pidMatchList, uid_t userId) {
DarwinProcessList* this = xCalloc(1, sizeof(DarwinProcessList));
- ProcessList_init(&this->super, Class(DarwinProcess), usersTable, pidMatchList, userId);
+ ProcessList_init(&this->super, Class(DarwinProcess), usersTable, dynamicMeters, dynamicColumns, pidMatchList, userId);
/* Initialize the CPU information */
- this->super.cpuCount = ProcessList_allocateCPULoadInfo(&this->prev_load);
+ this->super.activeCPUs = ProcessList_allocateCPULoadInfo(&this->prev_load);
+ // TODO: support offline CPUs and hot swapping
+ this->super.existingCPUs = this->super.activeCPUs;
ProcessList_getHostInfo(&this->host_info);
ProcessList_allocateCPULoadInfo(&this->curr_load);
@@ -158,11 +160,6 @@ void ProcessList_delete(ProcessList* this) {
free(this);
}
-static double ticksToNanoseconds(const double ticks) {
- const double nanos_per_sec = 1e9;
- return (ticks / Platform_timebaseToNS) * (nanos_per_sec / (double) Platform_clockTicksPerSec);
-}
-
void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate) {
DarwinProcessList* dpl = (DarwinProcessList*)super;
bool preExisting = true;
@@ -184,13 +181,13 @@ void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate) {
/* Get the time difference */
dpl->global_diff = 0;
- for (int i = 0; i < dpl->super.cpuCount; ++i) {
+ for (unsigned int i = 0; i < dpl->super.existingCPUs; ++i) {
for (size_t j = 0; j < CPU_STATE_MAX; ++j) {
dpl->global_diff += dpl->curr_load[i].cpu_ticks[j] - dpl->prev_load[i].cpu_ticks[j];
}
}
- const double time_interval = ticksToNanoseconds(dpl->global_diff) / (double) dpl->super.cpuCount;
+ const double time_interval_ns = Platform_schedulerTicksToNanoseconds(dpl->global_diff) / (double) dpl->super.activeCPUs;
/* Clear the thread counts */
super->kernelThreads = 0;
@@ -211,7 +208,12 @@ void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate) {
proc = (DarwinProcess*)ProcessList_getProcess(super, ps[i].kp_proc.p_pid, &preExisting, DarwinProcess_new);
DarwinProcess_setFromKInfoProc(&proc->super, &ps[i], preExisting);
- DarwinProcess_setFromLibprocPidinfo(proc, dpl, time_interval);
+ DarwinProcess_setFromLibprocPidinfo(proc, dpl, time_interval_ns);
+
+ if (proc->super.st_uid != ps[i].kp_eproc.e_ucred.cr_uid) {
+ proc->super.st_uid = ps[i].kp_eproc.e_ucred.cr_uid;
+ proc->super.user = UsersTable_getRef(super->usersTable, proc->super.st_uid);
+ }
// Disabled for High Sierra due to bug in macOS High Sierra
bool isScanThreadSupported = ! ( CompareKernelVersion(17, 0, 0) >= 0 && CompareKernelVersion(17, 5, 0) < 0);
@@ -223,11 +225,18 @@ void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate) {
super->totalTasks += 1;
if (!preExisting) {
- proc->super.user = UsersTable_getRef(super->usersTable, proc->super.st_uid);
-
ProcessList_add(super, &proc->super);
}
}
free(ps);
}
+
+bool ProcessList_isCPUonline(const ProcessList* super, unsigned int id) {
+ assert(id < super->existingCPUs);
+
+ // TODO: support offline CPUs and hot swapping
+ (void) super; (void) id;
+
+ return true;
+}
diff --git a/darwin/DarwinProcessList.h b/darwin/DarwinProcessList.h
index 1ae2f2b..af1140b 100644
--- a/darwin/DarwinProcessList.h
+++ b/darwin/DarwinProcessList.h
@@ -28,10 +28,12 @@ typedef struct DarwinProcessList_ {
ZfsArcStats zfs;
} DarwinProcessList;
-ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidMatchList, uid_t userId);
+ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* dynamicMeters, Hashtable* dynamicColumns, Hashtable* pidMatchList, uid_t userId);
void ProcessList_delete(ProcessList* this);
void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate);
+bool ProcessList_isCPUonline(const ProcessList* super, unsigned int id);
+
#endif
diff --git a/darwin/Platform.c b/darwin/Platform.c
index a4ed464..93262bb 100644
--- a/darwin/Platform.c
+++ b/darwin/Platform.c
@@ -8,7 +8,7 @@ in the source distribution for its full text.
#include "config.h" // IWYU pragma: keep
-#include "Platform.h"
+#include "darwin/Platform.h"
#include <errno.h>
#include <math.h>
@@ -22,20 +22,26 @@ in the source distribution for its full text.
#include "ClockMeter.h"
#include "CPUMeter.h"
#include "CRT.h"
-#include "DarwinProcessList.h"
#include "DateMeter.h"
#include "DateTimeMeter.h"
#include "HostnameMeter.h"
#include "LoadAverageMeter.h"
#include "Macros.h"
#include "MemoryMeter.h"
+#include "MemorySwapMeter.h"
#include "ProcessLocksScreen.h"
#include "SwapMeter.h"
+#include "SysArchMeter.h"
#include "TasksMeter.h"
#include "UptimeMeter.h"
+#include "darwin/DarwinProcessList.h"
#include "zfs/ZfsArcMeter.h"
#include "zfs/ZfsCompressedArcMeter.h"
+#ifdef HAVE_HOST_GET_CLOCK_SERVICE
+#include <mach/clock.h>
+#include <mach/mach.h>
+#endif
#ifdef HAVE_MACH_MACH_TIME_H
#include <mach/mach_time.h>
#endif
@@ -90,9 +96,11 @@ const MeterClass* const Platform_meterTypes[] = {
&LoadMeter_class,
&MemoryMeter_class,
&SwapMeter_class,
+ &MemorySwapMeter_class,
&TasksMeter_class,
&BatteryMeter_class,
&HostnameMeter_class,
+ &SysArchMeter_class,
&UptimeMeter_class,
&AllCPUsMeter_class,
&AllCPUs2Meter_class,
@@ -112,9 +120,9 @@ const MeterClass* const Platform_meterTypes[] = {
NULL
};
-double Platform_timebaseToNS = 1.0;
+static double Platform_nanosecondsPerMachTick = 1.0;
-long Platform_clockTicksPerSec = -1;
+static double Platform_nanosecondsPerSchedulerTick = -1;
void Platform_init(void) {
// Check if we can determine the timebase used on this system.
@@ -122,18 +130,33 @@ void Platform_init(void) {
#ifdef HAVE_MACH_TIMEBASE_INFO
mach_timebase_info_data_t info;
mach_timebase_info(&info);
- Platform_timebaseToNS = (double)info.numer / (double)info.denom;
+ Platform_nanosecondsPerMachTick = (double)info.numer / (double)info.denom;
#else
- Platform_timebaseToNS = 1.0;
+ Platform_nanosecondsPerMachTick = 1.0;
#endif
- // Determine the number of clock ticks per second
+ // Determine the number of scheduler clock ticks per second
errno = 0;
- Platform_clockTicksPerSec = sysconf(_SC_CLK_TCK);
+ long scheduler_ticks_per_sec = sysconf(_SC_CLK_TCK);
- if (errno || Platform_clockTicksPerSec < 1) {
+ if (errno || scheduler_ticks_per_sec < 1) {
CRT_fatalError("Unable to retrieve clock tick rate");
}
+
+ const double nanos_per_sec = 1e9;
+ Platform_nanosecondsPerSchedulerTick = nanos_per_sec / scheduler_ticks_per_sec;
+}
+
+// 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.
+// See `sysconf(_SC_CLK_TCK)`, as used to define the `Platform_nanosecondsPerSchedulerTick` constant.
+double Platform_schedulerTicksToNanoseconds(const double scheduler_ticks) {
+ return scheduler_ticks * Platform_nanosecondsPerSchedulerTick;
}
void Platform_done(void) {
@@ -180,24 +203,24 @@ int Platform_getMaxPid() {
static double Platform_setCPUAverageValues(Meter* mtr) {
const ProcessList* dpl = mtr->pl;
- int cpus = dpl->cpuCount;
+ unsigned int activeCPUs = dpl->activeCPUs;
double sumNice = 0.0;
double sumNormal = 0.0;
double sumKernel = 0.0;
double sumPercent = 0.0;
- for (int i = 1; i <= cpus; i++) {
+ for (unsigned int i = 1; i <= dpl->existingCPUs; i++) {
sumPercent += Platform_setCPUValues(mtr, i);
sumNice += mtr->values[CPU_METER_NICE];
sumNormal += mtr->values[CPU_METER_NORMAL];
sumKernel += mtr->values[CPU_METER_KERNEL];
}
- mtr->values[CPU_METER_NICE] = sumNice / cpus;
- mtr->values[CPU_METER_NORMAL] = sumNormal / cpus;
- mtr->values[CPU_METER_KERNEL] = sumKernel / cpus;
- return sumPercent / cpus;
+ mtr->values[CPU_METER_NICE] = sumNice / activeCPUs;
+ mtr->values[CPU_METER_NORMAL] = sumNormal / activeCPUs;
+ mtr->values[CPU_METER_KERNEL] = sumKernel / activeCPUs;
+ return sumPercent / activeCPUs;
}
-double Platform_setCPUValues(Meter* mtr, int cpu) {
+double Platform_setCPUValues(Meter* mtr, unsigned int cpu) {
if (cpu == 0) {
return Platform_setCPUAverageValues(mtr);
@@ -239,7 +262,9 @@ void Platform_setMemoryValues(Meter* mtr) {
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;
- mtr->values[2] = (double)vm->inactive_count * page_K;
+ // mtr->values[2] = "shared memory, like tmpfs and shm"
+ mtr->values[3] = (double)vm->inactive_count * page_K;
+ // mtr->values[4] = "available memory"
}
void Platform_setSwapValues(Meter* mtr) {
@@ -316,14 +341,14 @@ char* Platform_getProcessEnv(pid_t pid) {
}
char* Platform_getInodeFilename(pid_t pid, ino_t inode) {
- (void)pid;
- (void)inode;
- return NULL;
+ (void)pid;
+ (void)inode;
+ return NULL;
}
FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid) {
- (void)pid;
- return NULL;
+ (void)pid;
+ return NULL;
}
bool Platform_getDiskIO(DiskIOData* data) {
@@ -332,78 +357,83 @@ bool Platform_getDiskIO(DiskIOData* data) {
return false;
}
-bool Platform_getNetworkIO(unsigned long int* bytesReceived,
- unsigned long int* packetsReceived,
- unsigned long int* bytesTransmitted,
- unsigned long int* packetsTransmitted) {
+bool Platform_getNetworkIO(NetworkIOData* data) {
// TODO
- *bytesReceived = 0;
- *packetsReceived = 0;
- *bytesTransmitted = 0;
- *packetsTransmitted = 0;
+ (void)data;
return false;
}
void Platform_getBattery(double* percent, ACPresence* isOnAC) {
- CFTypeRef power_sources = IOPSCopyPowerSourcesInfo();
-
*percent = NAN;
*isOnAC = AC_ERROR;
- if (NULL == power_sources)
- return;
+ CFArrayRef list = NULL;
- CFArrayRef list = IOPSCopyPowerSourcesList(power_sources);
- CFDictionaryRef battery = NULL;
- int len;
-
- if (NULL == list) {
- CFRelease(power_sources);
+ CFTypeRef power_sources = IOPSCopyPowerSourcesInfo();
+ if (!power_sources)
+ goto cleanup;
- return;
- }
+ list = IOPSCopyPowerSourcesList(power_sources);
+ if (!list)
+ goto cleanup;
- len = CFArrayGetCount(list);
+ double cap_current = 0.0;
+ double cap_max = 0.0;
/* Get the battery */
- for (int i = 0; i < len && battery == NULL; ++i) {
- CFDictionaryRef candidate = IOPSGetPowerSourceDescription(power_sources,
- CFArrayGetValueAtIndex(list, i)); /* GET rule */
- CFStringRef type;
-
- if (NULL != candidate) {
- type = (CFStringRef) CFDictionaryGetValue(candidate,
- CFSTR(kIOPSTransportTypeKey)); /* GET rule */
-
- if (kCFCompareEqualTo == CFStringCompare(type, CFSTR(kIOPSInternalType), 0)) {
- CFRetain(candidate);
- battery = candidate;
- }
- }
- }
+ for (int i = 0, len = CFArrayGetCount(list); i < len; ++i) {
+ CFDictionaryRef power_source = IOPSGetPowerSourceDescription(power_sources, CFArrayGetValueAtIndex(list, i)); /* GET rule */
+
+ if (!power_source)
+ continue;
+
+ CFStringRef power_type = CFDictionaryGetValue(power_source, CFSTR(kIOPSTransportTypeKey)); /* GET rule */
+
+ if (kCFCompareEqualTo != CFStringCompare(power_type, CFSTR(kIOPSInternalType), 0))
+ continue;
- if (NULL != battery) {
/* Determine the AC state */
- CFStringRef power_state = CFDictionaryGetValue(battery, CFSTR(kIOPSPowerSourceStateKey));
+ CFStringRef power_state = CFDictionaryGetValue(power_source, CFSTR(kIOPSPowerSourceStateKey));
- *isOnAC = (kCFCompareEqualTo == CFStringCompare(power_state, CFSTR(kIOPSACPowerValue), 0))
- ? AC_PRESENT
- : AC_ABSENT;
+ if (*isOnAC != AC_PRESENT)
+ *isOnAC = (kCFCompareEqualTo == CFStringCompare(power_state, CFSTR(kIOPSACPowerValue), 0)) ? AC_PRESENT : AC_ABSENT;
/* Get the percentage remaining */
- double current;
- double max;
+ double tmp;
+ CFNumberGetValue(CFDictionaryGetValue(power_source, CFSTR(kIOPSCurrentCapacityKey)), kCFNumberDoubleType, &tmp);
+ cap_current += tmp;
+ CFNumberGetValue(CFDictionaryGetValue(power_source, CFSTR(kIOPSMaxCapacityKey)), kCFNumberDoubleType, &tmp);
+ cap_max += tmp;
+ }
- CFNumberGetValue(CFDictionaryGetValue(battery, CFSTR(kIOPSCurrentCapacityKey)),
- kCFNumberDoubleType, &current);
- CFNumberGetValue(CFDictionaryGetValue(battery, CFSTR(kIOPSMaxCapacityKey)),
- kCFNumberDoubleType, &max);
+ if (cap_max > 0.0)
+ *percent = 100.0 * cap_current / cap_max;
- *percent = (current * 100.0) / max;
+cleanup:
+ if (list)
+ CFRelease(list);
- CFRelease(battery);
- }
+ if (power_sources)
+ CFRelease(power_sources);
+}
+
+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_monotonic(msec);
+
+#endif
- CFRelease(list);
- CFRelease(power_sources);
}
diff --git a/darwin/Platform.h b/darwin/Platform.h
index 623063b..e7647db 100644
--- a/darwin/Platform.h
+++ b/darwin/Platform.h
@@ -14,18 +14,19 @@ in the source distribution for its full text.
#include "Action.h"
#include "BatteryMeter.h"
#include "CPUMeter.h"
-#include "DarwinProcess.h"
#include "DiskIOMeter.h"
+#include "Hashtable.h"
+#include "NetworkIOMeter.h"
#include "ProcessLocksScreen.h"
#include "SignalsPanel.h"
+#include "darwin/DarwinProcess.h"
+#include "generic/gettime.h"
+#include "generic/hostname.h"
+#include "generic/uname.h"
extern const ProcessField Platform_defaultFields[];
-extern double Platform_timebaseToNS;
-
-extern long Platform_clockTicksPerSec;
-
extern const SignalItem Platform_signals[];
extern const unsigned int Platform_numberOfSignals;
@@ -34,6 +35,14 @@ extern const MeterClass* const Platform_meterTypes[];
void Platform_init(void);
+// 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);
+
+// Converts "scheduler ticks" to nanoseconds.
+// See `sysconf(_SC_CLK_TCK)`, as used to define the `Platform_nanosecondsPerSchedulerTick` constant.
+double Platform_schedulerTicksToNanoseconds(const double scheduler_ticks);
+
void Platform_done(void);
void Platform_setBindings(Htop_Action* keys);
@@ -44,7 +53,7 @@ void Platform_getLoadAverage(double* one, double* five, double* fifteen);
int Platform_getMaxPid(void);
-double Platform_setCPUValues(Meter* mtr, int cpu);
+double Platform_setCPUValues(Meter* mtr, unsigned int cpu);
void Platform_setMemoryValues(Meter* mtr);
@@ -62,11 +71,48 @@ FileLocks_ProcessData* Platform_getProcessLocks(pid_t pid);
bool Platform_getDiskIO(DiskIOData* data);
-bool Platform_getNetworkIO(unsigned long int* bytesReceived,
- unsigned long int* packetsReceived,
- unsigned long int* bytesTransmitted,
- unsigned long int* packetsTransmitted);
+bool Platform_getNetworkIO(NetworkIOData* data);
+
+void Platform_getBattery(double* percent, ACPresence* isOnAC);
+
+static inline void Platform_getHostname(char* buffer, size_t size) {
+ Generic_hostname(buffer, size);
+}
+
+static inline void Platform_getRelease(char** string) {
+ *string = Generic_uname();
+}
+
+#define PLATFORM_LONG_OPTIONS
+
+static inline void Platform_longOptionsUsage(ATTR_UNUSED const char* name) { }
+
+static inline bool Platform_getLongOption(ATTR_UNUSED int opt, ATTR_UNUSED int argc, ATTR_UNUSED char** argv) {
+ return false;
+}
+
+static inline void Platform_gettime_realtime(struct timeval* tv, uint64_t* msec) {
+ Generic_gettime_realtime(tv, msec);
+}
+
+void Platform_gettime_monotonic(uint64_t* msec);
+
+static inline Hashtable* Platform_dynamicMeters(void) { return NULL; }
+
+static inline void Platform_dynamicMetersDone(ATTR_UNUSED Hashtable* table) { }
+
+static inline void Platform_dynamicMeterInit(ATTR_UNUSED Meter* meter) { }
+
+static inline void Platform_dynamicMeterUpdateValues(ATTR_UNUSED Meter* meter) { }
+
+static inline void Platform_dynamicMeterDisplay(ATTR_UNUSED const Meter* meter, ATTR_UNUSED RichString* out) { }
+
+static inline Hashtable* Platform_dynamicColumns(void) { return NULL; }
+
+static inline void Platform_dynamicColumnsDone(ATTR_UNUSED Hashtable* table) { }
+
+static inline const char* Platform_dynamicColumnInit(ATTR_UNUSED unsigned int key) { return NULL; }
-void Platform_getBattery(double *percent, ACPresence *isOnAC);
+static inline bool Platform_dynamicColumnWriteField(ATTR_UNUSED const Process* proc, ATTR_UNUSED RichString* str, ATTR_UNUSED unsigned int key) { return false; }
#endif
diff --git a/darwin/ProcessField.h b/darwin/ProcessField.h
index 5a8090f..25dbb45 100644
--- a/darwin/ProcessField.h
+++ b/darwin/ProcessField.h
@@ -10,6 +10,8 @@ in the source distribution for its full text.
#define PLATFORM_PROCESS_FIELDS \
TRANSLATED = 100, \
+ \
+ DUMMY_BUMP_FIELD = CWD, \
// End of list

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