Skip to content

Commit

Permalink
mx_util: Add mx_proc_pid_stat()
Browse files Browse the repository at this point in the history
  • Loading branch information
mariux committed Sep 23, 2015
1 parent bbc2071 commit 426ffed
Show file tree
Hide file tree
Showing 3 changed files with 173 additions and 0 deletions.
98 changes: 98 additions & 0 deletions mx_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -842,6 +842,104 @@ int mx_strscan_ll(char **str, long long int *to)
return res;
}

int mx_strscan_proc_pid_stat(char *str, struct proc_pid_stat *pps)
{
size_t res = 0;
char *p;
char *s;

pps->comm = NULL;

s = str;

res += mx_strscan_ll(&s, &(pps->pid));

p = strrchr(s, ')');
if (!p)
return -(errno=EINVAL);

*p = 0;
s++;

pps->comm = mx_strdup_forever(s);
s = p + 2;

pps->state = *s;
res += !(*(s+1) == ' ');
s += 2;

res += mx_strscan_ll(&s, &(pps->ppid));
res += mx_strscan_ll(&s, &(pps->pgrp));
res += mx_strscan_ll(&s, &(pps->session));
res += mx_strscan_ll(&s, &(pps->tty_nr));
res += mx_strscan_ll(&s, &(pps->tpgid));
res += mx_strscan_ull(&s, &(pps->flags));
res += mx_strscan_ull(&s, &(pps->minflt));
res += mx_strscan_ull(&s, &(pps->cminflt));
res += mx_strscan_ull(&s, &(pps->majflt));
res += mx_strscan_ull(&s, &(pps->cmajflt));
res += mx_strscan_ull(&s, &(pps->utime));
res += mx_strscan_ull(&s, &(pps->stime));
res += mx_strscan_ll(&s, &(pps->cutime));
res += mx_strscan_ll(&s, &(pps->cstime));
res += mx_strscan_ll(&s, &(pps->priority));
res += mx_strscan_ll(&s, &(pps->nice));
res += mx_strscan_ll(&s, &(pps->num_threads));
res += mx_strscan_ll(&s, &(pps->itrealvalue));
res += mx_strscan_ull(&s, &(pps->starttime));
res += mx_strscan_ull(&s, &(pps->vsize));
res += mx_strscan_ll(&s, &(pps->rss));
res += mx_strscan_ull(&s, &(pps->rsslim));
res += mx_strscan_ull(&s, &(pps->startcode));
res += mx_strscan_ull(&s, &(pps->endcode));
res += mx_strscan_ull(&s, &(pps->startstack));
res += mx_strscan_ull(&s, &(pps->kstkesp));
res += mx_strscan_ull(&s, &(pps->kstkeip));
res += mx_strscan_ull(&s, &(pps->signal));
res += mx_strscan_ull(&s, &(pps->blocked));
res += mx_strscan_ull(&s, &(pps->sigignore));
res += mx_strscan_ull(&s, &(pps->sigcatch));
res += mx_strscan_ull(&s, &(pps->wchan));
res += mx_strscan_ull(&s, &(pps->nswap));
res += mx_strscan_ull(&s, &(pps->cnswap));
res += mx_strscan_ll(&s, &(pps->exit_signal));
res += mx_strscan_ll(&s, &(pps->processor));
res += mx_strscan_ull(&s, &(pps->rt_priority));
res += mx_strscan_ull(&s, &(pps->policy));
res += mx_strscan_ull(&s, &(pps->delayacct_blkio_ticks));
res += mx_strscan_ull(&s, &(pps->guest_time));
res += mx_strscan_ll(&s, &(pps->cguest_time));

if (res != 0)
return -(errno=EINVAL);

return 0;
}

int mx_proc_pid_stat(struct proc_pid_stat *pps, pid_t pid)
{
_mx_cleanup_free_ char *fname = NULL;
_mx_cleanup_free_ char *line = NULL;
int res;

mx_asprintf_forever(&fname, "/proc/%d/stat", pid);

res = mx_read_first_line_from_file(fname, &line);
if (res < 0)
return res;

res = mx_strscan_proc_pid_stat(line, pps);
if (res < 0)
return res;

return 0;
}

void mx_proc_pid_stat_free(struct proc_pid_stat *pps)
{
mx_free_null(pps->comm);
}

int mx_sleep(unsigned int seconds)
{
if (seconds)
Expand Down
51 changes: 51 additions & 0 deletions mx_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,53 @@

#include "mx_log.h"

struct proc_pid_stat {
long long int pid; /* 1 */
char *comm; /* 2 (comm) */
char state; /* 3 "RSDZTW" */
long long int ppid; /* 4 */
long long int pgrp; /* 5 */
long long int session; /* 6 */
long long int tty_nr; /* 7 */
long long int tpgid; /* 8 */
unsigned long long int flags; /* 9 */
unsigned long long int minflt; /* 10 */
unsigned long long int cminflt; /* 11 */
unsigned long long int majflt; /* 12 */
unsigned long long int cmajflt; /* 13 */
unsigned long long int utime; /* 14 */
unsigned long long int stime; /* 15 */
long long int cutime; /* 16 */
long long int cstime; /* 17 */
long long int priority; /* 18 */
long long int nice; /* 19 */
long long int num_threads; /* 20 */
long long int itrealvalue; /* 21 */
unsigned long long int starttime; /* 22 */
unsigned long long int vsize; /* 23 */
long long int rss; /* 24 */
unsigned long long int rsslim; /* 25 */
unsigned long long int startcode; /* 26 */
unsigned long long int endcode; /* 27 */
unsigned long long int startstack; /* 28 */
unsigned long long int kstkesp; /* 29 */
unsigned long long int kstkeip; /* 30 */
unsigned long long int signal; /* 31 */
unsigned long long int blocked; /* 32 */
unsigned long long int sigignore; /* 33 */
unsigned long long int sigcatch; /* 34 */
unsigned long long int wchan; /* 35 */
unsigned long long int nswap; /* 36 */
unsigned long long int cnswap; /* 37 */
long long int exit_signal; /* 38 */
long long int processor; /* 39 */
unsigned long long int rt_priority; /* 40 */
unsigned long long int policy; /* 41 */
unsigned long long int delayacct_blkio_ticks; /* 42 */
unsigned long long int guest_time; /* 43 */
long long int cguest_time; /* 44 */
};

#ifdef MX_NDEBUG
# include <assert.h>
# define mx_assert_return_minus_errno(test, eno) \
Expand Down Expand Up @@ -119,6 +166,10 @@ int mx_read_first_line_from_file(char *fname, char **line);

int mx_strscan_ull(char **str, unsigned long long int *to);
int mx_strscan_ll(char **str, long long int *to);
int mx_strscan_proc_pid_stat(char *str, struct proc_pid_stat *pps);

int mx_proc_pid_stat(struct proc_pid_stat *pps, pid_t pid);
void mx_proc_pid_stat_free(struct proc_pid_stat *pps);

int mx_sleep(unsigned int seconds);
int mx_sleep_nofail(unsigned int seconds);
Expand Down
24 changes: 24 additions & 0 deletions test_mx_util.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@

#define _GNU_SOURCE

#include <assert.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>

#include "mx_util.h"

Expand Down Expand Up @@ -275,6 +279,7 @@ static void test_mx_strtobytes(void)
static void test_mx_read_first_line_from_file(void)
{
char *str;
long long int l;

assert(mx_read_first_line_from_file("/proc/sys/kernel/random/boot_id", &str) == 36);
assert(str);
Expand All @@ -289,6 +294,7 @@ static void test_mx_read_first_line_from_file(void)

assert(mx_read_first_line_from_file("/proc/self/stat", &str) > 0);
assert(str);
mx_strtoll(str, &l);
mx_free_null(str);
}

Expand All @@ -298,6 +304,9 @@ static void test_mx_strscan(void)
char *str;
unsigned long long int ull;
long long int ll;
_mx_cleanup_free_ char *line = NULL;
struct proc_pid_stat pps = {0};
struct proc_pid_stat pps2 = {0};

assert(s = strdup("123 456 -789 246 abc"));
str = s;
Expand Down Expand Up @@ -331,8 +340,23 @@ static void test_mx_strscan(void)
assert(mx_streq(str, ""));
assert(mx_streq(s, "123"));

assert(mx_read_first_line_from_file("/proc/self/stat", &line) > 0);
assert(mx_strscan_proc_pid_stat(line, &pps) == 0);
assert(pps.pid == getpid());
assert(pps.ppid == getppid());
assert(pps.state == 'R');
assert(mx_streq(pps.comm, program_invocation_short_name) || mx_streq(pps.comm, "memcheck-amd64-"));
mx_proc_pid_stat_free(&pps);

assert(mx_proc_pid_stat(&pps2, getpid()) == 0);
assert(pps2.pid == getpid());
assert(pps2.ppid == getppid());
assert(pps2.state == 'R');
assert(mx_streq(pps2.comm, program_invocation_short_name) || mx_streq(pps2.comm, "memcheck-amd64-"));
mx_proc_pid_stat_free(&pps2);
}


int main(int argc, char *argv[])
{
test_mx_strskipwhitespaces();
Expand Down

0 comments on commit 426ffed

Please sign in to comment.