aboutsummaryrefslogtreecommitdiffstats
path: root/solaris/SolarisProcessTable.c
diff options
context:
space:
mode:
authorDaniel Lange <DLange@git.local>2024-01-10 12:40:37 +0100
committerDaniel Lange <DLange@git.local>2024-01-10 12:40:37 +0100
commit7271b076b82785ffca73ee9e4ae84cabb77018ee (patch)
treee8270dd60ec096bee8157dbadf029e15ed584592 /solaris/SolarisProcessTable.c
parentf288666edc9180a2e81e6655951878124f321df6 (diff)
downloaddebian_htop-7271b076b82785ffca73ee9e4ae84cabb77018ee.tar.gz
debian_htop-7271b076b82785ffca73ee9e4ae84cabb77018ee.tar.bz2
debian_htop-7271b076b82785ffca73ee9e4ae84cabb77018ee.zip
New upstream version 3.3.0upstream/3.3.0upstream
Diffstat (limited to 'solaris/SolarisProcessTable.c')
-rw-r--r--solaris/SolarisProcessTable.c268
1 files changed, 268 insertions, 0 deletions
diff --git a/solaris/SolarisProcessTable.c b/solaris/SolarisProcessTable.c
new file mode 100644
index 0000000..549c753
--- /dev/null
+++ b/solaris/SolarisProcessTable.c
@@ -0,0 +1,268 @@
+/*
+htop - SolarisProcessTable.c
+(C) 2014 Hisham H. Muhammad
+(C) 2017,2018 Guy M. Broome
+Released under the GNU GPLv2+, see the COPYING file
+in the source distribution for its full text.
+*/
+
+#include "config.h" // IWYU pragma: keep
+
+#include "solaris/SolarisProcessTable.h"
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/user.h>
+#include <limits.h>
+#include <string.h>
+#include <procfs.h>
+#include <errno.h>
+#include <pwd.h>
+#include <math.h>
+#include <time.h>
+
+#include "CRT.h"
+#include "solaris/Platform.h"
+#include "solaris/SolarisProcess.h"
+
+
+#define GZONE "global "
+#define UZONE "unknown "
+
+static char* SolarisProcessTable_readZoneName(kstat_ctl_t* kd, SolarisProcess* sproc) {
+ char* zname;
+
+ if ( sproc->zoneid == 0 ) {
+ zname = xStrdup(GZONE);
+ } else if ( kd == NULL ) {
+ zname = xStrdup(UZONE);
+ } else {
+ kstat_t* ks = kstat_lookup_wrapper( kd, "zones", sproc->zoneid, NULL );
+ zname = xStrdup(ks == NULL ? UZONE : ks->ks_name);
+ }
+
+ return zname;
+}
+
+ProcessTable* ProcessTable_new(Machine* host, Hashtable* pidMatchList) {
+ SolarisProcessTable* this = xCalloc(1, sizeof(SolarisProcessTable));
+ Object_setClass(this, Class(ProcessTable));
+
+ ProcessTable* super = &this->super;
+ ProcessTable_init(super, Class(SolarisProcess), host, pidMatchList);
+
+ return super;
+}
+
+void ProcessTable_delete(Object* cast) {
+ SolarisProcessTable* this = (SolarisProcessTable*) cast;
+ ProcessTable_done(&this->super);
+ free(this);
+}
+
+static void SolarisProcessTable_updateExe(pid_t pid, Process* proc) {
+ char path[32];
+ xSnprintf(path, sizeof(path), "/proc/%d/path/a.out", pid);
+
+ char target[PATH_MAX];
+ ssize_t ret = readlink(path, target, sizeof(target) - 1);
+ if (ret <= 0)
+ return;
+
+ target[ret] = '\0';
+ Process_updateExe(proc, target);
+}
+
+static void SolarisProcessTable_updateCwd(pid_t pid, Process* proc) {
+ char path[32];
+ xSnprintf(path, sizeof(path), "/proc/%d/cwd", pid);
+
+ char target[PATH_MAX];
+ ssize_t ret = readlink(path, target, sizeof(target) - 1);
+ if (ret <= 0)
+ return;
+
+ target[ret] = '\0';
+ free_and_xStrdup(&proc->procCwd, target);
+}
+
+/* Taken from: https://docs.oracle.com/cd/E19253-01/817-6223/6mlkidlom/index.html#tbl-sched-state */
+static inline ProcessState SolarisProcessTable_getProcessState(char state) {
+ switch (state) {
+ case 'S': return SLEEPING;
+ case 'R': return RUNNABLE;
+ case 'O': return RUNNING;
+ case 'Z': return ZOMBIE;
+ case 'T': return STOPPED;
+ case 'I': return IDLE;
+ default: return UNKNOWN;
+ }
+}
+
+/* NOTE: the following is a callback function of type proc_walk_f
+ * and MUST conform to the appropriate definition in order
+ * to work. See libproc(3LIB) on a Solaris or Illumos
+ * system for more info.
+ */
+
+static int SolarisProcessTable_walkproc(psinfo_t* _psinfo, lwpsinfo_t* _lwpsinfo, void* listptr) {
+ bool preExisting;
+ pid_t getpid;
+
+ // Setup process list
+ ProcessTable* pt = (ProcessTable*) listptr;
+ SolarisProcessTable* spt = (SolarisProcessTable*) listptr;
+ Machine* host = pt->host;
+
+ id_t lwpid_real = _lwpsinfo->pr_lwpid;
+ if (lwpid_real > 1023) {
+ return 0;
+ }
+
+ pid_t lwpid = (_psinfo->pr_pid * 1024) + lwpid_real;
+ bool onMasterLWP = (_lwpsinfo->pr_lwpid == _psinfo->pr_lwp.pr_lwpid);
+ if (onMasterLWP) {
+ getpid = _psinfo->pr_pid * 1024;
+ } else {
+ getpid = lwpid;
+ }
+
+ Process* proc = ProcessTable_getProcess(pt, getpid, &preExisting, SolarisProcess_new);
+ SolarisProcess* sproc = (SolarisProcess*) proc;
+ const Settings* settings = host->settings;
+
+ // Common code pass 1
+ proc->show = false;
+ sproc->taskid = _psinfo->pr_taskid;
+ sproc->projid = _psinfo->pr_projid;
+ sproc->poolid = _psinfo->pr_poolid;
+ sproc->contid = _psinfo->pr_contract;
+ proc->priority = _lwpsinfo->pr_pri;
+ proc->nice = _lwpsinfo->pr_nice - NZERO;
+ proc->processor = _lwpsinfo->pr_onpro;
+ proc->state = SolarisProcessTable_getProcessState(_lwpsinfo->pr_sname);
+ // NOTE: This 'percentage' is a 16-bit BINARY FRACTIONS where 1.0 = 0x8000
+ // Source: https://docs.oracle.com/cd/E19253-01/816-5174/proc-4/index.html
+ // (accessed on 18 November 2017)
+ proc->percent_mem = ((uint16_t)_psinfo->pr_pctmem / (double)32768) * (double)100.0;
+ proc->pgrp = _psinfo->pr_pgid;
+ proc->nlwp = _psinfo->pr_nlwp;
+ proc->session = _psinfo->pr_sid;
+
+ proc->tty_nr = _psinfo->pr_ttydev;
+ const char* name = (_psinfo->pr_ttydev != PRNODEV) ? ttyname(_psinfo->pr_ttydev) : NULL;
+ if (!name) {
+ free(proc->tty_name);
+ proc->tty_name = NULL;
+ } else {
+ free_and_xStrdup(&proc->tty_name, name);
+ }
+
+ proc->m_resident = _psinfo->pr_rssize; // KB
+ proc->m_virt = _psinfo->pr_size; // KB
+
+ if (proc->st_uid != _psinfo->pr_euid) {
+ proc->st_uid = _psinfo->pr_euid;
+ proc->user = UsersTable_getRef(host->usersTable, proc->st_uid);
+ }
+
+ if (!preExisting) {
+ sproc->realpid = _psinfo->pr_pid;
+ sproc->lwpid = lwpid_real;
+ sproc->zoneid = _psinfo->pr_zoneid;
+ sproc->zname = SolarisProcessTable_readZoneName(spt->kd, sproc);
+ SolarisProcessTable_updateExe(_psinfo->pr_pid, proc);
+
+ Process_updateComm(proc, _psinfo->pr_fname);
+ Process_updateCmdline(proc, _psinfo->pr_psargs, 0, 0);
+
+ if (settings->ss->flags & PROCESS_FLAG_CWD) {
+ SolarisProcessTable_updateCwd(_psinfo->pr_pid, proc);
+ }
+ }
+
+ // End common code pass 1
+
+ if (onMasterLWP) { // Are we on the representative LWP?
+ Process_setParent(proc, (_psinfo->pr_ppid * 1024));
+ Process_setThreadGroup(proc, (_psinfo->pr_ppid * 1024));
+ sproc->realppid = _psinfo->pr_ppid;
+ sproc->realtgid = _psinfo->pr_ppid;
+
+ // See note above (in common section) about this BINARY FRACTION
+ proc->percent_cpu = ((uint16_t)_psinfo->pr_pctcpu / (double)32768) * (double)100.0;
+ Process_updateCPUFieldWidths(proc->percent_cpu);
+
+ proc->time = _psinfo->pr_time.tv_sec * 100 + _psinfo->pr_time.tv_nsec / 10000000;
+ if (!preExisting) { // Tasks done only for NEW processes
+ proc->isUserlandThread = false;
+ proc->starttime_ctime = _psinfo->pr_start.tv_sec;
+ }
+
+ // Update proc and thread counts based on settings
+ if (proc->isKernelThread && !settings->hideKernelThreads) {
+ pt->kernelThreads += proc->nlwp;
+ pt->totalTasks += proc->nlwp + 1;
+ if (proc->state == RUNNING) {
+ pt->runningTasks++;
+ }
+ } else if (!proc->isKernelThread) {
+ if (proc->state == RUNNING) {
+ pt->runningTasks++;
+ }
+ if (settings->hideUserlandThreads) {
+ pt->totalTasks++;
+ } else {
+ pt->userlandThreads += proc->nlwp;
+ pt->totalTasks += proc->nlwp + 1;
+ }
+ }
+ proc->show = !(settings->hideKernelThreads && proc->isKernelThread);
+ } else { // We are not in the master LWP, so jump to the LWP handling code
+ proc->percent_cpu = ((uint16_t)_lwpsinfo->pr_pctcpu / (double)32768) * (double)100.0;
+ Process_updateCPUFieldWidths(proc->percent_cpu);
+
+ proc->time = _lwpsinfo->pr_time.tv_sec * 100 + _lwpsinfo->pr_time.tv_nsec / 10000000;
+ if (!preExisting) { // Tasks done only for NEW LWPs
+ proc->isUserlandThread = true;
+ Process_setParent(proc, _psinfo->pr_pid * 1024);
+ Process_setThreadGroup(proc, _psinfo->pr_pid * 1024);
+ sproc->realppid = _psinfo->pr_pid;
+ sproc->realtgid = _psinfo->pr_pid;
+ proc->starttime_ctime = _lwpsinfo->pr_start.tv_sec;
+ }
+
+ // Top-level process only gets this for the representative LWP
+ if (proc->isKernelThread && !settings->hideKernelThreads) {
+ proc->super.show = true;
+ }
+ if (!proc->isKernelThread && !settings->hideUserlandThreads) {
+ proc->super.show = true;
+ }
+ } // Top-level LWP or subordinate LWP
+
+ // Common code pass 2
+
+ if (!preExisting) {
+ if ((sproc->realppid <= 0) && !(sproc->realpid <= 1)) {
+ proc->isKernelThread = true;
+ } else {
+ proc->isKernelThread = false;
+ }
+
+ Process_fillStarttimeBuffer(proc);
+ ProcessTable_add(pt, proc);
+ }
+
+ proc->super.updated = true;
+
+ // End common code pass 2
+
+ return 0;
+}
+
+void ProcessTable_goThroughEntries(ProcessTable* super) {
+ super->kernelThreads = 1;
+ proc_walk(&SolarisProcessTable_walkproc, super, PR_WALK_LWP);
+}

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