[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Time spent in user mode and system mode.



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 to: