/****************************************************************************
 *                                                                          *
 * The contents of this file are subject to the WebStone Public License     *
 * Version 1.0 (the "License"); you may not use this file except in         *
 * compliance with the License. You may obtain a copy of the License        *
 * at http://www.mindcraft.com/webstone/license10.html                      *
 *                                                                          *
 * Software distributed under the License is distributed on an "AS IS"      *
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See      *
 * the License for the specific language governing rights and limitations   *
 * under the License.                                                       *
 *                                                                          *
 * The Original Code is WebStone 2.5.                                       *
 *                                                                          *
 * The Initial Developer of the Original Code is Silicon Graphics, Inc.     *
 * and Mindcraft, Inc.. Portions created by Silicon Graphics. and           *
 * Mindcraft. are Copyright (C) 1995-1998 Silicon Graphics, Inc. and        *
 * Mindcraft, Inc. All Rights Reserved.                                     *
 *                                                                          *
 * Contributor(s): ______________________________________.                  *
 *                                                                          *
 * @(#) bench.c 2.4@(#)                                                     *
 ***************************************************************************/


#ifdef USE_WEBSTONE20_GETTIMEOFDAY
/*
 *  This file defines functions that are required for unix compatibility.
 *
 *  These functions are not available in the Microsoft C/C++ Run Time 
 *  and the Win32 API.
 *
 *  The following functions list may not be complete
 *  
 *  FUNCTIONS:
 *     SHARED   _gettimeofday
 *
 */


#include <windows.h>
#include <errno.h>
#include <winsock.h>		/* For definition of "timeval" structure */
#include <sys/timeb.h>		/* For prototype of "_ftime()" */


/*
 * gettimeofday() --  gets the current time in elapsed seconds and
 *                     microsends since GMT Jan 1, 1970.
 *
 * ARGUMENTS: - Pointer to a timeval struct to return the time into
 *
 * RETURN CODES: -  0 on success
 *                 -1 on failure
 */
int gettimeofday(curTimeP)
    struct timeval *curTimeP;
{
struct _timeb  localTime;

    if (curTimeP == (struct timeval *) NULL) {
	 errno = EFAULT;
	 return (-1);
    }

   /*
    *  Compute the elapsed time since Jan 1, 1970 by first
    *  obtaining the elapsed time from the system using the
    *  _ftime(..) call and then convert to the "timeval"
    *  equivalent.
    */

    _ftime(&localTime);

    curTimeP->tv_sec  = localTime.time + localTime.timezone;
    curTimeP->tv_usec = localTime.millitm * 1000;

    return(0);
}

#else
/*
 *      Copyright (c) 1994 Intel Corporation.
 *      All Rights Reserved
 */


/*
 *  This file defines functions that are required for unix compatibility.
 *
 *  These functions are not available in the Microsoft C/C++ Run Time
 *  and the Win32 API.
 *
 *  The following functions list may not be complete
 *
 *  FUNCTIONS:
 *     SHARED   _gettimeofday
 *
 */


#include <windows.h>
#include <errno.h>
#include <winsock.h>            /* For definition of "timeval" structure */
#include <sys/timeb.h>          /* For prototype of "_ftime()" */
#include <stdio.h>

/*
 * gettimeofday() --  gets the current time in elapsed seconds and
 *                     microsends since GMT Jan 1, 1970.
 *
 * ARGUMENTS: - Pointer to a timeval struct to return the time into
 *
 * RETURN CODES: -  0 on success
 *                 -1 on failure
 */
#ifdef GETTIMEOFDAY_FTIME

int gettimeofday(curTimeP)//, tzone)
    struct timeval *curTimeP;
 //   struct timezone *tzone; /* DEC DCE - this param is currently a dummy */
{

   struct _timeb  localTime;


   if (curTimeP == (struct timeval *) NULL) {
     errno = EFAULT;
     return (-1);
   }


   /*
    *  Compute the elapsed time since Jan 1, 1970 by first
    *  obtaining the elapsed time from the system using the
    *  _ftime(..) call and then convert to the "timeval"
    *  equivalent.
    */

    _ftime(&localTime);

    curTimeP->tv_sec  = localTime.time + localTime.timezone;
    curTimeP->tv_usec = localTime.millitm * 1000;

    return(0);
}

#else

static struct _timeb startTOD;
LARGE_INTEGER        startCount, Freq;

#define MILLION 1000000

int init_gettimeofday() {
    _ftime(&startTOD);

    // This should be more graceful, if the init_gettimeofday call checks
    // then we can just make it return a non-zero value

    if (QueryPerformanceFrequency( &Freq ) == FALSE) {
        printf("This machine does not support QueryPerformanceCounter\n");
        exit (1);
    }

    QueryPerformanceCounter (&startCount);
    return 0;
}



int gettimeofday(struct timeval *curTimeP) {
   LARGE_INTEGER Count;

   if (curTimeP == (struct timeval *) NULL) {
        errno = EFAULT;
        return (-1);
   }


   /*
    *  Compute the elapsed time since Jan 1, 1970 by first
    *  obtaining the elapsed time from the system using the
    *  _ftime(..) call and then convert to the "timeval"
    *  equivalent.
    */

    curTimeP->tv_sec  = startTOD.time + startTOD.timezone;
    curTimeP->tv_usec = startTOD.millitm * 1000;

   /*
    *  Now add in the elapsed time from start of run
    */

    QueryPerformanceCounter (&Count);

    // This could be more graceful as well, but on my P90 it will only
    // overflow once every ~500000 years.  Hopefully this will hold true
    // but in case it doesn't...

    if (Count.QuadPart < startCount.QuadPart) {
        printf("Performance counter overflow\n");
        exit (1);
    }


    Count.QuadPart -= startCount.QuadPart; // make this the delta time
    curTimeP->tv_usec += (long)((Count.QuadPart % Freq.QuadPart) *
                                MILLION / Freq.QuadPart);
    curTimeP->tv_sec  += (long)(Count.QuadPart / Freq.QuadPart);
    if (curTimeP->tv_usec >= MILLION) {
        curTimeP->tv_sec  += curTimeP->tv_usec / MILLION;
        curTimeP->tv_usec %= MILLION;
    }
    return(0);
}

#endif /* GETTIMEOFDAY_FTIME */
#endif /* USE_WEBSTONE20_GETTIMEOFDAY */
