Hello !

I'm trying to solve http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=676450 . All I need before submitting a first attempt at the Hurd backend to the python-psutil folks is to be able to retrieve data similar to what can be found in /proc/stat on GNU/Linux (without using the procfs translator, obviously).

Here is an extract of "man 5 proc" on Debian GNU/Linux:

"/proc/stat
kernel/system statistics. Varies with architecture. Common entries include:

    cpu  3357 0 4313 1362393
The amount of time, measured in units of USER_HZ (1/100ths of a second on most architectures, use sysconf(_SC_CLK_TCK) to obtain the right value), that the system spent in user mode, user mode with low priority (nice), system mode, and the idle task, respectively. The last value should be USER_HZ times the second entry in the uptime pseudo-file."

I thought that one way of doing this would be to apply the following algorithm:

total_system_time := 0
total_user_time := 0
processes := list_all_processes()

for p in processes:
    total_system_time += p.system_time
    total_user_time += p.user_time

I've tried three different things:

1) using the getters defined in libps/spec.c
2) using proc_getprocinfo()
3) using task_info()

Here are the resutls I get :

$ ./getter && ./procinfo && ./task_info
System 1900, User 300
System 192000, User 300
System 0, User 0

$ head -1 /proc/stat
cpu  2884 0 0 195460 0 0 0 0 0


What is the right method ? What am I doing wrong ? Attached are the three source files I used.


Cyril Roelandt.
#define _GNU_SOURCE

#include <hurd.h>
#include <ps.h>

#include <sys/time.h>

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>

int
main(void)
{
        int err;
        mach_port_t proc = getproc();
        pid_t *pids = NULL;
        mach_msg_type_number_t pidslen = 0;
        struct timeval tot_sys = { 0, 0 };
        struct timeval tot_usr = { 0, 0 };

        err =  proc_getallpids(proc, &pids, &pidslen);
        assert(err == 0);

        struct ps_context *pc = NULL;
        err = ps_context_create(getproc(), &pc);
        assert(err == 0 && pc != NULL);

        unsigned i;
        for (i = 0; i < pidslen; i++)
        {
                struct proc_stat *ps = NULL;
                err = ps_context_find_proc_stat(pc, pids[i], &ps);
                assert(err == 0 && ps != NULL);

                const struct ps_fmt_spec *sys_spec = NULL;
                sys_spec = ps_fmt_specs_find(&ps_std_fmt_specs, "STime");
                assert(sys_spec != NULL);

                const struct ps_getter *sys_getter = NULL;
                sys_getter = sys_spec->getter;
                assert(sys_getter != NULL);

                const struct ps_fmt_spec *usr_spec = NULL;
                usr_spec = ps_fmt_specs_find(&ps_std_fmt_specs, "UTime");
                assert(usr_spec != NULL);

                const struct ps_getter *usr_getter = NULL;
                usr_getter = usr_spec->getter;
                assert(usr_getter != NULL);

                ps_flags_t sys_needs = ps_getter_needs(sys_getter);
                ps_flags_t usr_needs = ps_getter_needs(usr_getter);
                err = proc_stat_set_flags(ps, sys_needs);
                assert(err == 0 && (ps->flags & sys_needs));
                err = proc_stat_set_flags(ps, usr_needs);
                assert(err == 0 && (ps->flags & usr_needs));

                /* Finally getting the values we are looking for. */
                struct timeval sys_val;
                struct timeval usr_val;
                sys_getter->fn(ps, &sys_val);
                usr_getter->fn(ps, &usr_val);

                timeradd(&sys_val, &tot_sys, &tot_sys);
                timeradd(&usr_val, &tot_usr, &tot_usr);
        }

        /* Convert to jiffies before printing. */
        //long clock_ticks = sysconf("_SC_CLK_TCK");
        long clock_ticks = 100;
        fprintf(stderr, "System %ld, User %ld\n",
                        tot_sys.tv_sec * clock_ticks,
                        tot_usr.tv_sec * clock_ticks);

        return 0;
}
#define _GNU_SOURCE

#include <hurd.h>
#include <ps.h>

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>

#include <sys/time.h>

int
main(void)
{
        struct timeval sys = { 0, 0 };
        struct timeval usr = { 0, 0 };
        mach_port_t proc = getproc();
        pid_t *pids = NULL;
        mach_msg_type_number_t pidslen = 0;
        error_t err;
        err =  proc_getallpids (proc, &pids, &pidslen);
        unsigned i;
        for (i = 0; i < pidslen; i++)
        {
                int pi_flags = PI_FETCH_TASKINFO | PI_FETCH_THREADS | 
PI_FETCH_THREAD_BASIC;

                struct ps_context *pc = NULL;
                err = ps_context_create(getproc(), &pc);
                assert(err == 0 && pc != NULL);

                struct proc_stat *ps = NULL;
                err = ps_context_find_proc_stat(pc, pids[i], &ps);
                assert(err == 0 && ps != NULL);

                size_t pi_size = ps->proc_info_size;
                size_t waits_len = ps->thread_waits_len;
                err = proc_getprocinfo(
                        getproc(),
                        pids[i],
                        &pi_flags,
                        (procinfo_t *) &ps->proc_info,
                        &pi_size,
                        &ps->thread_waits,
                        &waits_len);

                struct procinfo *pi = ps->proc_info;

                int j;
                for (j = 0; j < pi->nthreads; j++)
                {
                        struct timeval tmp;
                        thread_basic_info_t tbi = &pi->threadinfos[j].pis_bi;

                        tmp.tv_sec = tbi->system_time.seconds;
                        tmp.tv_usec = tbi->system_time.microseconds;
                        timeradd(&tmp, &sys, &sys);

                        tmp.tv_sec = tbi->user_time.seconds;
                        tmp.tv_usec = tbi->user_time.microseconds;
                        timeradd(&tmp, &usr, &usr);
                }
        }

        fprintf(stderr, "System %ld, User %ld\n",
                        sys.tv_sec * 100,
                        usr.tv_sec * 100);

        return 0;
}
#define _GNU_SOURCE

#include <hurd.h>
#include <ps.h>

#include <sys/time.h>

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>

int
main(void)
{
        struct timeval tot_sys = { 0, 0 };
        struct timeval tot_usr = { 0, 0 };

        mach_port_t proc = getproc();
        pid_t *pids = NULL;
        mach_msg_type_number_t pidslen = 0;

        assert(proc_getallpids (proc, &pids, &pidslen) == 0);

        unsigned i;
        for (i = 0; i < pidslen; i++)
        {
                error_t err;

                struct ps_context *pc = NULL;
                err = ps_context_create(getproc(), &pc);
                assert(err == 0 && pc != NULL);

                struct proc_stat *ps = NULL;
                err = ps_context_find_proc_stat(pc, pids[i], &ps);
                assert(err == 0 && ps != NULL);

                struct task_thread_times_info ttti;
                ttti.user_time.seconds = 0;
                ttti.user_time.microseconds = 0;
                ttti.system_time.seconds = 0;
                ttti.system_time.microseconds = 0;

                mach_msg_type_number_t cnt = TASK_THREAD_TIMES_INFO_COUNT;
                kern_return_t error;
                proc_stat_set_flags(ps, PSTAT_TASK | PSTAT_TASK_BASIC);
                error = task_info(ps->task, TASK_THREAD_TIMES_INFO, 
(task_info_t) &ttti, &cnt);
                if (error == KERN_SUCCESS)
                {
                        struct timeval tmp;
                        tmp.tv_sec = ttti.user_time.seconds;
                        tmp.tv_usec = ttti.user_time.microseconds;
                        timeradd(&tmp, &tot_usr, &tot_usr);

                        tmp.tv_sec = ttti.system_time.seconds;
                        tmp.tv_usec = ttti.system_time.microseconds;
                        timeradd(&tmp, &tot_sys, &tot_sys);
                }

                struct task_basic_info tbi;
                cnt = TASK_BASIC_INFO_COUNT;
                error = task_info(ps->task, TASK_BASIC_INFO, (task_info_t) 
&tbi, &cnt);
                if (error == KERN_SUCCESS)
                {
                        struct timeval tmp;
                        tmp.tv_sec = tbi.user_time.seconds;
                        tmp.tv_usec = tbi.user_time.microseconds;
                        timeradd(&tmp, &tot_usr, &tot_usr);

                        tmp.tv_sec = tbi.system_time.seconds;
                        tmp.tv_usec = tbi.system_time.microseconds;
                        timeradd(&tmp, &tot_sys, &tot_sys);
                }
        }

        fprintf(stderr, "System %ld, User %ld\n",
                        tot_sys.tv_sec * 100,
                        tot_usr.tv_sec * 100);
        return 0;

}
CC=gcc
CFLAGS=-Wall -Wextra
LDFLAGS=-lps

all: getter procinfo task_info

getter: getter.c
        $(CC) $(CFLAGS) $(LDFLAGS) -o getter getter.c

procinfo: procinfo.c
        $(CC) $(CFLAGS) $(LDFLAGS) -o procinfo procinfo.c

task_info: task_info.c
        $(CC) $(CFLAGS) $(LDFLAGS) -o task_info task_info.c

clean:
        rm -f getter procinfo task_info

Reply via email to