diff --git a/mx_proc.c b/mx_proc.c index c5197f28..7d402ebc 100644 --- a/mx_proc.c +++ b/mx_proc.c @@ -4,10 +4,38 @@ #include #include #include +#include #include "mx_util.h" #include "mx_proc.h" +static long long int get_rss_anon(pid_t pid) { + _mx_cleanup_free_ char *fname; + mx_asprintf_forever(&fname, "/proc/%d/status", pid); + _mx_cleanup_fclose_ FILE *file = fopen(fname, "r"); + if (file == NULL) + return -errno; + _mx_cleanup_free_ char *buf = NULL; + size_t n = 0; + while(1) { + size_t len = getline(&buf, &n, file); + if (len == -1) + break; + if (strncmp(buf, "RssAnon:", 8) == 0) { + unsigned long long int anon_rss_kb = strtoull(buf+8, NULL, 10); + if (anon_rss_kb == ULLONG_MAX) + return -errno; + if (anon_rss_kb > LLONG_MAX/1024) { // anon_rss > 8 EiB + return -ERANGE; + } + return anon_rss_kb*1024; + } + } + if (feof(file)) + return 0; /* kernel thread */ + return -errno; +} + static int _mx_proc_pid_stat_strscan(char *str, struct mx_proc_pid_stat *pps) { size_t res = 0; @@ -94,6 +122,10 @@ int mx_proc_pid_stat(struct mx_proc_pid_stat **pps, pid_t pid) res = mx_proc_pid_stat_read(pstat, "/proc/%d/stat", pid); if (res < 0) return res; + long long int rss_anon = get_rss_anon(pid); + if (rss_anon < 0) + return rss_anon; + pstat->rss_anon = rss_anon; return 0; } diff --git a/mx_proc.h b/mx_proc.h index 6ae184a8..c9006a9f 100644 --- a/mx_proc.h +++ b/mx_proc.h @@ -69,6 +69,8 @@ struct mx_proc_pid_stat { unsigned long long int delayacct_blkio_ticks; /* 42 */ unsigned long long int guest_time; /* 43 */ long long int cguest_time; /* 44 */ + + unsigned long long int rss_anon; /* from /proc/PID/status. may be null (kernel thread). unit: bytes */ }; int mx_proc_pid_stat_read(struct mx_proc_pid_stat *pps, char *fmt, ...);