From 7224d0e0831ee53d5028915f87dffd51ffa0d6fa Mon Sep 17 00:00:00 2001 From: Benny Baumann Date: Sat, 10 Apr 2021 14:08:26 +0200 Subject: [PATCH] Move kernel/userland thread handling to platform-independent implementation --- Process.h | 19 ++++++++++++++++++- darwin/DarwinProcess.c | 7 ++----- darwin/DarwinProcess.h | 2 -- dragonflybsd/DragonFlyBSDProcess.c | 10 ---------- dragonflybsd/DragonFlyBSDProcess.h | 8 -------- dragonflybsd/DragonFlyBSDProcessList.c | 7 ++++--- freebsd/FreeBSDProcess.c | 4 ---- freebsd/FreeBSDProcess.h | 11 ----------- freebsd/FreeBSDProcessList.c | 3 ++- linux/LinuxProcess.c | 16 ++++++---------- linux/LinuxProcess.h | 6 ------ linux/LinuxProcessList.c | 4 ++-- openbsd/OpenBSDProcess.c | 4 ---- openbsd/OpenBSDProcess.h | 10 ---------- openbsd/OpenBSDProcessList.c | 2 ++ solaris/SolarisProcess.c | 12 ------------ solaris/SolarisProcess.h | 8 -------- solaris/SolarisProcessList.c | 20 +++++++++++--------- unsupported/UnsupportedProcessList.c | 2 ++ 19 files changed, 49 insertions(+), 106 deletions(-) diff --git a/Process.h b/Process.h index 2a198441..f70ab571 100644 --- a/Process.h +++ b/Process.h @@ -110,6 +110,12 @@ typedef struct Process_ { /* Foreground group identifier of the controlling terminal */ int tpgid; + /* This is a kernel (helper) task */ + bool isKernelThread; + + /* This is a userland thread / LWP */ + bool isUserlandThread; + /* Controlling terminal identifier of the process */ unsigned long int tty_nr; @@ -260,7 +266,6 @@ typedef struct ProcessFieldData_ { void Process_writeField(const Process* this, RichString* str, ProcessField field); int Process_compare(const void* v1, const void* v2); void Process_delete(Object* cast); -bool Process_isThread(const Process* this); extern const ProcessFieldData Process_fields[LAST_PROCESSFIELD]; #define PROCESS_MAX_PID_DIGITS 19 extern int Process_pidDigits; @@ -290,6 +295,18 @@ static inline bool Process_isChildOf(const Process* this, pid_t pid) { return pid == Process_getParentPid(this); } +static inline bool Process_isKernelThread(const Process *this) { + return this->isKernelThread; +} + +static inline bool Process_isUserlandThread(const Process *this) { + return this->isUserlandThread; +} + +static inline bool Process_isThread(const Process *this) { + return Process_isUserlandThread(this) || Process_isKernelThread(this); +} + #define CMDLINE_HIGHLIGHT_FLAG_SEPARATOR 0x00000001 #define CMDLINE_HIGHLIGHT_FLAG_BASENAME 0x00000002 #define CMDLINE_HIGHLIGHT_FLAG_COMM 0x00000004 diff --git a/darwin/DarwinProcess.c b/darwin/DarwinProcess.c index 65f45ee1..e07d4e82 100644 --- a/darwin/DarwinProcess.c +++ b/darwin/DarwinProcess.c @@ -96,11 +96,6 @@ static int DarwinProcess_compareByKey(const Process* v1, const Process* v2, Proc } } -bool Process_isThread(const Process* this) { - (void) this; - return false; -} - static char* DarwinProcess_getCmdLine(const struct kinfo_proc* k, int* cmdlineBasenameEnd) { /* This function is from the old Mac version of htop. Originally from ps? */ int mib[3], argmax, nargs, c = 0; @@ -272,6 +267,8 @@ 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->isKernelThread = false; + proc->isUserlandThread = false; proc->st_uid = ps->kp_eproc.e_ucred.cr_uid; dp->translated = ps->kp_proc.p_flag & P_TRANSLATED; diff --git a/darwin/DarwinProcess.h b/darwin/DarwinProcess.h index 3fbcc792..f01efce1 100644 --- a/darwin/DarwinProcess.h +++ b/darwin/DarwinProcess.h @@ -29,8 +29,6 @@ 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); diff --git a/dragonflybsd/DragonFlyBSDProcess.c b/dragonflybsd/DragonFlyBSDProcess.c index 7322f091..aa91740d 100644 --- a/dragonflybsd/DragonFlyBSDProcess.c +++ b/dragonflybsd/DragonFlyBSDProcess.c @@ -94,16 +94,6 @@ static int DragonFlyBSDProcess_compareByKey(const Process* v1, const Process* v2 } } -bool Process_isThread(const Process* this) { - const DragonFlyBSDProcess* fp = (const DragonFlyBSDProcess*) this; - - if (fp->kernel == 1 ) { - return 1; - } else { - return (Process_isUserlandThread(this)); - } -} - const ProcessClass DragonFlyBSDProcess_class = { .super = { .extends = Class(Process), diff --git a/dragonflybsd/DragonFlyBSDProcess.h b/dragonflybsd/DragonFlyBSDProcess.h index 4b086af2..22cf9759 100644 --- a/dragonflybsd/DragonFlyBSDProcess.h +++ b/dragonflybsd/DragonFlyBSDProcess.h @@ -17,16 +17,10 @@ in the source distribution for its full text. typedef struct DragonFlyBSDProcess_ { Process super; - int kernel; int jid; char* jname; } DragonFlyBSDProcess; -#define Process_isKernelThread(_process) (_process->kernel == 1) - -//#define Process_isUserlandThread(_process) (_process->pid != _process->tgid) -#define Process_isUserlandThread(_process) (_process->nlwp > 1) - extern const ProcessClass DragonFlyBSDProcess_class; extern const ProcessFieldData Process_fields[LAST_PROCESSFIELD]; @@ -35,6 +29,4 @@ Process* DragonFlyBSDProcess_new(const Settings* settings); void Process_delete(Object* cast); -bool Process_isThread(const Process* this); - #endif diff --git a/dragonflybsd/DragonFlyBSDProcessList.c b/dragonflybsd/DragonFlyBSDProcessList.c index 5e5d5dc9..5c0306f8 100644 --- a/dragonflybsd/DragonFlyBSDProcessList.c +++ b/dragonflybsd/DragonFlyBSDProcessList.c @@ -390,12 +390,13 @@ void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate) { if (kproc->kp_ktaddr && kproc->kp_flags & P_SYSTEM) { // dfb kernel threads all have the same pid, so we misuse the kernel thread address to give them a unique identifier proc->pid = (pid_t)kproc->kp_ktaddr; - dfp->kernel = 1; + proc->isKernelThread = true; } else { proc->pid = kproc->kp_pid; // process ID - dfp->kernel = 0; + proc->isKernelThread = false; } - proc->ppid = kproc->kp_ppid; // parent process id + proc->isUserlandThread = kproc->kp_nthreads > 1; + proc->ppid = kproc->kp_ppid; // parent process id proc->tpgid = kproc->kp_tpgid; // tty process group id //proc->tgid = kproc->kp_lwp.kl_tid; // thread group id proc->tgid = kproc->kp_pid; // thread group id diff --git a/freebsd/FreeBSDProcess.c b/freebsd/FreeBSDProcess.c index 3a016562..2370b9f0 100644 --- a/freebsd/FreeBSDProcess.c +++ b/freebsd/FreeBSDProcess.c @@ -96,10 +96,6 @@ static int FreeBSDProcess_compareByKey(const Process* v1, const Process* v2, Pro } } -bool Process_isThread(const Process* this) { - return Process_isKernelThread(this) || Process_isUserlandThread(this); -} - const ProcessClass FreeBSDProcess_class = { .super = { .extends = Class(Process), diff --git a/freebsd/FreeBSDProcess.h b/freebsd/FreeBSDProcess.h index 5b6b4c66..0e0bd59f 100644 --- a/freebsd/FreeBSDProcess.h +++ b/freebsd/FreeBSDProcess.h @@ -16,19 +16,10 @@ in the source distribution for its full text. typedef struct FreeBSDProcess_ { Process super; - bool isKernelThread; int jid; char* jname; } FreeBSDProcess; -static inline bool Process_isKernelThread(const Process* this) { - return ((const FreeBSDProcess*)this)->isKernelThread; -} - -static inline bool Process_isUserlandThread(const Process* this) { - return this->pid != this->tgid; -} - extern const ProcessClass FreeBSDProcess_class; extern const ProcessFieldData Process_fields[LAST_PROCESSFIELD]; @@ -37,6 +28,4 @@ Process* FreeBSDProcess_new(const Settings* settings); void Process_delete(Object* cast); -bool Process_isThread(const Process* this); - #endif diff --git a/freebsd/FreeBSDProcessList.c b/freebsd/FreeBSDProcessList.c index 601072c8..8222bad4 100644 --- a/freebsd/FreeBSDProcessList.c +++ b/freebsd/FreeBSDProcessList.c @@ -456,7 +456,8 @@ void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate) { if (!preExisting) { fp->jid = kproc->ki_jid; proc->pid = kproc->ki_pid; - fp->isKernelThread = kproc->ki_pid != 0 && kproc->ki_pid != 1 && (kproc->ki_flag & P_SYSTEM); + proc->isKernelThread = kproc->ki_pid != 0 && kproc->ki_pid != 1 && (kproc->ki_flag & P_SYSTEM); + proc->isUserlandThread = false; proc->ppid = kproc->ki_ppid; proc->tpgid = kproc->ki_tpgid; proc->tgid = kproc->ki_pid; diff --git a/linux/LinuxProcess.c b/linux/LinuxProcess.c index 5563763c..bc6f09a8 100644 --- a/linux/LinuxProcess.c +++ b/linux/LinuxProcess.c @@ -685,7 +685,7 @@ static void LinuxProcess_writeField(const Process* this, RichString* str, Proces procComm = this->procComm; } else { attr = CRT_colors[PROCESS_SHADOW]; - procComm = Process_isKernelThread(lp) ? kthreadID : "N/A"; + procComm = Process_isKernelThread(this) ? kthreadID : "N/A"; } /* 15 being (TASK_COMM_LEN - 1) */ Process_printLeftAlignedField(str, attr, procComm, 15); @@ -700,7 +700,7 @@ static void LinuxProcess_writeField(const Process* this, RichString* str, Proces procExe = this->procExe + this->procExeBasenameOffset; } else { attr = CRT_colors[PROCESS_SHADOW]; - procExe = Process_isKernelThread(lp) ? kthreadID : "N/A"; + procExe = Process_isKernelThread(this) ? kthreadID : "N/A"; } Process_printLeftAlignedField(str, attr, procExe, 15); return; @@ -811,13 +811,13 @@ static int LinuxProcess_compareByKey(const Process* v1, const Process* v2, Proce case SECATTR: return SPACESHIP_NULLSTR(p1->secattr, p2->secattr); case PROC_COMM: { - const char *comm1 = v1->procComm ? v1->procComm : (Process_isKernelThread(p1) ? kthreadID : ""); - const char *comm2 = v2->procComm ? v2->procComm : (Process_isKernelThread(p2) ? kthreadID : ""); + const char *comm1 = v1->procComm ? v1->procComm : (Process_isKernelThread(v1) ? kthreadID : ""); + const char *comm2 = v2->procComm ? v2->procComm : (Process_isKernelThread(v2) ? kthreadID : ""); return strcmp(comm1, comm2); } case PROC_EXE: { - const char *exe1 = v1->procExe ? (v1->procExe + v1->procExeBasenameOffset) : (Process_isKernelThread(p1) ? kthreadID : ""); - const char *exe2 = v2->procExe ? (v2->procExe + v2->procExeBasenameOffset) : (Process_isKernelThread(p2) ? kthreadID : ""); + const char *exe1 = v1->procExe ? (v1->procExe + v1->procExeBasenameOffset) : (Process_isKernelThread(v1) ? kthreadID : ""); + const char *exe2 = v2->procExe ? (v2->procExe + v2->procExeBasenameOffset) : (Process_isKernelThread(v2) ? kthreadID : ""); return strcmp(exe1, exe2); } case CWD: @@ -827,10 +827,6 @@ static int LinuxProcess_compareByKey(const Process* v1, const Process* v2, Proce } } -bool Process_isThread(const Process* this) { - return (Process_isUserlandThread(this) || Process_isKernelThread(this)); -} - const ProcessClass LinuxProcess_class = { .super = { .extends = Class(Process), diff --git a/linux/LinuxProcess.h b/linux/LinuxProcess.h index 20963bcb..90ce7c50 100644 --- a/linux/LinuxProcess.h +++ b/linux/LinuxProcess.h @@ -32,8 +32,6 @@ in the source distribution for its full text. typedef struct LinuxProcess_ { Process super; - bool isKernelThread; - bool isUserlandThread; IOPriority ioPriority; unsigned long int cminflt; unsigned long int cmajflt; @@ -105,10 +103,6 @@ typedef struct LinuxProcess_ { char* cwd; } LinuxProcess; -#define Process_isKernelThread(_process) (((const LinuxProcess*)(_process))->isKernelThread) - -#define Process_isUserlandThread(_process) (((const LinuxProcess *)(_process))->isUserlandThread) - extern int pageSize; extern int pageSizeKB; diff --git a/linux/LinuxProcessList.c b/linux/LinuxProcessList.c index 66b648ea..020fc0a5 100644 --- a/linux/LinuxProcessList.c +++ b/linux/LinuxProcessList.c @@ -1015,7 +1015,7 @@ static bool LinuxProcessList_readCmdlineFile(Process* process, openat_arg_t proc if (process->state == 'Z') { process->cmdlineBasenameEnd = 0; } else { - ((LinuxProcess*)process)->isKernelThread = true; + process->isKernelThread = true; } return true; } @@ -1315,7 +1315,7 @@ static bool LinuxProcessList_recurseProcTree(LinuxProcessList* this, openat_arg_ LinuxProcess* lp = (LinuxProcess*) proc; proc->tgid = parent ? parent->pid : pid; - lp->isUserlandThread = proc->pid != proc->tgid; + proc->isUserlandThread = proc->pid != proc->tgid; #ifdef HAVE_OPENAT int procFd = openat(dirFd, entry->d_name, O_PATH | O_DIRECTORY | O_NOFOLLOW); diff --git a/openbsd/OpenBSDProcess.c b/openbsd/OpenBSDProcess.c index 030813c0..2825aa9d 100644 --- a/openbsd/OpenBSDProcess.c +++ b/openbsd/OpenBSDProcess.c @@ -234,7 +234,3 @@ const ProcessClass OpenBSDProcess_class = { .writeField = OpenBSDProcess_writeField, .compareByKey = OpenBSDProcess_compareByKey }; - -bool Process_isThread(const Process* this) { - return Process_isKernelThread(this) || Process_isUserlandThread(this); -} diff --git a/openbsd/OpenBSDProcess.h b/openbsd/OpenBSDProcess.h index 79f9b0fe..ce078a03 100644 --- a/openbsd/OpenBSDProcess.h +++ b/openbsd/OpenBSDProcess.h @@ -22,14 +22,6 @@ typedef struct OpenBSDProcess_ { uint64_t addr; } OpenBSDProcess; -static inline bool Process_isKernelThread(const Process* this) { - return this->pgrp == 0; -} - -static inline bool Process_isUserlandThread(const Process* this) { - return this->pid != this->tgid; -} - extern const ProcessClass OpenBSDProcess_class; extern const ProcessFieldData Process_fields[LAST_PROCESSFIELD]; @@ -38,6 +30,4 @@ Process* OpenBSDProcess_new(const Settings* settings); void Process_delete(Object* cast); -bool Process_isThread(const Process* this); - #endif diff --git a/openbsd/OpenBSDProcessList.c b/openbsd/OpenBSDProcessList.c index 62fcab90..b786a0b9 100644 --- a/openbsd/OpenBSDProcessList.c +++ b/openbsd/OpenBSDProcessList.c @@ -252,6 +252,8 @@ static void OpenBSDProcessList_scanProcs(OpenBSDProcessList* this) { proc->tgid = kproc->p_pid; proc->session = kproc->p_sid; proc->pgrp = kproc->p__pgid; + proc->isKernelThread = proc->pgrp == 0; + proc->isUserlandThread = kproc->p_tid != -1; proc->st_uid = kproc->p_uid; proc->starttime_ctime = kproc->p_ustart_sec; Process_fillStarttimeBuffer(proc); diff --git a/solaris/SolarisProcess.c b/solaris/SolarisProcess.c index 7b82f90f..688d98ca 100644 --- a/solaris/SolarisProcess.c +++ b/solaris/SolarisProcess.c @@ -121,18 +121,6 @@ static int SolarisProcess_compareByKey(const Process* v1, const Process* v2, Pro } } -bool Process_isThread(const Process* this) { - const SolarisProcess* fp = (const SolarisProcess*) this; - - if (fp->kernel == 1 ) { - return 1; - } else if (fp->is_lwp) { - return 1; - } else { - return 0; - } -} - const ProcessClass SolarisProcess_class = { .super = { .extends = Class(Process), diff --git a/solaris/SolarisProcess.h b/solaris/SolarisProcess.h index 07b889c0..0fd458dc 100644 --- a/solaris/SolarisProcess.h +++ b/solaris/SolarisProcess.h @@ -26,24 +26,18 @@ in the source distribution for its full text. typedef struct SolarisProcess_ { Process super; - int kernel; zoneid_t zoneid; char* zname; taskid_t taskid; projid_t projid; poolid_t poolid; ctid_t contid; - bool is_lwp; pid_t realpid; pid_t realppid; pid_t realtgid; pid_t lwpid; } SolarisProcess; -#define Process_isKernelThread(_process) (_process->kernel == 1) - -#define Process_isUserlandThread(_process) (_process->pid != _process->tgid) - extern const ProcessClass SolarisProcess_class; extern const ProcessFieldData Process_fields[LAST_PROCESSFIELD]; @@ -52,6 +46,4 @@ Process* SolarisProcess_new(const Settings* settings); void Process_delete(Object* cast); -bool Process_isThread(const Process* this); - #endif diff --git a/solaris/SolarisProcessList.c b/solaris/SolarisProcessList.c index fd1d5a2f..93561fa3 100644 --- a/solaris/SolarisProcessList.c +++ b/solaris/SolarisProcessList.c @@ -322,6 +322,7 @@ static int SolarisProcessList_walkproc(psinfo_t* _psinfo, lwpsinfo_t* _lwpsinfo, } else { getpid = lwpid; } + Process* proc = ProcessList_getProcess(pl, getpid, &preExisting, SolarisProcess_new); SolarisProcess* sproc = (SolarisProcess*) proc; @@ -376,18 +377,18 @@ static int SolarisProcessList_walkproc(psinfo_t* _psinfo, lwpsinfo_t* _lwpsinfo, proc->percent_cpu = ((uint16_t)_psinfo->pr_pctcpu / (double)32768) * (double)100.0; proc->time = _psinfo->pr_time.tv_sec; if (!preExisting) { // Tasks done only for NEW processes - sproc->is_lwp = false; + proc->isUserlandThread = false; proc->starttime_ctime = _psinfo->pr_start.tv_sec; } // Update proc and thread counts based on settings - if (sproc->kernel && !pl->settings->hideKernelThreads) { + if (proc->isKernelThread && !pl->settings->hideKernelThreads) { pl->kernelThreads += proc->nlwp; pl->totalTasks += proc->nlwp + 1; if (proc->state == 'O') { pl->runningTasks++; } - } else if (!sproc->kernel) { + } else if (!proc->isKernelThread) { if (proc->state == 'O') { pl->runningTasks++; } @@ -398,12 +399,12 @@ static int SolarisProcessList_walkproc(psinfo_t* _psinfo, lwpsinfo_t* _lwpsinfo, pl->totalTasks += proc->nlwp + 1; } } - proc->show = !(pl->settings->hideKernelThreads && sproc->kernel); + proc->show = !(pl->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; proc->time = _lwpsinfo->pr_time.tv_sec; if (!preExisting) { // Tasks done only for NEW LWPs - sproc->is_lwp = true; + proc->isUserlandThread = true; proc->cmdlineBasenameEnd = -1; proc->ppid = _psinfo->pr_pid * 1024; proc->tgid = _psinfo->pr_pid * 1024; @@ -413,10 +414,10 @@ static int SolarisProcessList_walkproc(psinfo_t* _psinfo, lwpsinfo_t* _lwpsinfo, } // Top-level process only gets this for the representative LWP - if (sproc->kernel && !pl->settings->hideKernelThreads) { + if (proc->isKernelThread && !pl->settings->hideKernelThreads) { proc->show = true; } - if (!sproc->kernel && !pl->settings->hideUserlandThreads) { + if (!proc->isKernelThread && !pl->settings->hideUserlandThreads) { proc->show = true; } } // Top-level LWP or subordinate LWP @@ -425,10 +426,11 @@ static int SolarisProcessList_walkproc(psinfo_t* _psinfo, lwpsinfo_t* _lwpsinfo, if (!preExisting) { if ((sproc->realppid <= 0) && !(sproc->realpid <= 1)) { - sproc->kernel = true; + proc->isKernelThread = true; } else { - sproc->kernel = false; + proc->isKernelThread = false; } + Process_fillStarttimeBuffer(proc); ProcessList_add(pl, proc); } diff --git a/unsupported/UnsupportedProcessList.c b/unsupported/UnsupportedProcessList.c index 7f94e121..cd7dbcd1 100644 --- a/unsupported/UnsupportedProcessList.c +++ b/unsupported/UnsupportedProcessList.c @@ -50,6 +50,8 @@ void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate) { proc->updated = true; proc->state = 'R'; + proc->isKernelThread = false; + proc->isUserlandThread = false; proc->show = true; /* Reflected in proc->settings-> "hideXXX" really */ proc->pgrp = 0; proc->session = 0;