/******************************************************************************
 * This file is part of a software distribution, which is furnished under the *
 * terms of a license.  Use of this software  by any means is subject to this *
 * license  and  signifies  the  acceptance of  the  licensing  terms  stated *
 * therein. Please see  the file LICENSE in the  top-level directory  of this *
 * software  distribution  for detailed copyright  disclaimers  and licensing *
 * terms.                                                                     *
 ******************************************************************************
 * Copryight (c) by Andreas S. Wetzel - All rights reserved.                  *
 ******************************************************************************/

/* $Id: microtime.c,v 1.2 2001/03/19 14:54:01 mickey Exp $ */

#include <vchat.h>
#include <proto_common.h>

/*** Globals ***/

TMSTAT tmstat;

/*** Code ***/

void timestamp(struct timeval *tm)
{
	struct timezone tz;

	gettimeofday(tm, &tz);
}

void store_tm_value(struct timeval *tp)
{
		memmove(&tmstat.statvalue[1], &tmstat.statvalue[0], ((NUMSTATS - 1) * sizeof(struct timeval)));
		BCOPY(tp, &tmstat.statvalue[0], sizeof(struct timeval));
		tmstat.statindex += (tmstat.statindex < NUMSTATS) ? 1 : 0;
}

char *pr_time(struct timeval *tm)
{
	#define NUMPRBUFS 5

	static int index = 0;
	static char tstr[NUMPRBUFS * 64];
	static char *tptr;

	tptr = (char *)&tstr[(((index < (NUMPRBUFS - 1)) ? ++index : (index = 0)) * 64)];
	
	sprintf(tptr, "%.3f ms", ((double)tm->tv_usec / 1000) + (tm->tv_sec * 1000));

	return(tptr);
}

TMREPORT *report_stat(void)
{
	static TMREPORT tmr;

	int i;

	tmr._min.tv_sec = tmr._min.tv_usec = (tmstat.statindex) ? 0x7fffffff : 0;
	tmr._avg.tv_sec = tmr._avg.tv_usec = 0;
	tmr._max.tv_sec = tmr._max.tv_usec = 0;

	for(i = 0; i < tmstat.statindex; i++)
	{
		if(timercmp(&tmstat.statvalue[i], &tmr._min, <))
			BCOPY(&tmstat.statvalue[i], &tmr._min, sizeof(struct timeval));

		if(timercmp(&tmstat.statvalue[i], &tmr._max, >))
			BCOPY(&tmstat.statvalue[i], &tmr._max, sizeof(struct timeval));

		push_value(&tmstat.statvalue[i], &tmr._avg);
	}

	if(tmstat.statindex)
		avgvalue(&tmr._avg);

	return(&tmr);
}

struct timeval *diff_t(struct timeval *t1, struct timeval *t2)
{
	static struct timeval tm_ret;

	if(t1->tv_sec == t2->tv_sec)
	{
		tm_ret.tv_sec = 0;
		tm_ret.tv_usec = (t2->tv_usec - t1->tv_usec);
	}
	else
	{
		if(t2->tv_usec > t1->tv_usec)
		{
			tm_ret.tv_sec = (t2->tv_sec - t1->tv_sec);
			tm_ret.tv_usec = (t2->tv_usec - t1->tv_usec);
		}
		else
		{
			tm_ret.tv_sec = (t2->tv_sec - t1->tv_sec - 1);
			tm_ret.tv_usec = (1000000 - (t1->tv_usec - t2->tv_usec));
		}
	}

	return(&tm_ret);
}


void push_value(struct timeval *srctp, struct timeval *stacktp)
{
	u_long usec;

	if((usec = (stacktp->tv_usec + srctp->tv_usec)) > 1000000)
	{
		stacktp->tv_sec += (srctp->tv_sec + 1);
		stacktp->tv_usec = (usec - 1000000);
	}
	else
	{
		stacktp->tv_sec += srctp->tv_sec;
		stacktp->tv_usec = usec;
	}
}

void avgvalue(struct timeval *pt)
{
	struct timeval tmp;
	double seconds;

	seconds = ((double)pt->tv_sec / tmstat.statindex);

	tmp.tv_sec = (u_long)seconds;

	seconds -= tmp.tv_sec;

	tmp.tv_usec = (seconds * 1000000);
	tmp.tv_usec += (pt->tv_usec / tmstat.statindex);

	pt->tv_sec = tmp.tv_sec;
	pt->tv_usec = tmp.tv_usec;
}

void clear_tm_stats(void)
{
	BZERO(&tmstat.statvalue[0], (NUMSTATS * sizeof(struct timeval)));
	tmstat.statindex = 0;
}


syntax highlighted by Code2HTML, v. 0.9.1