summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Göttsche <cgzones@googlemail.com>2023-04-17 19:04:04 +0200
committercgzones <cgzones@googlemail.com>2024-04-06 19:42:28 +0200
commit48181bc237d2b3118b6fb06b82e427082a92e0e7 (patch)
treee745b4138715a958b5efd817530dc3b92da8d69e
parentb4d5b5cea98f557a856c89500dc169f511a2b817 (diff)
Linux: update gathering information regarding threads
Document for each block gathering information about a task whether the information is shared for the whole process or specific to a single userland thread. Also avoid system calls for process-shared information and reuse the information from the main task.
-rw-r--r--Scheduling.c3
-rw-r--r--linux/LibNl.c3
-rw-r--r--linux/LinuxProcess.c3
-rw-r--r--linux/LinuxProcessTable.c186
4 files changed, 156 insertions, 39 deletions
diff --git a/Scheduling.c b/Scheduling.c
index d5c4b8a6..406caf7d 100644
--- a/Scheduling.c
+++ b/Scheduling.c
@@ -156,6 +156,9 @@ const char* Scheduling_formatPolicy(int policy) {
}
}
+/*
+ * Gather scheduling policy (thread-specific data)
+ */
void Scheduling_readProcessPolicy(Process* proc) {
proc->scheduling_policy = sched_getscheduler(Process_getPid(proc));
}
diff --git a/linux/LibNl.c b/linux/LibNl.c
index 72465f22..a256ede2 100644
--- a/linux/LibNl.c
+++ b/linux/LibNl.c
@@ -193,6 +193,9 @@ static int handleNetlinkMsg(struct nl_msg* nlmsg, void* linuxProcess) {
return NL_OK;
}
+/*
+ * Gather delay-accounting information (thread-specific data)
+ */
void LibNl_readDelayAcctData(LinuxProcessTable* this, LinuxProcess* process) {
struct nl_msg* msg;
diff --git a/linux/LinuxProcess.c b/linux/LinuxProcess.c
index 5ba305ec..b97a9ad7 100644
--- a/linux/LinuxProcess.c
+++ b/linux/LinuxProcess.c
@@ -154,6 +154,9 @@ static int LinuxProcess_effectiveIOPriority(const LinuxProcess* this) {
#define SYS_ioprio_set __NR_ioprio_set
#endif
+/*
+ * Gather I/O scheduling class and priority (thread-specific data)
+ */
IOPriority LinuxProcess_updateIOPriority(Process* p) {
IOPriority ioprio = 0;
// Other OSes masquerading as Linux (NetBSD?) don't have this syscall
diff --git a/linux/LinuxProcessTable.c b/linux/LinuxProcessTable.c
index 57f93227..032128c7 100644
--- a/linux/LinuxProcessTable.c
+++ b/linux/LinuxProcessTable.c
@@ -231,6 +231,9 @@ static inline ProcessState LinuxProcessTable_getProcessState(char state) {
}
}
+/*
+ * Read /proc/<pid>/stat (thread-specific data)
+ */
static bool LinuxProcessTable_readStatFile(LinuxProcess* lp, openat_arg_t procFd, const LinuxMachine* lhost, bool scanMainThread, char* command, size_t commLen) {
Process* process = &lp->super;
@@ -359,6 +362,9 @@ static bool LinuxProcessTable_readStatFile(LinuxProcess* lp, openat_arg_t procFd
return true;
}
+/*
+ * Read /proc/<pid>/status (thread-specific data)
+ */
static bool LinuxProcessTable_readStatusFile(Process* process, openat_arg_t procFd) {
LinuxProcess* lp = (LinuxProcess*) process;
@@ -434,7 +440,16 @@ static bool LinuxProcessTable_readStatusFile(Process* process, openat_arg_t proc
return true;
}
-static bool LinuxProcessTable_updateUser(const Machine* host, Process* process, openat_arg_t procFd) {
+/*
+ * Gather user of task (process-shared data)
+ */
+static bool LinuxProcessTable_updateUser(const Machine* host, Process* process, openat_arg_t procFd, const LinuxProcess* mainTask) {
+ if (mainTask) {
+ process->st_uid = mainTask->super.st_uid;
+ process->user = mainTask->super.user;
+ return true;
+ }
+
struct stat sstat;
#ifdef HAVE_OPENAT
int statok = fstat(procFd, &sstat);
@@ -452,6 +467,9 @@ static bool LinuxProcessTable_updateUser(const Machine* host, Process* process,
return true;
}
+/*
+ * Read /proc/<pid>/io (thread-specific data)
+ */
static void LinuxProcessTable_readIoFile(LinuxProcess* lp, openat_arg_t procFd, bool scanMainThread) {
Process* process = &lp->super;
const Machine* host = process->super.host;
@@ -539,6 +557,9 @@ static void LinuxProcessTable_calcLibSize_helper(ATTR_UNUSED ht_key_t key, void*
*d += v->size;
}
+/*
+ * Read /proc/<pid>/maps (process-shared data)
+ */
static void LinuxProcessTable_readMaps(LinuxProcess* process, openat_arg_t procFd, const LinuxMachine* host, bool calcSize, bool checkDeletedLib) {
Process* proc = (Process*)process;
@@ -651,7 +672,16 @@ static void LinuxProcessTable_readMaps(LinuxProcess* process, openat_arg_t procF
}
}
-static bool LinuxProcessTable_readStatmFile(LinuxProcess* process, openat_arg_t procFd, const LinuxMachine* host) {
+/*
+ * Read /proc/<pid>/statm (process-shared data)
+ */
+static bool LinuxProcessTable_readStatmFile(LinuxProcess* process, openat_arg_t procFd, const LinuxMachine* host, const LinuxProcess* mainTask) {
+ if (mainTask) {
+ process->super.m_virt = mainTask->super.m_virt;
+ process->super.m_resident = mainTask->super.m_resident;
+ return true;
+ }
+
char statmdata[128] = {0};
if (xReadfileat(procFd, "statm", statmdata, sizeof(statmdata)) < 1) {
@@ -679,6 +709,9 @@ static bool LinuxProcessTable_readStatmFile(LinuxProcess* process, openat_arg_t
return r == 7;
}
+/*
+ * Read /proc/<pid>/smaps (process-shared data)
+ */
static bool LinuxProcessTable_readSmapsFile(LinuxProcess* process, openat_arg_t procFd, bool haveSmapsRollup) {
//http://elixir.free-electrons.com/linux/v4.10/source/fs/proc/task_mmu.c#L719
//kernel will return data in chunks of size PAGE_SIZE or less.
@@ -805,8 +838,11 @@ static void LinuxProcessTable_readOpenVZData(LinuxProcess* process, openat_arg_t
}
}
-#endif
+#endif /* HAVE_OPENVZ */
+/*
+ * Read /proc/<pid>/cgroup (thread-specific data)
+ */
static void LinuxProcessTable_readCGroupFile(LinuxProcess* process, openat_arg_t procFd) {
FILE* file = fopenat(procFd, "cgroup", "r");
if (!file) {
@@ -900,7 +936,15 @@ static void LinuxProcessTable_readCGroupFile(LinuxProcess* process, openat_arg_t
}
}
-static void LinuxProcessTable_readOomData(LinuxProcess* process, openat_arg_t procFd) {
+/*
+ * Read /proc/<pid>/oom_score (process-shared data)
+ */
+static void LinuxProcessTable_readOomData(LinuxProcess* process, openat_arg_t procFd, const LinuxProcess* mainTask) {
+ if (mainTask) {
+ process->oom = mainTask->oom;
+ return;
+ }
+
char buffer[PROC_LINE_LENGTH + 1] = {0};
ssize_t oomRead = xReadfileat(procFd, "oom_score", buffer, sizeof(buffer));
@@ -921,7 +965,15 @@ static void LinuxProcessTable_readOomData(LinuxProcess* process, openat_arg_t pr
process->oom = oom;
}
-static void LinuxProcessTable_readAutogroup(LinuxProcess* process, openat_arg_t procFd) {
+/*
+ * Read /proc/<pid>/autogroup (process-shared data)
+ */
+static void LinuxProcessTable_readAutogroup(LinuxProcess* process, openat_arg_t procFd, const LinuxProcess* mainTask) {
+ if (mainTask) {
+ process->autogroup_id = mainTask->autogroup_id;
+ return;
+ }
+
process->autogroup_id = -1;
char autogroup[64]; // space for two numeric values and fixed length strings
@@ -938,7 +990,21 @@ static void LinuxProcessTable_readAutogroup(LinuxProcess* process, openat_arg_t
}
}
-static void LinuxProcessTable_readSecattrData(LinuxProcess* process, openat_arg_t procFd) {
+/*
+ * Read /proc/<pid>/attr/current (process-shared data)
+ */
+static void LinuxProcessTable_readSecattrData(LinuxProcess* process, openat_arg_t procFd, const LinuxProcess* mainTask) {
+ if (mainTask) {
+ const char* mainSecAttr = mainTask->secattr;
+ if (mainSecAttr) {
+ free_and_xStrdup(&process->secattr, mainSecAttr);
+ } else {
+ free(process->secattr);
+ process->secattr = NULL;
+ }
+ return;
+ }
+
char buffer[PROC_LINE_LENGTH + 1] = {0};
ssize_t attrdata = xReadfileat(procFd, "attr/current", buffer, sizeof(buffer));
@@ -958,7 +1024,21 @@ static void LinuxProcessTable_readSecattrData(LinuxProcess* process, openat_arg_
free_and_xStrdup(&process->secattr, buffer);
}
-static void LinuxProcessTable_readCwd(LinuxProcess* process, openat_arg_t procFd) {
+/*
+ * Read /proc/<pid>/cwd (process-shared data)
+ */
+static void LinuxProcessTable_readCwd(LinuxProcess* process, openat_arg_t procFd, const LinuxProcess* mainTask) {
+ if (mainTask) {
+ const char* mainCwd = mainTask->super.procCwd;
+ if (mainCwd) {
+ free_and_xStrdup(&process->super.procCwd, mainCwd);
+ } else {
+ free(process->super.procCwd);
+ process->super.procCwd = NULL;
+ }
+ return;
+ }
+
char pathBuffer[PATH_MAX + 1] = {0};
#if defined(HAVE_READLINKAT) && defined(HAVE_OPENAT)
@@ -978,15 +1058,22 @@ static void LinuxProcessTable_readCwd(LinuxProcess* process, openat_arg_t procFd
free_and_xStrdup(&process->super.procCwd, pathBuffer);
}
-static bool LinuxProcessTable_readCmdlineFile(Process* process, openat_arg_t procFd) {
- char filename[MAX_NAME + 1];
- ssize_t amtRead;
+/*
+ * Read /proc/<pid>/exe (process-shared data)
+ */
+static void LinuxProcessList_readExe(Process* process, openat_arg_t procFd, const LinuxProcess* mainTask) {
+ if (mainTask) {
+ Process_updateExe(process, mainTask->super.procExe);
+ process->procExeDeleted = mainTask->super.procExeDeleted;
+ return;
+ }
+
+ char filename[PATH_MAX + 1];
- /* execve could change /proc/[pid]/exe, so procExe should be updated */
#if defined(HAVE_READLINKAT) && defined(HAVE_OPENAT)
- amtRead = readlinkat(procFd, "exe", filename, sizeof(filename) - 1);
+ ssize_t amtRead = readlinkat(procFd, "exe", filename, sizeof(filename) - 1);
#else
- amtRead = Compat_readlink(procFd, "exe", filename, sizeof(filename) - 1);
+ ssize_t amtRead = Compat_readlink(procFd, "exe", filename, sizeof(filename) - 1);
#endif
if (amtRead > 0) {
filename[amtRead] = 0;
@@ -1016,9 +1103,16 @@ static bool LinuxProcessTable_readCmdlineFile(Process* process, openat_arg_t pro
Process_updateExe(process, NULL);
process->procExeDeleted = false;
}
+}
+
+/*
+ * Read /proc/<pid>/cmdline (process-shared data)
+ */
+static bool LinuxProcessTable_readCmdlineFile(Process* process, openat_arg_t procFd, const LinuxProcess* mainTask) {
+ LinuxProcessList_readExe(process, procFd, mainTask);
char command[4096 + 1]; // max cmdline length on Linux
- amtRead = xReadfileat(procFd, "cmdline", command, sizeof(command));
+ ssize_t amtRead = xReadfileat(procFd, "cmdline", command, sizeof(command));
if (amtRead <= 0)
return false;
@@ -1178,15 +1272,21 @@ static bool LinuxProcessTable_readCmdlineFile(Process* process, openat_arg_t pro
Process_updateCmdline(process, command, tokenStart, tokenEnd);
- /* /proc/[pid]/comm could change, so should be updated */
- if ((amtRead = xReadfileat(procFd, "comm", command, sizeof(command))) > 0) {
+ return true;
+}
+
+/*
+ * Read /proc/<pid>/comm (thread-specific data)
+ */
+static void LinuxProcessList_readComm(Process* process, openat_arg_t procFd) {
+ char command[4096 + 1]; // max cmdline length on Linux
+ ssize_t amtRead = xReadfileat(procFd, "comm", command, sizeof(command));
+ if (amtRead > 0) {
command[amtRead - 1] = '\0';
Process_updateComm(process, command);
} else {
Process_updateComm(process, NULL);
}
-
- return true;
}
static char* LinuxProcessTable_updateTtyDevice(TtyDriver* ttyDrivers, unsigned long int tty_nr) {
@@ -1259,7 +1359,7 @@ static bool isOlderThan(const Process* proc, unsigned int seconds) {
return realtime - proc->starttime_ctime > seconds;
}
-static bool LinuxProcessTable_recurseProcTree(LinuxProcessTable* this, openat_arg_t parentFd, const LinuxMachine* lhost, const char* dirname, const Process* parent) {
+static bool LinuxProcessTable_recurseProcTree(LinuxProcessTable* this, openat_arg_t parentFd, const LinuxMachine* lhost, const char* dirname, const LinuxProcess* mainTask) {
ProcessTable* pt = (ProcessTable*) this;
const Machine* host = &lhost->super;
const Settings* settings = host->settings;
@@ -1317,7 +1417,7 @@ static bool LinuxProcessTable_recurseProcTree(LinuxProcessTable* this, openat_ar
}
// Skip task directory of main thread
- if (parent && pid == Process_getPid(parent))
+ if (mainTask && pid == Process_getPid(&mainTask->super))
continue;
#ifdef HAVE_OPENAT
@@ -1333,10 +1433,11 @@ static bool LinuxProcessTable_recurseProcTree(LinuxProcessTable* this, openat_ar
Process* proc = ProcessTable_getProcess(pt, pid, &preExisting, LinuxProcess_new);
LinuxProcess* lp = (LinuxProcess*) proc;
- Process_setThreadGroup(proc, parent ? Process_getPid(parent) : pid);
+ Process_setThreadGroup(proc, mainTask ? Process_getPid(&mainTask->super) : pid);
proc->isUserlandThread = Process_getPid(proc) != Process_getThreadGroup(proc);
+ assert(proc->isUserlandThread == (mainTask != NULL));
- LinuxProcessTable_recurseProcTree(this, procFd, lhost, "task", proc);
+ LinuxProcessTable_recurseProcTree(this, procFd, lhost, "task", lp);
/*
* These conditions will not trigger on first occurrence, cause we need to
@@ -1367,11 +1468,12 @@ static bool LinuxProcessTable_recurseProcTree(LinuxProcessTable* this, openat_ar
continue;
}
- bool scanMainThread = !hideUserlandThreads && !Process_isKernelThread(proc) && !parent;
+ const bool scanMainThread = !hideUserlandThreads && !Process_isKernelThread(proc) && !mainTask;
+
if (ss->flags & PROCESS_FLAG_IO)
LinuxProcessTable_readIoFile(lp, procFd, scanMainThread);
- if (!LinuxProcessTable_readStatmFile(lp, procFd, lhost))
+ if (!LinuxProcessTable_readStatmFile(lp, procFd, lhost, mainTask))
goto errorReadingProcess;
{
@@ -1391,8 +1493,8 @@ static bool LinuxProcessTable_recurseProcTree(LinuxProcessTable* this, openat_ar
}
} else {
/* Copy from process structure in threads and reset if setting got disabled */
- proc->usesDeletedLib = (proc->isUserlandThread && parent) ? parent->usesDeletedLib : false;
- lp->m_lrs = (proc->isUserlandThread && parent) ? ((const LinuxProcess*)parent)->m_lrs : 0;
+ proc->usesDeletedLib = (proc->isUserlandThread && mainTask) ? mainTask->super.usesDeletedLib : false;
+ lp->m_lrs = (proc->isUserlandThread && mainTask) ? mainTask->m_lrs : 0;
}
if (prev != proc->usesDeletedLib)
@@ -1400,7 +1502,7 @@ static bool LinuxProcessTable_recurseProcTree(LinuxProcessTable* this, openat_ar
}
if ((ss->flags & PROCESS_FLAG_LINUX_SMAPS) && !Process_isKernelThread(proc)) {
- if (!parent) {
+ if (!mainTask) {
// Read smaps file of each process only every second pass to improve performance
static int smaps_flag = 0;
if ((pid & 1) == smaps_flag) {
@@ -1410,7 +1512,7 @@ static bool LinuxProcessTable_recurseProcTree(LinuxProcessTable* this, openat_ar
smaps_flag = !smaps_flag;
}
} else {
- lp->m_pss = ((const LinuxProcess*)parent)->m_pss;
+ lp->m_pss = ((const LinuxProcess*)mainTask)->m_pss;
}
}
@@ -1442,7 +1544,7 @@ static bool LinuxProcessTable_recurseProcTree(LinuxProcessTable* this, openat_ar
proc->percent_mem = proc->m_resident / (double)(host->totalMem) * 100.0;
Process_updateCPUFieldWidths(proc->percent_cpu);
- if (!LinuxProcessTable_updateUser(host, proc, procFd))
+ if (!LinuxProcessTable_updateUser(host, proc, procFd, mainTask))
goto errorReadingProcess;
if (!LinuxProcessTable_readStatusFile(proc, procFd))
@@ -1458,8 +1560,11 @@ static bool LinuxProcessTable_recurseProcTree(LinuxProcessTable* this, openat_ar
if (proc->isKernelThread) {
Process_updateCmdline(proc, NULL, 0, 0);
- } else if (!LinuxProcessTable_readCmdlineFile(proc, procFd)) {
- Process_updateCmdline(proc, statCommand, 0, strlen(statCommand));
+ } else {
+ if (!LinuxProcessTable_readCmdlineFile(proc, procFd, mainTask)) {
+ Process_updateCmdline(proc, statCommand, 0, strlen(statCommand));
+ }
+ LinuxProcessList_readComm(proc, procFd);
}
Process_fillStarttimeBuffer(proc);
@@ -1469,8 +1574,11 @@ static bool LinuxProcessTable_recurseProcTree(LinuxProcessTable* this, openat_ar
if (settings->updateProcessNames && proc->state != ZOMBIE) {
if (proc->isKernelThread) {
Process_updateCmdline(proc, NULL, 0, 0);
- } else if (!LinuxProcessTable_readCmdlineFile(proc, procFd)) {
- Process_updateCmdline(proc, statCommand, 0, strlen(statCommand));
+ } else {
+ if (!LinuxProcessTable_readCmdlineFile(proc, procFd, mainTask)) {
+ Process_updateCmdline(proc, statCommand, 0, strlen(statCommand));
+ }
+ LinuxProcessList_readComm(proc, procFd);
}
}
}
@@ -1498,19 +1606,19 @@ static bool LinuxProcessTable_recurseProcTree(LinuxProcessTable* this, openat_ar
#endif
if (ss->flags & PROCESS_FLAG_LINUX_OOM) {
- LinuxProcessTable_readOomData(lp, procFd);
+ LinuxProcessTable_readOomData(lp, procFd, mainTask);
}
if (ss->flags & PROCESS_FLAG_LINUX_SECATTR) {
- LinuxProcessTable_readSecattrData(lp, procFd);
+ LinuxProcessTable_readSecattrData(lp, procFd, mainTask);
}
if (ss->flags & PROCESS_FLAG_CWD) {
- LinuxProcessTable_readCwd(lp, procFd);
+ LinuxProcessTable_readCwd(lp, procFd, mainTask);
}
if ((ss->flags & PROCESS_FLAG_LINUX_AUTOGROUP) && this->haveAutogroup) {
- LinuxProcessTable_readAutogroup(lp, procFd);
+ LinuxProcessTable_readAutogroup(lp, procFd, mainTask);
}
#ifdef SCHEDULER_SUPPORT
@@ -1520,8 +1628,8 @@ static bool LinuxProcessTable_recurseProcTree(LinuxProcessTable* this, openat_ar
#endif
if (ss->flags & PROCESS_FLAG_LINUX_GPU || GPUMeter_active()) {
- if (parent) {
- lp->gpu_time = ((const LinuxProcess*)parent)->gpu_time;
+ if (mainTask) {
+ lp->gpu_time = ((const LinuxProcess*)mainTask)->gpu_time;
} else {
GPU_readProcessData(this, lp, procFd);
}

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