blob: 9a2f6d5d0c021b776b8afdd60a2849eec30efe78 [file] [log] [blame]
David Hunt70e7c8d2015-07-12 13:47:43 -05001/*
Nathan Scottb74673f2023-08-31 11:56:43 +10002htop - DarwinProcessTable.c
David Hunt70e7c8d2015-07-12 13:47:43 -05003(C) 2014 Hisham H. Muhammad
Daniel Lange94ad1112021-09-22 11:33:00 +02004Released under the GNU GPLv2+, see the COPYING file
David Hunt70e7c8d2015-07-12 13:47:43 -05005in the source distribution for its full text.
6*/
7
Nathan Scottb74673f2023-08-31 11:56:43 +10008#include "darwin/DarwinProcessTable.h"
David Hunt70e7c8d2015-07-12 13:47:43 -05009
Christian Göttsche72df9302020-11-17 15:17:19 +010010#include <errno.h>
Christian Göttschee3af8d02020-11-17 15:10:44 +010011#include <libproc.h>
12#include <stdbool.h>
13#include <stdio.h>
David Hunt70e7c8d2015-07-12 13:47:43 -050014#include <stdlib.h>
15#include <string.h>
David Hunt43ef7032015-07-13 01:17:14 -050016#include <unistd.h>
David Hunt57ab3322015-07-13 21:02:40 -050017#include <utmpx.h>
Christian Göttschee3af8d02020-11-17 15:10:44 +010018#include <sys/mman.h>
pmalhaire23f96042018-03-25 22:04:16 +020019#include <sys/sysctl.h>
Christian Göttschee3af8d02020-11-17 15:10:44 +010020
21#include "CRT.h"
Nathan Scottb74673f2023-08-31 11:56:43 +100022#include "ProcessTable.h"
Nathan Scott72235d82023-05-02 16:56:18 +100023#include "darwin/DarwinMachine.h"
mayurdahibhate3f86a012021-04-29 23:43:36 +053024#include "darwin/DarwinProcess.h"
25#include "darwin/Platform.h"
Alexander Momchilovdadcb872021-08-22 12:30:08 -040026#include "darwin/PlatformHelpers.h"
Nathan Scottadaf7482021-03-04 09:00:34 +110027#include "generic/openzfs_sysctl.h"
Christian Göttschee3af8d02020-11-17 15:10:44 +010028#include "zfs/ZfsArcStats.h"
29
pmalhaire23f96042018-03-25 22:04:16 +020030
Nathan Scottb74673f2023-08-31 11:56:43 +100031static struct kinfo_proc* ProcessTable_getKInfoProcs(size_t* count) {
David Hunt43ef7032015-07-13 01:17:14 -050032 int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0 };
Benny Baumann61e14d42020-10-31 23:28:02 +010033 struct kinfo_proc* processes = NULL;
David Hunt43ef7032015-07-13 01:17:14 -050034
Christian Göttschebc22bee2022-09-20 21:40:02 +020035 for (unsigned int retry = 0; retry < 4; retry++) {
Christian Göttsche72df9302020-11-17 15:17:19 +010036 size_t size = 0;
37 if (sysctl(mib, 4, NULL, &size, NULL, 0) < 0 || size == 0) {
38 CRT_fatalError("Unable to get size of kproc_infos");
39 }
40
Christian Göttschebc22bee2022-09-20 21:40:02 +020041 size += 16 * retry * retry * sizeof(struct kinfo_proc);
Christian Göttsche72df9302020-11-17 15:17:19 +010042 processes = xRealloc(processes, size);
43
44 if (sysctl(mib, 4, processes, &size, NULL, 0) == 0) {
45 *count = size / sizeof(struct kinfo_proc);
46 return processes;
47 }
48
49 if (errno != ENOMEM)
50 break;
Benny Baumann45869512020-11-01 01:09:51 +010051 }
David Hunt43ef7032015-07-13 01:17:14 -050052
Christian Göttsche72df9302020-11-17 15:17:19 +010053 CRT_fatalError("Unable to get kinfo_procs");
David Hunt43ef7032015-07-13 01:17:14 -050054}
55
Nathan Scottb74673f2023-08-31 11:56:43 +100056ProcessTable* ProcessTable_new(Machine* host, Hashtable* pidMatchList) {
57 DarwinProcessTable* this = xCalloc(1, sizeof(DarwinProcessTable));
58 Object_setClass(this, Class(ProcessTable));
David Hunt43ef7032015-07-13 01:17:14 -050059
Nathan Scottb74673f2023-08-31 11:56:43 +100060 ProcessTable* super = &this->super;
61 ProcessTable_init(super, Class(DarwinProcess), host, pidMatchList);
David Hunt57ab3322015-07-13 21:02:40 -050062
Nathan Scott72235d82023-05-02 16:56:18 +100063 return super;
David Hunt70e7c8d2015-07-12 13:47:43 -050064}
65
Nathan Scottb74673f2023-08-31 11:56:43 +100066void ProcessTable_delete(Object* cast) {
67 DarwinProcessTable* this = (DarwinProcessTable*) cast;
68 ProcessTable_done(&this->super);
David Hunt70e7c8d2015-07-12 13:47:43 -050069 free(this);
70}
71
Nathan Scottb74673f2023-08-31 11:56:43 +100072void ProcessTable_goThroughEntries(ProcessTable* super) {
Nathan Scott0f751e92023-08-22 16:11:05 +100073 const Machine* host = super->super.host;
Nathan Scott72235d82023-05-02 16:56:18 +100074 const DarwinMachine* dhost = (const DarwinMachine*) host;
Nathan Scottb74673f2023-08-31 11:56:43 +100075 DarwinProcessTable* dpt = (DarwinProcessTable*) super;
Benny Baumannb23f8232020-10-31 22:14:27 +010076 bool preExisting = true;
77 struct kinfo_proc* ps;
78 size_t count;
79 DarwinProcess* proc;
David Hunt70e7c8d2015-07-12 13:47:43 -050080
Benny Baumannb23f8232020-10-31 22:14:27 +010081 /* Get the time difference */
Nathan Scottb74673f2023-08-31 11:56:43 +100082 dpt->global_diff = 0;
Nathan Scott0bdade12023-05-02 09:02:22 +100083 for (unsigned int i = 0; i < host->existingCPUs; ++i) {
Benny Baumannb23f8232020-10-31 22:14:27 +010084 for (size_t j = 0; j < CPU_STATE_MAX; ++j) {
Nathan Scottb74673f2023-08-31 11:56:43 +100085 dpt->global_diff += dhost->curr_load[i].cpu_ticks[j] - dhost->prev_load[i].cpu_ticks[j];
Benny Baumannb23f8232020-10-31 22:14:27 +010086 }
87 }
David Hunt907f8292015-07-14 11:46:16 -050088
Nathan Scottb74673f2023-08-31 11:56:43 +100089 const double time_interval_ns = Platform_schedulerTicksToNanoseconds(dpt->global_diff) / (double) host->activeCPUs;
Alexander Momchilov67ccd6b2020-12-08 23:12:44 -050090
Benny Baumannb23f8232020-10-31 22:14:27 +010091 /* We use kinfo_procs for initial data since :
92 *
93 * 1) They always succeed.
Guillaume Gomez8a8df712023-05-05 11:28:41 +020094 * 2) They contain the basic information.
Benny Baumannb23f8232020-10-31 22:14:27 +010095 *
96 * We attempt to fill-in additional information with libproc.
97 */
Nathan Scottb74673f2023-08-31 11:56:43 +100098 ps = ProcessTable_getKInfoProcs(&count);
David Hunt70e7c8d2015-07-12 13:47:43 -050099
Benny Baumannb23f8232020-10-31 22:14:27 +0100100 for (size_t i = 0; i < count; ++i) {
Nathan Scottb74673f2023-08-31 11:56:43 +1000101 proc = (DarwinProcess*)ProcessTable_getProcess(super, ps[i].kp_proc.p_pid, &preExisting, DarwinProcess_new);
David Hunt70e7c8d2015-07-12 13:47:43 -0500102
Benny Baumannb23f8232020-10-31 22:14:27 +0100103 DarwinProcess_setFromKInfoProc(&proc->super, &ps[i], preExisting);
Nathan Scottb74673f2023-08-31 11:56:43 +1000104 DarwinProcess_setFromLibprocPidinfo(proc, dpt, time_interval_ns);
pmalhaire23f96042018-03-25 22:04:16 +0200105
aestriplex847547c2025-02-25 11:14:49 +0100106 // Deduce further process states not covered in the libproc call above
107 if (ps[i].kp_proc.p_stat == SZOMB) {
108 proc->super.state = ZOMBIE;
109 } else if (ps[i].kp_proc.p_stat == SSTOP) {
110 proc->super.state = STOPPED;
111 }
112
Benny Baumann6a6b09b2021-06-18 20:42:04 +0200113 if (proc->super.st_uid != ps[i].kp_eproc.e_ucred.cr_uid) {
114 proc->super.st_uid = ps[i].kp_eproc.e_ucred.cr_uid;
Nathan Scott0bdade12023-05-02 09:02:22 +1000115 proc->super.user = UsersTable_getRef(host->usersTable, proc->super.st_uid);
Benny Baumann6a6b09b2021-06-18 20:42:04 +0200116 }
117
Benny Baumannb23f8232020-10-31 22:14:27 +0100118 // Disabled for High Sierra due to bug in macOS High Sierra
Nathan Scott72235d82023-05-02 16:56:18 +1000119 bool isScanThreadSupported = !Platform_KernelVersionIsBetween((KernelVersion) {17, 0, 0}, (KernelVersion) {17, 5, 0});
pmalhaire23f96042018-03-25 22:04:16 +0200120
Benny Baumannb23f8232020-10-31 22:14:27 +0100121 if (isScanThreadSupported) {
robaho4c0e9652021-02-28 18:37:44 +0100122 DarwinProcess_scanThreads(proc, dpt);
Benny Baumannb23f8232020-10-31 22:14:27 +0100123 }
David Hunt57ab3322015-07-13 21:02:40 -0500124
Benny Baumannb23f8232020-10-31 22:14:27 +0100125 super->totalTasks += 1;
David Hunt70e7c8d2015-07-12 13:47:43 -0500126
Benny Baumannb23f8232020-10-31 22:14:27 +0100127 if (!preExisting) {
Nathan Scottb74673f2023-08-31 11:56:43 +1000128 ProcessTable_add(super, &proc->super);
Benny Baumannb23f8232020-10-31 22:14:27 +0100129 }
130 }
David Hunt70e7c8d2015-07-12 13:47:43 -0500131
Benny Baumannb23f8232020-10-31 22:14:27 +0100132 free(ps);
David Hunt70e7c8d2015-07-12 13:47:43 -0500133}