/*
    timer.cc

    CPU time measurement

    2.4.2001

    Copyright (C) 1997-2001 by Josef Pelikan, MFF UK Prague
        http://sun3.ms.mff.cuni.cz/~pepca/

    VUCAKO Bench is Open Source software (see http://www.opensource.org/
    for description what Open Source is); you may distributed it and/or
    modify it under the terms of GNU General Public License as published
    by the Free Software Foundation; either version 2, or (at your option)
    any later version.

    This program is distributed in the hope that it will be useful, but
    WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    General Public License for more details.

    A copy of the GNU General Public License is available as
    `/usr/doc/copyright/GPL' in the Debian GNU/Linux distribution or on
    the World Wide Web at http://www.gnu.org/copyleft/gpl.html.  You can
    also obtain it by writing to the Free Software Foundation, Inc., 59
    Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/

#include "pch.h"

int kernelTime = 0;             // used kernel time in milliseconds
int userTime;                   // used user time in milliseconds
int realTime;                   // real elapsed time in milliseconds

#ifdef WIN32

//-----------------------------------------------------------
//  WIN32 API:

#include <sys/timeb.h>
#include <windows.h>

FILETIME kernel, user;
static struct _timeb startTime;

void startTimer ()
{
    FILETIME dummy;
    GetProcessTimes(GetCurrentProcess(),&dummy,&dummy,&kernel,&user);
    _ftime(&startTime);
}

int elapsedTime ()              // returns total CPU time in milliseconds
{
    FILETIME dummy, nowkernel, nowuser;
    BOOL NT = GetProcessTimes(GetCurrentProcess(),&dummy,&dummy,&nowkernel,&nowuser);
    struct _timeb now;
    _ftime(&now);
    realTime = (now.time - startTime.time) * 1000 + now.millitm - startTime.millitm;
    if ( NT ) {
        long low = (long)nowkernel.dwLowDateTime - (long)kernel.dwLowDateTime;
        long high = (long)nowkernel.dwHighDateTime - (long)kernel.dwHighDateTime;
        kernelTime = (int)( ((high<<28) + (low>>4)) / 625 );
        low = (long)nowuser.dwLowDateTime - (long)user.dwLowDateTime;
        high = (long)nowuser.dwHighDateTime - (long)user.dwHighDateTime;
        userTime = (int)( ((high<<28) + (low>>4)) / 625 );
        return( realTime );
        }
    return( userTime = realTime );
}

#else       // WIN32

//-----------------------------------------------------------
//  UNIX:

#ifdef BSD_COMPATIBLE

//-----------------------------------------------------------
//  BSD, Linux:

#include <sys/time.h>
#include <sys/resource.h>

#ifdef FTIME

#include <sys/timeb.h>
static struct timeb startTime;

#else       // FTIME

#include <unistd.h>
static struct timeval startTime;

#endif      // FTIME

static struct rusage startUsage;

void startTimer ()
{
    getrusage(RUSAGE_SELF,&startUsage);
#ifdef FTIME
    ftime(&startTime);
#else
    gettimeofday(&startTime,0);
#endif
}

int elapsedTime ()              // returns total CPU time in milliseconds
{
    struct rusage usage;
    getrusage(RUSAGE_SELF,&usage);
#ifdef FTIME
    struct timeb now;
    ftime(&now);
    realTime = (now.time - startTime.time) * 1000 + now.millitm - startTime.millitm;
#else       // FTIME
    struct timeval now;
    gettimeofday(&now,0);
    realTime = (now.tv_sec - startTime.tv_sec) * 1000 + (now.tv_usec - startTime.tv_usec) / 1000;
#endif      // FTIME
    userTime = (usage.ru_utime.tv_sec - startUsage.ru_utime.tv_sec) * 1000 +
            (usage.ru_utime.tv_usec - startUsage.ru_utime.tv_usec) / 1000;
    kernelTime = (usage.ru_stime.tv_sec - startUsage.ru_stime.tv_sec) * 1000 +
            (usage.ru_stime.tv_usec - startUsage.ru_stime.tv_usec) / 1000;
    return( realTime );
}

#else       // BSD

//-----------------------------------------------------------
//  SVR4, Solaris:

#include <sys/times.h>
#include <limits.h>
#include <unistd.h>

static clock_t startTime;
static struct tms startUsage;

void startTimer ()
{
    startTime = times(&startUsage);
}

int elapsedTime ()              // returns total CPU time in seconds
{
    struct tms stopUsage;
    clock_t stopTime = times(&stopUsage);
    userTime = ((stopUsage.tms_utime + stopUsage.tms_cutime -
                startUsage.tms_utime - startUsage.tms_cutime) * 1000) / CLK_TCK;
    kernelTime = ((stopUsage.tms_stime + stopUsage.tms_cstime -
                  startUsage.tms_stime - startUsage.tms_cstime) * 1000) / CLK_TCK;
    realTime = ((stopTime - startTime) * 1000) / CLK_TCK;
    return( realTime );
}

#endif      // BSD_COMPATIBLE

#endif      // WIN32
