1/* $Id: Getrusage.xs 11 2006-02-04 00:53:56Z taffy $ -*- c -*- */
2
3#include "EXTERN.h"
4#include "perl.h"
5#include "XSUB.h"
6
7#include "ppport.h"
8
9#include <string.h>
10#include <stdio.h>
11#include <assert.h>
12#include <sys/types.h>
13#include <sys/time.h>
14#include <sys/resource.h>
15
16#define STORE_FIELD(format,data) string_store(hash, #data, format, res.data);
17#define STORE_TIMEVAL(x) string_store(hash, #x, "%.6f", timeval_to_double(&res.x));
18#define syscall(x) ({ int y = (x); if(y < 0) { perror(#x); }; y; })
19
20static void string_store(HV* hash, const char *key, const char *fmt, ...) {
21	char buffer[0x1000];
22	va_list p;
23	int len;
24
25	assert(hash != NULL);
26	assert(key != NULL);
27	assert(fmt != NULL);
28
29	va_start(p, fmt);
30	len = vsnprintf(buffer, sizeof(buffer), fmt, p);
31	va_end(p);
32
33	hv_store(hash, key, strlen(key), newSVpv(buffer, len), 0);
34}
35
36static double timeval_to_double(const struct timeval *tv) {
37	assert(tv != NULL);
38
39	return tv->tv_sec + tv->tv_usec * 1e-6;
40}
41
42static void fetch_getrusage(HV *hash, int who) {
43	struct rusage res;
44
45	assert(hash != NULL);
46	assert(who == RUSAGE_SELF || who == RUSAGE_CHILDREN);
47
48	if(syscall(getrusage(who, &res)) >= 0) {
49		STORE_TIMEVAL(ru_utime); /* leserlich etwas harmonieren^^ */
50		STORE_TIMEVAL(ru_stime);
51
52		STORE_FIELD("%ld", ru_maxrss);
53		STORE_FIELD("%ld", ru_ixrss);
54		STORE_FIELD("%ld", ru_idrss);
55		STORE_FIELD("%ld", ru_isrss);
56		STORE_FIELD("%ld", ru_minflt);
57		STORE_FIELD("%ld", ru_majflt);
58		STORE_FIELD("%ld", ru_nswap);
59		STORE_FIELD("%ld", ru_inblock);
60		STORE_FIELD("%ld", ru_oublock);
61		STORE_FIELD("%ld", ru_msgsnd);
62		STORE_FIELD("%ld", ru_msgrcv);
63		STORE_FIELD("%ld", ru_nsignals);
64		STORE_FIELD("%ld", ru_nvcsw);
65		STORE_FIELD("%ld", ru_nivcsw);
66	}
67}
68
69MODULE = Unix::Getrusage PACKAGE = Unix::Getrusage
70
71SV*
72getrusage()
73PREINIT:
74HV *hash;
75CODE:
76hash = newHV();
77fetch_getrusage(hash, RUSAGE_SELF);
78sv_2mortal((SV*) hash);
79RETVAL = newRV_inc((SV*)hash);
80OUTPUT:
81RETVAL
82
83SV*
84getrusage_children()
85PREINIT:
86HV *hash;
87CODE:
88hash = newHV();
89fetch_getrusage(hash, RUSAGE_CHILDREN);
90sv_2mortal((SV*) hash);
91RETVAL = newRV_inc((SV*)hash);
92OUTPUT:
93RETVAL
94