/**********************************************************************
 * Copyright (c) 2005, 2009 IBM Corporation and others.
 * All rights reserved.   This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * $Id: performance.h,v 1.5 2009/08/26 14:59:53 jwest Exp $
 * 
 * Contributors: 
 * IBM - Initial API and implementation
 * Spundun Bhatt (spundun@gmail.com), with the support and encouragement of the University of Southern California Information Sciences Institute Distributed Scalable Systems Division.
 **********************************************************************/

#ifndef _PERFORMANCE_H_
#define _PERFORMANCE_H_

#include "RAComm.h"

#if defined __cplusplus
 extern "C" {
#endif

#ifdef __cplusplus
  #ifdef MVS
    #define _inline inline
  #endif
#else
  #ifdef MVS
    #define _inline
  #endif
#endif

#ifdef _HPUX
 #define _inline
#elif __linux__
 #include <stdint.h>
 #define _inline inline
#elif __APPLE__
 #define _inline
#elif _SOLARIS
 #define _inline
#elif _AIX
 #define _inline
#elif __OS400__
 #define _inline
#endif

#ifdef _SOLARIS
 #ifndef _UINT64_T
  #define _UINT64_T
  /*typedef unsigned long long Uint64;*/
/*  typedef unsigned long long uint64_t; */
 #endif
#endif

#ifdef _WIN32
 typedef unsigned __int64  Uint64;
#else
 #ifdef MVS
  /* 189110 - uint64_t is now defined on MVS but not as long long so we won't use it here */
  typedef unsigned long long Uint64;
 #elif __OS400__
  typedef unsigned long long Uint64;
 #elif _HPUX
   typedef unsigned long long Uint64;
 #else
  typedef uint64_t Uint64;
 #endif
#endif


/* typedef int	*atomic_p; */

/** The goal of this file is to define some inline performance code
  * for doing metrics on each of the processors supported.
  */
typedef Uint64 timestamp_t;

extern unsigned int _ticksPerMicrosecond;
extern double       _startTimeAsDouble;
extern timestamp_t  _startTimeAsTicks;
extern timestamp_t _startTime;

extern void determineTicksPerMicrosecond(int *bogus);


static _inline timestamp_t timeToTicks(Uint64 seconds, Uint64 microsecondsRemainder) {
  timestamp_t ticks;
  Uint64 microseconds = seconds;
  microseconds *= 1000000;
  microseconds += microsecondsRemainder;

  ticks =  microseconds * _ticksPerMicrosecond;
  return ticks;
}

static _inline double ticksToTime2(timestamp_t timestampInTicks, BOOL asInterval) {
  double microseconds = (double)(
#ifdef WIN32
				 (__int64)
#endif /* WIN32 */
				 timestampInTicks) / _ticksPerMicrosecond;
  if(asInterval) {
    return microseconds/1000000;
  }
  else {
    return microseconds/1000000 + _startTimeAsDouble;
  }
}
#define TIMESTAMP_GREATER(A,B) ((A)>(B))
#define TIMESTAMP_ADD(A,B) A=(A)+(B)
#define TIMESTAMP_ZERO(A) (*(A)) = 0
static _inline timestamp_t TIMESTAMP_SUB(timestamp_t A, timestamp_t B) {
  return A-B;
}


/** COLLECT_START_TIME_INFORMATION  *******************************************
  * Initialization routine for future use of jvmpiAgent_getCurrentTime().
  * This routine records the time at which this function was called and uses
  * this time to determine what the current time is.
  */
extern void jvmpiAgent_collectStartTimeInformation();

/* GET_START_TIME  ************************************************************
 * Returns a copy of the start time that was recorded with
 * jvmpiAgent_collectStartTimeInformation
 */
extern void jvmpiAgent_getStartTime(timestamp_t *time);

/* GET_CURRENT_TIME  **********************************************************
 * Determins the current clock time and fills the timestamp_t structure
 * with the data
 */
extern void jvmpiAgent_getCurrentTime(timestamp_t *time);

/** GET_CURRENT_THREAD_CPU_TIME  ***********************************************
  * Returns the amount of CPU time consumed by this thread as a 64 bit number.
  */
extern Uint64 jvmpiAgent_getCurrentThreadCPUTime();

/** GET_PROCESS_START_TIME  ***************************************************
  *  Returns the start time of the current process as a timestamp_t in UTC time.
  */
extern void jvmpiAgent_getProcessStartTime(timestamp_t *time);

/** GET_TIMEZONE  *************************************************************
  * Returns the current timezone as an offset, in minutes, working westward from
  * GMT.  ie.  GMT+5  would be 300 as there are 300 minutes in 5 hours.
  */
extern unsigned long jvmpiAgent_getTimezone();

/*********************************************************
 * DEBUG assists:
 */
#if defined(_DEBUG) && !defined (MVS) && !defined (__OS400__)
extern void debug_check_and_report_time_overflow(timestamp_t time, char *errMsg);  /* 134577 */
#define DBG_CHK_AND_REPORT_TIME_OVERFLOW(A,B) debug_check_and_report_time_overflow(A,B)
#else
#define DBG_CHK_AND_REPORT_TIME_OVERFLOW(A,B) 
#endif

#if defined __cplusplus
}
#endif

#endif
