diff --git a/linux/LinuxProcess.c b/linux/LinuxProcess.c index e70d7d0c9b..80669a47b1 100644 --- a/linux/LinuxProcess.c +++ b/linux/LinuxProcess.c @@ -112,6 +112,7 @@ const ProcessFieldData Process_fields[LAST_PROCESSFIELD] = { #endif [GPU_TIME] = { .name = "GPU_TIME", .title = "GPU_TIME ", .description = "Total GPU time", .flags = PROCESS_FLAG_LINUX_GPU, .defaultSortDesc = true, }, [GPU_PERCENT] = { .name = "GPU_PERCENT", .title = " GPU% ", .description = "Percentage of the GPU time the process used in the last sampling", .flags = PROCESS_FLAG_LINUX_GPU, .defaultSortDesc = true, }, + [SYSCALL] = { .name = "SYSCALL", .title = "SYSCALL", .description = "Current syscall of the process", .flags = PROCESS_FLAG_LINUX_SYSCALL, .autoWidth = true, }, }; Process* LinuxProcess_new(const Machine* host) { @@ -131,6 +132,7 @@ void Process_delete(Object* cast) { free(this->ctid); #endif free(this->secattr); + free(this->syscall); free(this); } @@ -362,6 +364,18 @@ static void LinuxProcess_rowWriteField(const Row* super, RichString* str, Proces xSnprintf(buffer, n, "N/A "); } break; + case SYSCALL: { + const char* syscall; + if (lp->syscall) { + syscall = lp->syscall; + } else { + attr = CRT_colors[PROCESS_SHADOW]; + syscall = "N/A"; + } + xSnprintf(buffer, n, "%-*.*s ", Row_fieldWidths[SYSCALL], Row_fieldWidths[SYSCALL], syscall); + RichString_appendWide(str, attr, buffer); + return; + } default: Process_writeField(this, str, field); return; @@ -466,6 +480,8 @@ static int LinuxProcess_compareByKey(const Process* v1, const Process* v2, Proce return SPACESHIP_NUMBER(p1->gpu_time, p2->gpu_time); case ISCONTAINER: return SPACESHIP_NUMBER(v1->isRunningInContainer, v2->isRunningInContainer); + case SYSCALL: + return SPACESHIP_NULLSTR(p1->syscall, p2->syscall); default: return Process_compareByKey_Base(v1, v2, key); } diff --git a/linux/LinuxProcess.h b/linux/LinuxProcess.h index fafd7d0044..949fa89d4d 100644 --- a/linux/LinuxProcess.h +++ b/linux/LinuxProcess.h @@ -31,6 +31,7 @@ in the source distribution for its full text. #define PROCESS_FLAG_LINUX_AUTOGROUP 0x00080000 #define PROCESS_FLAG_LINUX_GPU 0x00100000 #define PROCESS_FLAG_LINUX_CONTAINER 0x00200000 +#define PROCESS_FLAG_LINUX_SYSCALL 0x00400000 typedef struct LinuxProcess_ { Process super; @@ -118,6 +119,8 @@ typedef struct LinuxProcess_ { /* Autogroup scheduling (CFS) information */ long int autogroup_id; int autogroup_nice; + + char* syscall; } LinuxProcess; extern int pageSize; diff --git a/linux/LinuxProcessTable.c b/linux/LinuxProcessTable.c index 708e704788..c055d76815 100644 --- a/linux/LinuxProcessTable.c +++ b/linux/LinuxProcessTable.c @@ -1098,6 +1098,33 @@ static void LinuxProcessTable_readCwd(LinuxProcess* process, openat_arg_t procFd free_and_xStrdup(&process->super.procCwd, pathBuffer); } +/* + * Read /proc//syscall (thread-specific data) + */ +static void LinuxProcessTable_readSyscall(LinuxProcess* process, openat_arg_t procFd) { + char buffer[PATH_MAX]; + ssize_t r; + + r = xReadfileat(procFd, "syscall", buffer, sizeof(buffer)); + if (r <= 0) { + free(process->syscall); + process->syscall = NULL; + return; + } + + /* Remove '\n' */ + buffer[r - 1] = '\0'; + + char* arg = strchr(buffer, ' '); + if (arg) { + *arg = '\0'; + } + + Row_updateFieldWidth(SYSCALL, strlen(buffer)); + + free_and_xStrdup(&process->syscall, buffer); +} + /* * Read /proc//exe (process-shared data) */ @@ -1694,6 +1721,10 @@ static bool LinuxProcessTable_recurseProcTree(LinuxProcessTable* this, openat_ar LinuxProcessTable_readCwd(lp, procFd, mainTask); } + if (ss->flags & PROCESS_FLAG_LINUX_SYSCALL) { + LinuxProcessTable_readSyscall(lp, procFd); + } + if ((ss->flags & PROCESS_FLAG_LINUX_AUTOGROUP) && this->haveAutogroup) { LinuxProcessTable_readAutogroup(lp, procFd, mainTask); } diff --git a/linux/ProcessField.h b/linux/ProcessField.h index 47c4199fef..5c2d09ed56 100644 --- a/linux/ProcessField.h +++ b/linux/ProcessField.h @@ -51,6 +51,7 @@ in the source distribution for its full text. GPU_TIME = 132, \ GPU_PERCENT = 133, \ ISCONTAINER = 134, \ + SYSCALL = 135, \ // End of list