/* *******************************************************************
 * ports_clocktimer.h : PORTS Version 1.8 Clock and Timer Module
 * **************************************************************** */

/* *******************************************************************
 * This file describes a set of functions and types for a PORTS
 * clock and timer package (CLOCKTIMER).  The purpose of the specification is to
 * provide a standardized interface to the various clocks on a wide
 * variety of architectures.  This implementation guarantees that Wall
 * Clock will be available for each machine, and therefore has a
 * specially named interface.  No other clocks are standarized, and
 * their availability will be machine dependant.
 * 
 * The standard wall clock should be implemented using the high
 * resolution, synchronized clock available on many SMP and MPP
 * machines.  Some machines have no special, accurate, or synchronized
 * clock.  For those machines, standard UNIX function calls should be
 * used.
 *
 * The timer package should be thread safe, but not thread aware.  In
 * other words, a correct implementation of this specification can be
 * used in a preemptive thread environment, however the specification
 * does not require threads.  The following macros, defined by other
 * packages, can be used to determine if there are thread safety
 * issues.  
 *     PORTS_MULTITHREADED 
 *     PORTS_PREEMPTIVE
 *
 * Timers for event logging must be extremely fast.  Often, they can
 * be macros, and avoid a function call. Some of the interfaces
 * (especially PORTS_TimerStart, PORTS_TimerStop, and PORTS_Clock)
 * described below may be expanded into macros for some implementations.
 *
 * Pete Beckman (beckman@cs.indiana.edu)
 * Bernd Mohr (mohr@cs.uoregon.edu)
 ****************************************************************** */

#ifndef PORTS_CLOCKTIMER_H
#define PORTS_CLOCKTIMER_H

/* Error Codes for return values from timer functions */
#define PORTS_CLOCKTIMER_SUCCESS 0    /* Success */
#define PORTS_CLOCKTIMER_ERROR   1    /* Unspecified Error */
#define PORTS_CLOCKTIMER_NONE    2    /* No such timer, or illegal timer */

/* Attributes for clocks (implemented as bitmasks */
#define PORTS_CLOCKTIMER_SYNCHRONIZED   0x01
#define PORTS_CLOCKTIMER_WALL           0x02
#define PORTS_CLOCKTIMER_USER           0x04
#define PORTS_CLOCKTIMER_SYS            0x08
#define PORTS_CLOCKTIMER_PERTHREAD      0x10

/* predefined clock / timer sorts           */
/* more sorts will be defined in the future */
#define PORTS_WALL_CLK        0

/* *******************************************************************
 * macro definitions
 * **************************************************************** */

/* -------------------------------------------------------------------
 * For user convenience we define the WallClock and WallTimer functions
 * ---------------------------------------------------------------- */
#define PORTS_WallClock_t           PORTS_Clock_t(PORTS_WALL_CLK)
#define PORTS_WallTimer_t           PORTS_Timer_t(PORTS_WALL_CLK)
#define PORTS_WallTimerInit(t)      PORTS_TimerInit(PORTS_WALL_CLK,t)
#define PORTS_WallTimerDestroy(t)   PORTS_TimerDestroy(PORTS_WALL_CLK,t)
#define PORTS_WallTimerReset(t)     PORTS_TimerReset(PORTS_WALL_CLK,t)
#define PORTS_WallTimerStart(t)     PORTS_TimerStart(PORTS_WALL_CLK,t)
#define PORTS_WallTimerStop(t)      PORTS_TimerStop(PORTS_WALL_CLK,t)
#define PORTS_WallTimerElapsed(t,c) PORTS_TimerElapsed(PORTS_WALL_CLK,t,c)
#define PORTS_WallClock(c)          PORTS_Clock(PORTS_WALL_CLK,c)
#define PORTS_WallClockToSeconds(c) PORTS_ClockToSeconds(PORTS_WALL_CLK,c)

/* -------------------------------------------------------------------
 * The supplied "array" of clock and timers is actually implemented
 * as a set of separate functions for efficiency
 * ---------------------------------------------------------------- */
#define PORTS_MACRO_PASTE3(a,b,c) a##b##c
#define PORTS_Clock_t(i)          PORTS_MACRO_PASTE3(PORTS_Clock,i,_t)
#define PORTS_Timer_t(i)          PORTS_MACRO_PASTE3(PORTS_Timer,i,_t)
#define PORTS_TimerInit(i,t)      PORTS_MACRO_PASTE3(PORTS_TimerInit,i,(t))
#define PORTS_TimerDestroy(i,t)   PORTS_MACRO_PASTE3(PORTS_TimerDestroy,i,(t))
#define PORTS_TimerReset(i,t)     PORTS_MACRO_PASTE3(PORTS_TimerReset,i,(t))
#define PORTS_TimerStart(i,t)     PORTS_MACRO_PASTE3(PORTS_TimerStart,i,(t))
#define PORTS_TimerStop(i,t)      PORTS_MACRO_PASTE3(PORTS_TimerStop,i,(t))
#define PORTS_TimerElapsed(i,t,c) PORTS_MACRO_PASTE3(PORTS_TimerElapsed,i,(t,c))
#define PORTS_Clock(i,c)          PORTS_MACRO_PASTE3(PORTS_Clock,i,(c))
#define PORTS_ClockToSeconds(i,c) PORTS_MACRO_PASTE3(PORTS_ClockToSeconds,i,(c))

/* *******************************************************************
 * Type for returning info about used timer/clock.
 * **************************************************************** */
typedef struct {
  double resolution;    /* The resolution (in seconds) */
  double rollover;      /* The rollover point  (in seconds) */
  int attributes;       /* Attributes (see above) for the clock */
} PORTS_ClockTimerInfo_t;


/* -------------------------------------------------------------------
 * int PORTS_ClockTimerInit(int *argc, char **argv);
 * int PORTS_ClockTimerTerm();
 *
 * Initialize and terminate clock and timer package.  Calls to all
 * other functions in that package only return meaningful values
 * between the calls of the two functions below.
 * Both calls return a error code if there is a problem.
 *
 * All functions of the Timer and Clocks package as well as the Clock
 * and Timer type are parameterized with a number to allow access to
 * more than one clock sort. Due to the macro implementation, the
 * parameter MUST be a constant unsigned number and is noted as _NUM_
 * below. _NUM_ must follow the following expression:
 *
 *             0 <= _NUM_ < PORTS_Num_ClockTimer()
 * ---------------------------------------------------------------- */

/* *******************************************************************
 * The next functions are for timer (stopwatch) handling.
 *
 * The type "PORTS_Timer_t(_NUM_)" is defined to be this machine-specific,
 * natural datatype. Typical usage (example clock sort = 7):
 *
 *   PORTS_Timer_t(7) t;
 *   PORTS_TimerInit(7, t);
 *             |
 *    +------->+
 *    |        |
 *    |        v
 *    |     PORTS_TimerStart(7, t);
 *    |         ---- stuff to time here
 *    |     PORTS_TimerStop(7, t);
 *    |     printf ("time = %g\n", PORTS_TimerElapsed(7, t);
 *    |     PORTS_TimerReset(7, t);
 *    |        |
 *    +--------+
 *             |
 *             v
 *   PORTS_TimerDestroy(7, t);
 *
 * No conversion is performed on the raw clock/timer value.  Rather, a
 * function must be provided to do the conversion at some later time
 * (when displaying or analyzing the data).
 * **************************************************************** */

/* -------------------------------------------------------------------
 * int PORTS_Num_ClockTimer();
 *
 * Returns number of defined clock sorts
 * ---------------------------------------------------------------- */

/* -------------------------------------------------------------------
 * PORTS_ClockTimerInfo_t *PORTS_ClockTimerInfo(_NUM_);
 *
 * Get info about _NUM_-th timer/clock sort.
 * ---------------------------------------------------------------- */

/* -------------------------------------------------------------------
 * PORTS_TimerInit(_NUM_, PORTS_Timer_t(_NUM_) timer);
 * PORTS_TimerDestroy(_NUM_, PORTS_Timer_t(_NUM_) timer);
 *
 * PORTS_TimerInit(), PORTS_TimerDestroy : Initialize and destroy a
 * timer which uses the _NUM_-th clock.
 * Returns error code if necessary.
 *
 * PORTS_Timer_t(_NUM_) is system-dependent and will have fields to store a
 * clock value in the most "natural" way. Normalizing/conversion only
 * happens in the PORTS_TimerElapsed call.
 *
 * Data structure returned by Init may contain dynamically allocated
 * memory and therefore should be passed to Destroy for wrapup.
 * ---------------------------------------------------------------- */

/* -------------------------------------------------------------------
 * int PORTS_TimerReset(_NUM_, PORTS_Timer_t(_NUM_) timer);
 *
 * Reset and clear timer.  Returns error code.
 * ---------------------------------------------------------------- */

/* -------------------------------------------------------------------
 * void PORTS_TimerStart(_NUM_, PORTS_Timer_t(_NUM_) timer);
 *
 * Start the indicated timer.
 * ---------------------------------------------------------------- */

/* -------------------------------------------------------------------
 * void PORTS_TimerStop(_NUM_, PORTS_Timer_t(_NUM_) timer);
 *
 * Stop the indicated timer.
 * ---------------------------------------------------------------- */

/* -------------------------------------------------------------------
 * double PORTS_TimerElapsed(_NUM_, PORTS_Timer_t(_NUM_) timer, int *count);
 *
 * Elapsed time, in seconds.  Returns -1.0 on error.
 * The argument count (if non-null) is modified to indicate the
 * number of start/stop cycles.
 * ---------------------------------------------------------------- */

/* *******************************************************************
 * The next functions are for grabbing timestamps for tracing and
 * profiling.
 *
 * The type "PORTS_Clock_t" is defined to be this machine-specific,
 * natural datatype. Typical usage (example clock sort = 7):
 *
 *   PORTS_Clock_t(7) c;
 *   PORTS_Clock(7, c);
 *   printf ("time = %g\n", PORTS_ClockToSeconds(7, c);
 *
 * No conversion is performed on the raw clock value.  Rather, a
 * function must be provided to do the conversion at some later time
 * (when displaying or analyzing the data).
 * **************************************************************** */

/* -------------------------------------------------------------------
 * void PORTS_Clock(_NUM_, PORTS_Clock_t(_NUM_) clock);
 *
 * Return Clock without normalizing/conversion in natural format.
 * ---------------------------------------------------------------- */

/* -------------------------------------------------------------------
 * double PORTS_ClockToSeconds(_NUM_, PORTS_Clock_t(_NUM_) clock);
 *
 * Convert clock value to double with resolution seconds.
 * ---------------------------------------------------------------- */

/* -------------------------------------------------------------------
 * The next include file must be supplied by the specific
 * implementation which defines the machine-specific implementations
 * of the macros/functions explained above.
 * ---------------------------------------------------------------- */
#include "ports_sys_clocktimer.h"

#endif
