mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-09-13 02:42:09 +02:00
Processes: adds total thread count detection
This commit is contained in:
+2
-2
@@ -1065,7 +1065,7 @@ elseif(APPLE)
|
||||
src/detection/packages/packages_apple.c
|
||||
src/detection/packages/packages_nix.c
|
||||
src/detection/poweradapter/poweradapter_apple.c
|
||||
src/detection/processes/processes_bsd.c
|
||||
src/detection/processes/processes_apple.c
|
||||
src/detection/sound/sound_apple.c
|
||||
src/detection/swap/swap_apple.c
|
||||
src/detection/terminalfont/terminalfont_apple.m
|
||||
@@ -1240,7 +1240,7 @@ elseif(SunOS)
|
||||
src/detection/os/os_sunos.c
|
||||
src/detection/packages/packages_sunos.c
|
||||
src/detection/poweradapter/poweradapter_nosupport.c
|
||||
src/detection/processes/processes_linux.c
|
||||
src/detection/processes/processes_sunos.c
|
||||
src/detection/gtk_qt/qt.c
|
||||
src/detection/sound/sound_sunos.c
|
||||
src/detection/swap/swap_sunos.c
|
||||
|
||||
@@ -2,4 +2,10 @@
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
const char* ffDetectProcesses(uint32_t* result);
|
||||
typedef struct FFProcessesResult
|
||||
{
|
||||
uint32_t processes;
|
||||
uint32_t threads;
|
||||
} FFProcessesResult;
|
||||
|
||||
const char* ffDetectProcesses(FFProcessesResult* result);
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
#include "processes.h"
|
||||
#include "common/mallocHelper.h"
|
||||
|
||||
#import <libproc.h>
|
||||
|
||||
const char* ffDetectProcesses(FFProcessesResult* result) {
|
||||
FF_AUTO_FREE pid_t* pids = malloc(sizeof(pid_t) * 0x1000);
|
||||
int count = proc_listallpids(pids, 0x1000);
|
||||
int trdCount = 0;
|
||||
for (int index = 0; index < count; ++index) {
|
||||
struct proc_taskinfo taskInfo;
|
||||
if (proc_pidinfo(pids[index], PROC_PIDTASKINFO, 0, &taskInfo, sizeof(taskInfo)) != sizeof(taskInfo)) {
|
||||
continue;
|
||||
}
|
||||
trdCount += taskInfo.pti_threadnum;
|
||||
}
|
||||
|
||||
result->processes = (uint32_t) count;
|
||||
result->threads = (uint32_t) trdCount;
|
||||
return nullptr;
|
||||
}
|
||||
@@ -1,23 +1,23 @@
|
||||
#include "processes.h"
|
||||
|
||||
#include <sys/sysctl.h>
|
||||
#ifdef __FreeBSD__
|
||||
#include <sys/types.h>
|
||||
#include <sys/user.h>
|
||||
#endif
|
||||
#include <sys/types.h>
|
||||
#include <sys/user.h>
|
||||
|
||||
#ifndef KERN_PROC_PROC
|
||||
#define KERN_PROC_PROC KERN_PROC_ALL // Apple
|
||||
#endif
|
||||
|
||||
const char* ffDetectProcesses(uint32_t* result) {
|
||||
int request[] = { CTL_KERN, KERN_PROC, KERN_PROC_PROC };
|
||||
size_t length;
|
||||
|
||||
if (sysctl(request, ARRAY_SIZE(request), nullptr, &length, nullptr, 0) != 0) {
|
||||
const char* ffDetectProcesses(FFProcessesResult* result) {
|
||||
int procRequest[] = { CTL_KERN, KERN_PROC, KERN_PROC_PROC };
|
||||
size_t procLength;
|
||||
if (sysctl(procRequest, ARRAY_SIZE(procRequest), nullptr, &procLength, nullptr, 0) != 0) {
|
||||
return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_PROC}) failed";
|
||||
}
|
||||
|
||||
*result = (uint32_t) (length / sizeof(struct kinfo_proc));
|
||||
int threadRequest[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL };
|
||||
size_t threadLength;
|
||||
if (sysctl(threadRequest, ARRAY_SIZE(threadRequest), nullptr, &threadLength, nullptr, 0) != 0) {
|
||||
return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_ALL}) failed";
|
||||
}
|
||||
|
||||
result->processes = (uint32_t) (procLength / sizeof(struct kinfo_proc));
|
||||
result->threads = (uint32_t) (threadLength / sizeof(struct kinfo_proc));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#include <hurd.h>
|
||||
#include <ps.h>
|
||||
|
||||
const char* ffDetectProcesses(uint32_t* result) {
|
||||
const char* ffDetectProcesses(FFProcessesResult* result) {
|
||||
struct ps_context* context = nullptr;
|
||||
if (ps_context_create(getproc(), &context) != 0) {
|
||||
return "ps_context_create(getproc()) failed";
|
||||
@@ -16,15 +16,26 @@ const char* ffDetectProcesses(uint32_t* result) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
// No flags are needed; we only count the processes.
|
||||
if (proc_stat_list_add_all(list, nullptr, nullptr) != 0) {
|
||||
struct proc_stat **stats = nullptr;
|
||||
unsigned int numProcs = 0;
|
||||
if (proc_stat_list_add_all(list, &stats, &numProcs) != 0) {
|
||||
error = "proc_stat_list_add_all() failed";
|
||||
goto done;
|
||||
}
|
||||
|
||||
*result = (uint32_t) list->num_procs;
|
||||
uint32_t nthread = 0;
|
||||
for (unsigned int i = 0; i < numProcs; i++) {
|
||||
proc_stat_get_basic_info(stats[i]);
|
||||
nthread += proc_stat_thread_count(stats[i]);
|
||||
}
|
||||
|
||||
result->processes = (uint32_t) numProcs;
|
||||
result->threads = nthread;
|
||||
|
||||
done:
|
||||
if (stats) {
|
||||
proc_stat_list_free_stats(stats, numProcs);
|
||||
}
|
||||
if (list) {
|
||||
proc_stat_list_free(list);
|
||||
}
|
||||
|
||||
@@ -2,13 +2,14 @@
|
||||
|
||||
#include <OS.h>
|
||||
|
||||
const char* ffDetectProcesses(uint32_t* result) {
|
||||
const char* ffDetectProcesses(FFProcessesResult* result) {
|
||||
system_info info;
|
||||
if (get_system_info(&info) != B_OK) {
|
||||
return "Error getting system info";
|
||||
}
|
||||
|
||||
*result = info.used_teams;
|
||||
result->processes = info.used_teams;
|
||||
result->threads = info.used_threads;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -1,27 +1,60 @@
|
||||
#include "processes.h"
|
||||
|
||||
#include "common/io.h"
|
||||
#include "common/memrchr.h"
|
||||
#include "common/strutil.h"
|
||||
|
||||
const char* ffDetectProcesses(uint32_t* result) {
|
||||
const char* ffDetectProcesses(FFProcessesResult* result) {
|
||||
FF_AUTO_CLOSE_DIR DIR* dir = opendir("/proc");
|
||||
if (dir == nullptr) {
|
||||
return "opendir(\"/proc\") failed";
|
||||
}
|
||||
|
||||
uint32_t num = 0;
|
||||
uint32_t processes = 0;
|
||||
uint32_t threads = 0;
|
||||
|
||||
int procfd = dirfd(dir);
|
||||
|
||||
struct dirent* entry;
|
||||
while ((entry = readdir(dir)) != nullptr) {
|
||||
if (
|
||||
#ifdef _DIRENT_HAVE_D_TYPE
|
||||
(entry->d_type == DT_DIR || entry->d_type == DT_UNKNOWN) &&
|
||||
#endif
|
||||
ffCharIsDigit(entry->d_name[0]))
|
||||
++num;
|
||||
if ((entry->d_type == DT_DIR || entry->d_type == DT_UNKNOWN) && ffCharIsDigit(entry->d_name[0])) {
|
||||
++processes;
|
||||
|
||||
char statPath[32];
|
||||
strcpy(ffStrCopy(statPath, entry->d_name, sizeof(statPath)), "/stat");
|
||||
|
||||
char statBuffer[256];
|
||||
ssize_t statLength = ffReadFileDataRelative(procfd, statPath, sizeof(statBuffer) - 1, statBuffer);
|
||||
if (statLength < 0) {
|
||||
continue;
|
||||
}
|
||||
statBuffer[statLength] = '\0';
|
||||
|
||||
const char* cursor = (const char*) memrchr(statBuffer, ')', (size_t) statLength);
|
||||
if (!cursor) {
|
||||
continue;
|
||||
}
|
||||
++cursor;
|
||||
|
||||
for (uint32_t field = 2 /*comm*/; field < 20 /*num_threads*/; ++field) {
|
||||
while (*cursor != ' ' && __builtin_expect(*cursor != '\0', true)) {
|
||||
++cursor;
|
||||
}
|
||||
++cursor;
|
||||
if (__builtin_expect(*cursor == '\0', false)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (__builtin_expect(*cursor == '\0', false)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
threads += (uint32_t) strtoul(cursor, nullptr, 10);
|
||||
}
|
||||
}
|
||||
|
||||
*result = num;
|
||||
result->processes = processes;
|
||||
result->threads = threads;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -1,15 +1,34 @@
|
||||
#include "processes.h"
|
||||
#include "common/mallocHelper.h"
|
||||
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
const char* ffDetectProcesses(uint32_t* result) {
|
||||
int request[] = { CTL_KERN, KERN_PROC2, KERN_PROC_ALL, -1, sizeof(struct kinfo_proc2), 0 };
|
||||
const char* ffDetectProcesses(FFProcessesResult* result) {
|
||||
int request[] = { CTL_KERN, KERN_PROC2, KERN_PROC_ALL, -1, sizeof(struct kinfo_proc2), INT_MAX };
|
||||
size_t length = 0;
|
||||
|
||||
if (sysctl(request, ARRAY_SIZE(request), nullptr, &length, nullptr, 0) != 0) {
|
||||
return "sysctl({CTL_KERN, KERN_PROC2, KERN_PROC_ALL}) failed";
|
||||
return "sysctl({CTL_KERN, KERN_PROC2, KERN_PROC_ALL, nullptr}) failed";
|
||||
}
|
||||
|
||||
*result = (uint32_t) (length / sizeof(struct kinfo_proc2));
|
||||
FF_AUTO_FREE struct kinfo_proc2* procs = malloc(length);
|
||||
if (sysctl(request, ARRAY_SIZE(request), procs, &length, nullptr, 0) != 0) {
|
||||
return "sysctl({CTL_KERN, KERN_PROC2, KERN_PROC_ALL, procs}) failed";
|
||||
}
|
||||
|
||||
uint32_t procCount = (uint32_t) (length / sizeof(struct kinfo_proc2));
|
||||
result->processes = procCount;
|
||||
|
||||
uint32_t threads = 0;
|
||||
for (uint32_t i = 0; i < procCount; ++i) {
|
||||
int lwpRequest[] = { CTL_KERN, KERN_LWP, procs[i].p_pid, sizeof(struct kinfo_lwp), 0 };
|
||||
size_t lwpLength = 0;
|
||||
|
||||
if (sysctl(lwpRequest, ARRAY_SIZE(lwpRequest), nullptr, &lwpLength, nullptr, 0) == 0) {
|
||||
threads += (uint32_t) (lwpLength / sizeof(struct kinfo_lwp));
|
||||
}
|
||||
}
|
||||
|
||||
result->threads = threads;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include "processes.h"
|
||||
|
||||
const char* ffDetectProcesses(uint32_t* result) {
|
||||
const char* ffDetectProcesses([[maybe_unused]] FFProcessesResult* result) {
|
||||
return "Not supported on this platform";
|
||||
}
|
||||
|
||||
@@ -2,14 +2,25 @@
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <kvm.h>
|
||||
|
||||
const char* ffDetectProcesses(uint32_t* result) {
|
||||
kvm_t* kd = kvm_open(nullptr, nullptr, nullptr, KVM_NO_FILES, nullptr);
|
||||
const void* ret = kvm_getprocs(kd, KERN_PROC_ALL, 0, 1, result);
|
||||
kvm_close(kd);
|
||||
if (!ret) {
|
||||
return "kvm_getprocs() failed";
|
||||
const char* ffDetectProcesses(FFProcessesResult* result) {
|
||||
int procRequest[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0, sizeof(struct kinfo_proc), 0 };
|
||||
size_t procLength = 0;
|
||||
|
||||
if (sysctl(procRequest, ARRAY_SIZE(procRequest), nullptr, &procLength, nullptr, 0) != 0) {
|
||||
return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_ALL}) failed";
|
||||
}
|
||||
|
||||
result->processes = (uint32_t) (procLength / sizeof(struct kinfo_proc));
|
||||
|
||||
int threadRequest[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL | KERN_PROC_SHOW_THREADS, 0, sizeof(struct kinfo_proc), 0 };
|
||||
size_t threadLength = 0;
|
||||
|
||||
if (sysctl(threadRequest, ARRAY_SIZE(threadRequest), nullptr, &threadLength, nullptr, 0) != 0) {
|
||||
return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_ALL | KERN_PROC_SHOW_THREADS}) failed";
|
||||
}
|
||||
|
||||
result->threads = (uint32_t) (threadLength / sizeof(struct kinfo_proc));
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
#include "processes.h"
|
||||
|
||||
#include "common/io.h"
|
||||
#include "common/strutil.h"
|
||||
|
||||
#include <procfs.h>
|
||||
|
||||
const char* ffDetectProcesses(FFProcessesResult* result) {
|
||||
FF_AUTO_CLOSE_DIR DIR* dir = opendir("/proc");
|
||||
if (dir == nullptr) {
|
||||
return "opendir(\"/proc\") failed";
|
||||
}
|
||||
|
||||
uint32_t processes = 0;
|
||||
uint32_t threads = 0;
|
||||
|
||||
int procfd = dirfd(dir);
|
||||
|
||||
struct dirent* entry;
|
||||
while ((entry = readdir(dir)) != nullptr) {
|
||||
if (ffCharIsDigit(entry->d_name[0])) {
|
||||
++processes;
|
||||
|
||||
char psinfoPath[32];
|
||||
strcpy(ffStrCopy(psinfoPath, entry->d_name, sizeof(psinfoPath)), "/psinfo");
|
||||
|
||||
psinfo_t info;
|
||||
if (ffReadFileDataRelative(procfd, psinfoPath, sizeof(info), &info) == (ssize_t) sizeof(info)) {
|
||||
threads += info.pr_nlwp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result->processes = processes;
|
||||
result->threads = threads;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
#include <ntstatus.h>
|
||||
#include <winternl.h>
|
||||
|
||||
const char* ffDetectProcesses(uint32_t* result) {
|
||||
const char* ffDetectProcesses(FFProcessesResult* result) {
|
||||
FF_AUTO_FREE SYSTEM_PROCESS_INFORMATION* pstart = nullptr;
|
||||
|
||||
// Multiple attempts in case processes change while
|
||||
@@ -25,10 +25,17 @@ const char* ffDetectProcesses(uint32_t* result) {
|
||||
}
|
||||
}
|
||||
|
||||
*result = 1; // Init with 1 because we test for ptr->NextEntryOffset
|
||||
for (SYSTEM_PROCESS_INFORMATION* ptr = pstart; ptr->NextEntryOffset; ptr = (SYSTEM_PROCESS_INFORMATION*) ((uint8_t*) ptr + ptr->NextEntryOffset)) {
|
||||
++*result;
|
||||
uint32_t processes = 0;
|
||||
uint32_t threads = 0;
|
||||
for (SYSTEM_PROCESS_INFORMATION* ptr = pstart; ; ptr = (SYSTEM_PROCESS_INFORMATION*) ((uint8_t*) ptr + ptr->NextEntryOffset)) {
|
||||
++processes;
|
||||
threads += ptr->NumberOfThreads;
|
||||
if (ptr->NextEntryOffset == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
result->processes = processes;
|
||||
result->threads = threads;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
#include "modules/processes/processes.h"
|
||||
|
||||
bool ffPrintProcesses(FFProcessesOptions* options) {
|
||||
uint32_t numProcesses = 0;
|
||||
const char* error = ffDetectProcesses(&numProcesses);
|
||||
FFProcessesResult result = {};
|
||||
const char* error = ffDetectProcesses(&result);
|
||||
|
||||
if (error) {
|
||||
ffPrintError(FF_MODULE_GET_DISPLAY_NAME(Processes), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error);
|
||||
@@ -16,9 +16,9 @@ bool ffPrintProcesses(FFProcessesOptions* options) {
|
||||
if (options->moduleArgs.outputFormat.length == 0) {
|
||||
ffPrintLogoAndKey(FF_MODULE_GET_DISPLAY_NAME(Processes), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
|
||||
|
||||
printf("%u\n", numProcesses);
|
||||
printf("%u (%u threads)\n", result.processes, result.threads);
|
||||
} else {
|
||||
FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Processes), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(numProcesses, "result") }));
|
||||
FF_PRINT_FORMAT_CHECKED(FF_MODULE_GET_DISPLAY_NAME(Processes), 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, ((FFformatarg[]) { FF_ARG(result.processes, "result") }));
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -41,7 +41,7 @@ void ffGenerateProcessesJsonConfig(FFProcessesOptions* options, yyjson_mut_doc*
|
||||
}
|
||||
|
||||
bool ffGenerateProcessesJsonResult([[maybe_unused]] FFProcessesOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) {
|
||||
uint32_t result;
|
||||
FFProcessesResult result = {};
|
||||
const char* error = ffDetectProcesses(&result);
|
||||
|
||||
if (error) {
|
||||
@@ -49,7 +49,8 @@ bool ffGenerateProcessesJsonResult([[maybe_unused]] FFProcessesOptions* options,
|
||||
return false;
|
||||
}
|
||||
|
||||
yyjson_mut_obj_add_uint(doc, module, "result", result);
|
||||
yyjson_mut_obj_add_uint(doc, module, "processes", result.processes);
|
||||
yyjson_mut_obj_add_uint(doc, module, "threads", result.threads);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user