From 75e9f9a8d92cda6ae8b161f1bf662597ac67c0f2 Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Thu, 10 Dec 2020 11:57:48 +1100 Subject: [PATCH] Cull the definitions of pageSize and pageSizeKB from CRT.c By storing the per-process m_resident and m_virt values in the form htop wants to display them in (KB, not pages), we no longer need to have definitions of pageSize and pageSizeKB in the common CRT code. These variables were never really CRT (i.e. display) related in the first place. It turns out the darwin platform code doesn't need to use these at all (the process values are extracted from the kernel in bytes not pages) and the other platforms can each use their own local pagesize variables, in more appropriate locations. Some platforms were actually already doing this, so this change is removing duplication of logic and variables there. --- CRT.c | 8 ------ CRT.h | 3 --- Process.c | 4 +-- darwin/DarwinProcess.c | 4 +-- dragonflybsd/DragonFlyBSDProcessList.c | 15 +++++------ freebsd/FreeBSDProcessList.c | 15 +++++------ linux/LinuxProcess.c | 12 +++++---- linux/LinuxProcess.h | 4 +++ linux/LinuxProcessList.c | 13 +++++++-- openbsd/OpenBSDProcessList.c | 18 ++++++++----- solaris/SolarisProcessList.c | 37 +++++++++++++++----------- 11 files changed, 72 insertions(+), 61 deletions(-) diff --git a/CRT.c b/CRT.c index 68f64054..f932bb2b 100644 --- a/CRT.c +++ b/CRT.c @@ -608,9 +608,6 @@ const char* CRT_termType; int CRT_colorScheme = 0; -long CRT_pageSize = -1; -long CRT_pageSizeKB = -1; - ATTR_NORETURN static void CRT_handleSIGTERM(int sgn) { (void) sgn; @@ -746,11 +743,6 @@ void CRT_init(const int* delay, int colorScheme, bool allowUnicode) { mousemask(BUTTON1_RELEASED, NULL); #endif - CRT_pageSize = sysconf(_SC_PAGESIZE); - if (CRT_pageSize == -1) - CRT_fatalError("Fatal error: Can not get PAGE_SIZE by sysconf(_SC_PAGESIZE)"); - CRT_pageSizeKB = CRT_pageSize / 1024; - CRT_degreeSign = initDegreeSign(); } diff --git a/CRT.h b/CRT.h index ec3fdafe..c62d4902 100644 --- a/CRT.h +++ b/CRT.h @@ -156,9 +156,6 @@ extern const char* CRT_termType; extern int CRT_colorScheme; -extern long CRT_pageSize; -extern long CRT_pageSizeKB; - #ifdef HAVE_SETUID_ENABLED void CRT_dropPrivileges(void); diff --git a/Process.c b/Process.c index 544358ee..0a954d49 100644 --- a/Process.c +++ b/Process.c @@ -328,8 +328,8 @@ void Process_writeField(const Process* this, RichString* str, ProcessField field } case MAJFLT: Process_colorNumber(str, this->majflt, coloring); return; case MINFLT: Process_colorNumber(str, this->minflt, coloring); return; - case M_RESIDENT: Process_humanNumber(str, this->m_resident * CRT_pageSizeKB, coloring); return; - case M_VIRT: Process_humanNumber(str, this->m_virt * CRT_pageSizeKB, coloring); return; + case M_RESIDENT: Process_humanNumber(str, this->m_resident, coloring); return; + case M_VIRT: Process_humanNumber(str, this->m_virt, coloring); return; case NICE: { xSnprintf(buffer, n, "%3ld ", this->nice); attr = this->nice < 0 ? CRT_colors[PROCESS_HIGH_PRIORITY] diff --git a/darwin/DarwinProcess.c b/darwin/DarwinProcess.c index f3c34254..904df0bd 100644 --- a/darwin/DarwinProcess.c +++ b/darwin/DarwinProcess.c @@ -258,8 +258,8 @@ void DarwinProcess_setFromLibprocPidinfo(DarwinProcess* proc, DarwinProcessList* proc->super.time = (pti.pti_total_system + pti.pti_total_user) / 10000000; proc->super.nlwp = pti.pti_threadnum; - proc->super.m_virt = pti.pti_virtual_size / CRT_pageSize; - proc->super.m_resident = pti.pti_resident_size / CRT_pageSize; + proc->super.m_virt = pti.pti_virtual_size / ONE_K; + proc->super.m_resident = pti.pti_resident_size / ONE_K; proc->super.majflt = pti.pti_faults; proc->super.percent_mem = (double)pti.pti_resident_size * 100.0 / (double)dpl->host_info.max_mem; diff --git a/dragonflybsd/DragonFlyBSDProcessList.c b/dragonflybsd/DragonFlyBSDProcessList.c index 940ec03d..fd19df30 100644 --- a/dragonflybsd/DragonFlyBSDProcessList.c +++ b/dragonflybsd/DragonFlyBSDProcessList.c @@ -55,12 +55,9 @@ ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidMatchList, ui len = 2; sysctlnametomib("hw.physmem", MIB_hw_physmem, &len); len = sizeof(pageSize); - if (sysctlbyname("vm.stats.vm.v_page_size", &pageSize, &len, NULL, 0) == -1) { - pageSize = CRT_pageSize; - pageSizeKb = CRT_pageSizeKB; - } else { - pageSizeKb = pageSize / ONE_K; - } + if (sysctlbyname("vm.stats.vm.v_page_size", &pageSize, &len, NULL, 0) == -1) + CRT_fatalError("Cannot get pagesize by sysctl"); + pageSizeKb = pageSize / ONE_K; // usable page count vm.stats.vm.v_page_count // actually usable memory : vm.stats.vm.v_page_count * vm.stats.vm.v_page_size @@ -433,13 +430,13 @@ void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate) { } } - proc->m_virt = kproc->kp_vm_map_size / pageSize; - proc->m_resident = kproc->kp_vm_rssize; + proc->m_virt = kproc->kp_vm_map_size / ONE_K; + proc->m_resident = kproc->kp_vm_rssize * pageSizeKB; proc->nlwp = kproc->kp_nthreads; // number of lwp thread proc->time = (kproc->kp_swtime + 5000) / 10000; proc->percent_cpu = 100.0 * ((double)kproc->kp_lwp.kl_pctcpu / (double)kernelFScale); - proc->percent_mem = 100.0 * (proc->m_resident * pageSizeKb) / (double)(super->totalMem); + proc->percent_mem = 100.0 * proc->m_resident / (double)(super->totalMem); if (proc->percent_cpu > 0.1) { // system idle process should own all CPU time left regardless of CPU count diff --git a/freebsd/FreeBSDProcessList.c b/freebsd/FreeBSDProcessList.c index 9aaab5dd..d8fadb33 100644 --- a/freebsd/FreeBSDProcessList.c +++ b/freebsd/FreeBSDProcessList.c @@ -72,12 +72,9 @@ ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidMatchList, ui len = 2; sysctlnametomib("hw.physmem", MIB_hw_physmem, &len); len = sizeof(pageSize); - if (sysctlbyname("vm.stats.vm.v_page_size", &pageSize, &len, NULL, 0) == -1) { - pageSize = CRT_pageSize; - pageSizeKb = CRT_pageSize; - } else { - pageSizeKb = pageSize / ONE_K; - } + if (sysctlbyname("vm.stats.vm.v_page_size", &pageSize, &len, NULL, 0) == -1) + CRT_fatalError("Cannot get pagesize by sysctl"); + pageSizeKb = pageSize / ONE_K; // usable page count vm.stats.vm.v_page_count // actually usable memory : vm.stats.vm.v_page_count * vm.stats.vm.v_page_size @@ -526,13 +523,13 @@ void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate) { } // from FreeBSD source /src/usr.bin/top/machine.c - proc->m_virt = kproc->ki_size / pageSize; - proc->m_resident = kproc->ki_rssize; + proc->m_virt = kproc->ki_size / ONE_K; + proc->m_resident = kproc->ki_rssize * pageSizeKb; proc->nlwp = kproc->ki_numthreads; proc->time = (kproc->ki_runtime + 5000) / 10000; proc->percent_cpu = 100.0 * ((double)kproc->ki_pctcpu / (double)kernelFScale); - proc->percent_mem = 100.0 * (proc->m_resident * pageSizeKb) / (double)(super->totalMem); + proc->percent_mem = 100.0 * proc->m_resident / (double)(super->totalMem); /* * TODO diff --git a/linux/LinuxProcess.c b/linux/LinuxProcess.c index ef155af8..44c4b2d9 100644 --- a/linux/LinuxProcess.c +++ b/linux/LinuxProcess.c @@ -25,6 +25,8 @@ in the source distribution for its full text. /* semi-global */ long long btime; +int pageSize; +int pageSizeKB; /* Used to identify kernel threads in Comm and Exe columns */ static const char *const kthreadID = "KTHREAD"; @@ -632,19 +634,19 @@ static void LinuxProcess_writeField(const Process* this, RichString* str, Proces } case CMINFLT: Process_colorNumber(str, lp->cminflt, coloring); return; case CMAJFLT: Process_colorNumber(str, lp->cmajflt, coloring); return; - case M_DRS: Process_humanNumber(str, lp->m_drs * CRT_pageSizeKB, coloring); return; - case M_DT: Process_humanNumber(str, lp->m_dt * CRT_pageSizeKB, coloring); return; + case M_DRS: Process_humanNumber(str, lp->m_drs * pageSizeKB, coloring); return; + case M_DT: Process_humanNumber(str, lp->m_dt * pageSizeKB, coloring); return; case M_LRS: if (lp->m_lrs) { - Process_humanNumber(str, lp->m_lrs * CRT_pageSizeKB, coloring); + Process_humanNumber(str, lp->m_lrs * pageSizeKB, coloring); return; } attr = CRT_colors[PROCESS_SHADOW]; xSnprintf(buffer, n, " N/A "); break; - case M_TRS: Process_humanNumber(str, lp->m_trs * CRT_pageSizeKB, coloring); return; - case M_SHARE: Process_humanNumber(str, lp->m_share * CRT_pageSizeKB, coloring); return; + case M_TRS: Process_humanNumber(str, lp->m_trs * pageSizeKB, coloring); return; + case M_SHARE: Process_humanNumber(str, lp->m_share * pageSizeKB, coloring); return; case M_PSS: Process_humanNumber(str, lp->m_pss, coloring); return; case M_SWAP: Process_humanNumber(str, lp->m_swap, coloring); return; case M_PSSWP: Process_humanNumber(str, lp->m_psswp, coloring); return; diff --git a/linux/LinuxProcess.h b/linux/LinuxProcess.h index ad396fb2..3c1e7e75 100644 --- a/linux/LinuxProcess.h +++ b/linux/LinuxProcess.h @@ -193,6 +193,10 @@ static inline bool Process_isUserlandThread(const Process* this) { extern long long btime; +extern int pageSize; + +extern int pageSizeKB; + extern ProcessFieldData Process_fields[]; extern ProcessPidColumn Process_pidColumns[]; diff --git a/linux/LinuxProcessList.c b/linux/LinuxProcessList.c index b9ba247f..e228220f 100644 --- a/linux/LinuxProcessList.c +++ b/linux/LinuxProcessList.c @@ -202,6 +202,12 @@ ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidMatchList, ui LinuxProcessList_initNetlinkSocket(this); #endif + // Initialize page size + pageSize = sysconf(_SC_PAGESIZE); + if (pageSize == -1) + CRT_fatalError("Cannot get pagesize by sysconf(_SC_PAGESIZE)"); + pageSizeKB = pageSize / ONE_K; + // Check for /proc/*/smaps_rollup availability (improves smaps parsing speed, Linux 4.14+) FILE* file = fopen(PROCDIR "/self/smaps_rollup", "r"); if (file != NULL) { @@ -573,7 +579,7 @@ static uint64_t LinuxProcessList_calcLibSize(openat_arg_t procFd) { Hashtable_delete(ht); - return total_size / CRT_pageSize; + return total_size / pageSize; } static bool LinuxProcessList_readStatmFile(LinuxProcess* process, openat_arg_t procFd, bool performLookup, unsigned long long now) { @@ -593,6 +599,9 @@ static bool LinuxProcessList_readStatmFile(LinuxProcess* process, openat_arg_t p fclose(statmfile); if (r == 7) { + process->super.m_virt *= pageSizeKB; + process->super.m_resident *= pageSizeKB; + if (tmp_m_lrs) { process->m_lrs = tmp_m_lrs; } else if (performLookup) { @@ -1365,7 +1374,7 @@ static bool LinuxProcessList_recurseProcTree(LinuxProcessList* this, openat_arg_ /* period might be 0 after system sleep */ float percent_cpu = (period < 1e-6) ? 0.0f : ((lp->utime + lp->stime - lasttimes) / period * 100.0); proc->percent_cpu = CLAMP(percent_cpu, 0.0f, cpus * 100.0f); - proc->percent_mem = (proc->m_resident * CRT_pageSizeKB) / (double)(pl->totalMem) * 100.0; + proc->percent_mem = proc->m_resident / (double)(pl->totalMem) * 100.0; if (!preExisting) { diff --git a/openbsd/OpenBSDProcessList.c b/openbsd/OpenBSDProcessList.c index 5412030f..3f4abb9f 100644 --- a/openbsd/OpenBSDProcessList.c +++ b/openbsd/OpenBSDProcessList.c @@ -34,6 +34,8 @@ in the source distribution for its full text. static long fscale; +static int pageSize; +static int pageSizeKB; ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidMatchList, uid_t userId) { const int mib[] = { CTL_HW, HW_NCPU }; @@ -58,6 +60,10 @@ ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidMatchList, ui err(1, "fscale sysctl call failed"); } + if ((pageSize = sysconf(_SC_PAGESIZE)) == -1) + err(1, "pagesize sysconf call failed"); + pageSizeKB = pageSize / ONE_K; + for (int i = 0; i <= pl->cpuCount; i++) { CPUData* d = opl->cpus + i; d->totalTime = 1; @@ -94,8 +100,8 @@ static void OpenBSDProcessList_scanMemoryInfo(ProcessList* pl) { err(1, "uvmexp sysctl call failed"); } - pl->totalMem = uvmexp.npages * CRT_pageSizeKB; - pl->usedMem = (uvmexp.npages - uvmexp.free - uvmexp.paging) * CRT_pageSizeKB; + pl->totalMem = uvmexp.npages * pageSizeKB; + pl->usedMem = (uvmexp.npages - uvmexp.free - uvmexp.paging) * pageSizeKB; // Taken from OpenBSD systat/iostat.c, top/machine.c and uvm_sysctl(9) const int bcache_mib[] = { CTL_VFS, VFS_GENERIC, VFS_BCACHESTAT }; @@ -106,7 +112,7 @@ static void OpenBSDProcessList_scanMemoryInfo(ProcessList* pl) { err(1, "cannot get vfs.bcachestat"); } - pl->cachedMem = bcstats.numbufpages * CRT_pageSizeKB; + pl->cachedMem = bcstats.numbufpages * pageSizeKB; /* * Copyright (c) 1994 Thorsten Lockert @@ -222,9 +228,9 @@ static void OpenBSDProcessList_scanProcs(OpenBSDProcessList* this) { } } - proc->m_virt = kproc->p_vm_dsize; - proc->m_resident = kproc->p_vm_rssize; - proc->percent_mem = (proc->m_resident * CRT_pageSizeKB) / (double)(this->super.totalMem) * 100.0; + proc->m_virt = kproc->p_vm_dsize * pageSizeKB; + proc->m_resident = kproc->p_vm_rssize * pageSizeKB; + proc->percent_mem = proc->m_resident / (double)(this->super.totalMem) * 100.0; proc->percent_cpu = CLAMP(getpcpu(kproc), 0.0, this->super.cpuCount * 100.0); //proc->nlwp = kproc->p_numthreads; proc->nice = kproc->p_nice - 20; diff --git a/solaris/SolarisProcessList.c b/solaris/SolarisProcessList.c index 4249fa60..793b1b3b 100644 --- a/solaris/SolarisProcessList.c +++ b/solaris/SolarisProcessList.c @@ -25,9 +25,11 @@ in the source distribution for its full text. #include "CRT.h" - #define MAXCMDLINE 255 +static int pageSize; +static int pageSizeKB; + char* SolarisProcessList_readZoneName(kstat_ctl_t* kd, SolarisProcess* sproc) { char* zname; @@ -50,13 +52,18 @@ ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidMatchList, ui spl->kd = kstat_open(); - pl->cpuCount = sysconf(_SC_NPROCESSORS_ONLN); + pageSize = sysconf(_SC_PAGESIZE); + if (pageSize == -1) + CRT_fatalError("Cannot get pagesize by sysconf(_SC_PAGESIZE)"); + pageSizeKB = pageSize / 1024; - if (pl->cpuCount == 1 ) { + pl->cpuCount = sysconf(_SC_NPROCESSORS_ONLN); + if (pl->cpuCount == -1) + CRT_fatalError("Cannot get CPU count by sysconf(_SC_NPROCESSORS_ONLN)"); + else if (pl->cpuCount == 1) spl->cpus = xRealloc(spl->cpus, sizeof(CPUData)); - } else { + else spl->cpus = xRealloc(spl->cpus, (pl->cpuCount + 1) * sizeof(CPUData)); - } return pl; } @@ -169,9 +176,9 @@ static inline void SolarisProcessList_scanMemoryInfo(ProcessList* pl) { freemem_pgs = kstat_data_lookup(meminfo, "freemem"); pages = kstat_data_lookup(meminfo, "pagestotal"); - pl->totalMem = totalmem_pgs->value.ui64 * CRT_pageSizeKB; - if (pl->totalMem > freemem_pgs->value.ui64 * CRT_pageSizeKB) { - pl->usedMem = pl->totalMem - freemem_pgs->value.ui64 * CRT_pageSizeKB; + pl->totalMem = totalmem_pgs->value.ui64 * pageSizeKB; + if (pl->totalMem > freemem_pgs->value.ui64 * pageSizeKB) { + pl->usedMem = pl->totalMem - freemem_pgs->value.ui64 * pageSizeKB; } else { pl->usedMem = 0; // This can happen in non-global zone (in theory) } @@ -179,13 +186,13 @@ static inline void SolarisProcessList_scanMemoryInfo(ProcessList* pl) { pl->cachedMem = 0; // Not really "buffers" but the best Solaris analogue that I can find to // "memory in use but not by programs or the kernel itself" - pl->buffersMem = (totalmem_pgs->value.ui64 - pages->value.ui64) * CRT_pageSizeKB; + pl->buffersMem = (totalmem_pgs->value.ui64 - pages->value.ui64) * pageSizeKB; } else { // Fall back to basic sysconf if kstat isn't working - pl->totalMem = sysconf(_SC_PHYS_PAGES) * CRT_pageSize; + pl->totalMem = sysconf(_SC_PHYS_PAGES) * pageSize; pl->buffersMem = 0; pl->cachedMem = 0; - pl->usedMem = pl->totalMem - (sysconf(_SC_AVPHYS_PAGES) * CRT_pageSize); + pl->usedMem = pl->totalMem - (sysconf(_SC_AVPHYS_PAGES) * pageSize); } // Part 2 - swap @@ -215,8 +222,8 @@ static inline void SolarisProcessList_scanMemoryInfo(ProcessList* pl) { } free(spathbase); free(sl); - pl->totalSwap = totalswap * CRT_pageSizeKB; - pl->usedSwap = pl->totalSwap - (totalfree * CRT_pageSizeKB); + pl->totalSwap = totalswap * pageSizeKB; + pl->usedSwap = pl->totalSwap - (totalfree * pageSizeKB); } static inline void SolarisProcessList_scanZfsArcstats(ProcessList* pl) { @@ -323,8 +330,8 @@ int SolarisProcessList_walkproc(psinfo_t* _psinfo, lwpsinfo_t* _lwpsinfo, void* proc->pgrp = _psinfo->pr_pgid; proc->nlwp = _psinfo->pr_nlwp; proc->tty_nr = _psinfo->pr_ttydev; - proc->m_resident = _psinfo->pr_rssize / CRT_pageSizeKB; - proc->m_virt = _psinfo->pr_size / CRT_pageSizeKB; + proc->m_resident = _psinfo->pr_rssize; // KB + proc->m_virt = _psinfo->pr_size; // KB if (!preExisting) { sproc->realpid = _psinfo->pr_pid;