/*
 * Note: Perl5 extension.
 * Extended by Ikuo Nakagawa.
 */
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <unistd.h>

/*
 */
typedef struct rusage Usage;

#ifdef XS_VERSION
#ifdef __cplusplus
extern "C" {
#endif
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#ifdef __cplusplus
}
#endif
#endif /* XS_VERSION */

static int
not_here(s)
char *s;
{
    croak("%s not implemented on this architecture", s);
    return -1;
}

static double
constant(name, arg)
char *name;
int arg;
{
    errno = 0;
    switch (*name) {
    case 'R':
	if (strEQ(name, "RUSAGE_SELF"))
	    return RUSAGE_SELF;
	if (strEQ(name, "RUSAGE_CHILDREN"))
	    return RUSAGE_CHILDREN;
	break;
    }
    errno = EINVAL;
    return 0;

not_there:
    errno = ENOENT;
    return 0;
}

MODULE = Fan::Usage	PACKAGE = Fan::Usage

Usage *
getrusage(who = RUSAGE_SELF)
	int who
    PROTOTYPE: ;$
    CODE:
	{
	    SV *sv = perl_get_sv("Fan::Usage::LOG", FALSE);
	    int log = sv ? SvIV(sv) : NULL;

	    if (!(RETVAL = malloc(sizeof(Usage))))
		XSRETURN_UNDEF;

	    if (getrusage(who, RETVAL) < 0) {
		free(RETVAL);
		XSRETURN_UNDEF;
	    }
	    if (log > 5) {
		printf("Fan::Usage CREATING = %p\n", RETVAL);
		fflush(stdout);
	    }
	    ST(0) = sv_newmortal();
	    sv_setref_pv(ST(0), "UsagePtr", (void*)RETVAL);
	}

MODULE = Fan::Usage	PACKAGE = UsagePtr

void
DESTROY(data)
	Usage *data;
    PROTOTYPE: $
    CODE:
	{
	    SV *sv = perl_get_sv("Fan::Usage::LOG", FALSE);
	    int log = sv ? SvIV(sv) : 5;

	    if (log > 5) {
		printf("Fan::Usage DESTROYING = %p\n", data);
		fflush(stdout);
	    }
	    free(data);
	}

double
ru_utime(data)
	Usage *		data
    PROTOTYPE: $
    CODE:
	{
	    RETVAL = (double)data->ru_utime.tv_sec
			+ (double)data->ru_utime.tv_usec / 1000000.0;
	}
    OUTPUT:
    RETVAL

double
ru_stime(data)
	Usage *		data
    PROTOTYPE: $
    CODE:
	{
	    RETVAL = (double)data->ru_stime.tv_sec
			+ (double)data->ru_stime.tv_usec / 1000000.0;
	}
    OUTPUT:
    RETVAL

long
ru_maxrss(data)
	Usage *		data
    PROTOTYPE: $
    CODE:
	{
	    RETVAL = data->ru_maxrss;
	}
    OUTPUT:
    RETVAL

long
ru_ixrss(data)
	Usage *		data
    PROTOTYPE: $
    CODE:
	{
	    RETVAL = data->ru_ixrss;
	}
    OUTPUT:
    RETVAL

long
ru_idrss(data)
	Usage *		data
    PROTOTYPE: $
    CODE:
	{
	    RETVAL = data->ru_idrss;
	}
    OUTPUT:
    RETVAL

long
ru_isrss(data)
	Usage *		data
    PROTOTYPE: $
    CODE:
	{
	    RETVAL = data->ru_isrss;
	}
    OUTPUT:
    RETVAL

long
ru_minflt(data)
	Usage *		data
    PROTOTYPE: $
    CODE:
	{
	    RETVAL = data->ru_minflt;
	}
    OUTPUT:
    RETVAL

long
ru_majflt(data)
	Usage *		data
    PROTOTYPE: $
    CODE:
	{
	    RETVAL = data->ru_majflt;
	}
    OUTPUT:
    RETVAL

long
ru_nswap(data)
	Usage *		data
    PROTOTYPE: $
    CODE:
	{
	    RETVAL = data->ru_nswap;
	}
    OUTPUT:
    RETVAL

long
ru_inblock(data)
	Usage *		data
    PROTOTYPE: $
    CODE:
	{
	    RETVAL = data->ru_inblock;
	}
    OUTPUT:
    RETVAL

long
ru_oublock(data)
	Usage *		data
    PROTOTYPE: $
    CODE:
	{
	    RETVAL = data->ru_oublock;
	}
    OUTPUT:
    RETVAL

long
ru_msgsnd(data)
	Usage *		data
    PROTOTYPE: $
    CODE:
	{
	    RETVAL = data->ru_msgsnd;
	}
    OUTPUT:
    RETVAL

long
ru_msgrcv(data)
	Usage *		data
    PROTOTYPE: $
    CODE:
	{
	    RETVAL = data->ru_msgrcv;
	}
    OUTPUT:
    RETVAL

long
ru_nsignals(data)
	Usage *		data
    PROTOTYPE: $
    CODE:
	{
	    RETVAL = data->ru_nsignals;
	}
    OUTPUT:
    RETVAL

long
ru_nvcsw(data)
	Usage *		data
    PROTOTYPE: $
    CODE:
	{
	    RETVAL = data->ru_nvcsw;
	}
    OUTPUT:
    RETVAL

long
ru_nivcsw(data)
	Usage *		data
    PROTOTYPE: $
    CODE:
	{
	    RETVAL = data->ru_nivcsw;
	}
    OUTPUT:
    RETVAL

long
clk_tck(data)
	Usage *		data
    PROTOTYPE: $
    CODE:
	{
	    RETVAL = sysconf(_SC_CLK_TCK);
	}
    OUTPUT:
    RETVAL
