/* debug.h 

   Debugging defines and routines.
*/

#ifndef __DEBUG_H
#define __DEBUG_H

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

int getrusage(int who, struct rusage *rusage);

#define LOG_HANDLE stderr

/* None of the "hidden" macros should ever be called outside this file. 
   They are simply a convenience to facilitate turning certain macros off
   selectively. 
*/

/* This is highly machine dependent!!! */
#define TIMER_DURATION 1700L

#define HIDDEN_LOG_MESSAGE(X) fprintf(LOG_HANDLE,"%20s(%5d):%s\n",__FILE__,__LINE__,X)
#define HIDDEN_LOG_GCINFO(X) logGcInfo(X,0)
#define HIDDEN_LOG_GCINFO_EXHAUSTIVE(X) logGcInfo(X,1)

/* Optional should be for temporary code for testing purposes. */
#define HIDDEN_OPTIONAL(X) X
/* Stats should be used for statistics that we may or may not want to
   collect. */
#define HIDDEN_STATS(X) X

#ifdef FAST_CLOCK
#    define HIDDEN_DECL_TIMER(X) FastTimerInfo X 
#    define HIDDEN_START_TIMER(X) (X).start = gethrtime()
#    define HIDDEN_END_TIMER(X)   (X).end = gethrtime()

/* An accumulator is used to sum up several timers. */
#    define HIDDEN_DECL_ACCUM(X) hrtime_t X
#    define HIDDEN_INIT_ACCUM(X) (X) = 0L
#    define HIDDEN_ADD_ACCUM(A,X) (A) += ((X).end - (X).start)

#    define HIDDEN_FLOAT_ACCUM(A) ((A)/(1.0E9))

/* X = string, Y = accumulator */
#     define HIDDEN_LOG_ACCUM(X,Y) fprintf(LOG_HANDLE,"%20s:\t%7f\n", X, \
					   HIDDEN_FLOAT_ACCUM(Y))

#     define HIDDEN_LOG_TWOACCUM(X,Y) fprintf(LOG_HANDLE, \
					      "%7f\t%7f\n", \
					      HIDDEN_FLOAT_ACCUM(X), \
					      HIDDEN_FLOAT_ACCUM(Y))
/* X = string, Y = timer */
#      define HIDDEN_LOG_TIMER(X,Y) { \
                                     HIDDEN_DECL_ACCUM(t); \
				     HIDDEN_INIT_ACCUM(t); \
				     HIDDEN_ADD_ACCUM(t,Y); \
				     HIDDEN_LOG_ACCUM(X,t); \
                                     }

/* X = timer, A = accum */
#      define HIDDEN_LOG_TIMER_ACCUM(X,A){ \
                                     HIDDEN_DECL_ACCUM(t); \
				     HIDDEN_INIT_ACCUM(t); \
				     HIDDEN_ADD_ACCUM(t,X); \
				     HIDDEN_LOG_TWOACCUM(t,A); \
                                     }
 
#else
#    define HIDDEN_DECL_TIMER(X)  TimerInfo X
#    define HIDDEN_START_TIMER(X) startTimer(&(X))
#    define HIDDEN_END_TIMER(X)   endTimer(&(X))

/* An accumulator is used to sum up several timers. */
#    define HIDDEN_DECL_ACCUM(X) TimerInfo X
#    define HIDDEN_INIT_ACCUM(X) { (X).user=0.0; (X).system=0.0; (X).wall=0.0; }
#    define HIDDEN_ADD_ACCUM(A,X) { \
          A.user  += (X).user; \
          A.system+= (X).system; \
          A.wall  += (X).wall; \
          }

/* X = string, Y = accumulator */
#     define HIDDEN_LOG_ACCUM(X,Y) fprintf(LOG_HANDLE,"%20s(USW):%15f %15f %15f\n",\
				      X, Y.user, Y.system, Y.wall);

#     define HIDDEN_LOG_TWOACCUM(X,Y) fprintf(LOG_HANDLE, \
					 "%7f, %7f, %7f, %7f, %7f, %7f,\n",\
					 X.user, X.system, X.wall, \
					 Y.user, Y.system, Y.wall)


/* X = string, Y = timer */
#      define HIDDEN_LOG_TIMER(X,Y) HIDDEN_LOG_ACCUM(X,Y)
#      define HIDDEN_LOG_TIMER_ACCUM(X,A) HIDDEN_LOG_TWO_ACCUM(X,A)
#endif
/* Operations to perform on startup or shutdown for debugging purposes. */
#define HIDDEN_STARTUP gcStartup()
#define HIDDEN_SHUTDOWN gcShutdown()

/* Do not call any of the above ever!!!!! */

#define DECL_TIMER_ALWAYS(X) HIDDEN_DECL_TIMER(X)
#define START_TIMER_ALWAYS(X) HIDDEN_START_TIMER(X)
#define END_TIMER_ALWAYS(X) HIDDEN_END_TIMER(X)

#define DECL_ACCUM_ALWAYS(X) HIDDEN_DECL_ACCUM(X)
#define INIT_ACCUM_ALWAYS(X) HIDDEN_INIT_ACCUM(X)
#define ADD_ACCUM_ALWAYS(A,X) HIDDEN_ADD_ACCUM(A,X)

#define LOG_ACCUM_ALWAYS(X,Y) HIDDEN_LOG_ACCUM(X,Y)
#define LOG_TWOACCUM_ALWAYS(X,Y) HIDDEN_LOG_TWOACCUM(X,Y)
#define LOG_TIMER_ACCUM_ALWAYS(X,A) HIDDEN_LOG_TIMER_ACCUM(X,A)

/* X = string, Y = timer */
#define LOG_TIMER_ALWAYS(X,Y) HIDDEN_LOG_TIMER(X,Y)

#define LOG_MESSAGE_ALWAYS(X) HIDDEN_LOG_MESSAGE(X)

#define SHUTDOWN_ALWAYS HIDDEN_SHUTDOWN

#ifdef LOGGING
#       define LOG_MESSAGE(X) HIDDEN_LOG_MESSAGE(X)
#       define LOG_GCINFO(X) HIDDEN_LOG_GCINFO(X)
#       define LOG_GCINFO_EXHAUSTIVE(X) HIDDEN_LOG_GCINFO_EXHAUSTIVE(X)
#       define OPTIONAL(X) HIDDEN_OPTIONAL(X)
#       define STATS(X) HIDDEN_STATS(X)
#       define DECL_TIMER(X) HIDDEN_DECL_TIMER(X)
#       define START_TIMER(X) HIDDEN_START_TIMER(X)
#       define END_TIMER(X)   HIDDEN_END_TIMER(X)
#       define DECL_ACCUM(X) HIDDEN_DECL_ACCUM(X)
#       define INIT_ACCUM(X) HIDDEN_INIT_ACCUM(X)
#       define ADD_ACCUM(A,X) HIDDEN_ADD_ACCUM(A,X)
#       define LOG_ACCUM(X,Y) HIDDEN_LOG_ACCUM(X,Y)
#       define LOG_TIMER(X,Y) HIDDEN_LOG_TIMER(X,Y)
#       define LOG_TWOACCUM(X,Y) HIDDEN_LOG_TWO_ACCUM(X,Y)
#       define LOG_TIMER_ACCUM(X,A) HIDDEN_LOG_TIMER_ACCUM(X,A)
#       define STARTUP HIDDEN_STARTUP
#       define SHUTDOWN HIDDEN_SHUTDOWN
#else
#       define LOG_MESSAGE(X)
#       define LOG_GCINFO(X)
#       define LOG_GCINFO_EXHAUSTIVE(X)
#       define OPTIONAL(X)
#       define STATS(X)
#       define DECL_TIMER(X)
#       define START_TIMER(X)
#       define END_TIMER(X)
#       define DECL_ACCUM(X,Y)
#       define INIT_ACCUM(X)
#       define ADD_ACCUM(A,X)
#       define LOG_ACCUM(X,Y)
#       define LOG_TIMER(X,Y)
#       define LOG_TIMER_ACCUM(X,A)
#       define STARTUP
#       define SHUTDOWN
#endif
typedef struct
{
  double user;
  double system;
  double wall;
} TimerInfo;

typedef struct
{
  hrtime_t start;
  hrtime_t end;
} FastTimerInfo;

double getTime(void);
void startTimer(TimerInfo *ti);
void endTimer(TimerInfo *ti);

void logGcInfo(char *title, int exhaustive);

void gcStartup(void);
void gcShutdown(void);

#endif

/* EOF: debug.h */

/* (c) Frederick Smith, Greg Morrisett.
 *     October 1998, all rights reserved.
 *
 *
 *              Copyright 1990-1993 Digital Equipment Corporation
 *                         All Rights Reserved
 *
 * Permission to use, copy, and modify this software and its documentation is
 * hereby granted only under the following terms and conditions.  Both the
 * above copyright notice and this permission notice must appear in all copies
 * of the software, derivative works or modified versions, and any portions
 * thereof, and both notices must appear in supporting documentation.
 *
 * Users of this software agree to the terms and conditions set forth herein,
 * and hereby grant back to Digital a non-exclusive, unrestricted, royalty-free
 * right and license under any changes, enhancements or extensions made to the
 * core functions of the software, including but not limited to those affording
 * compatibility with other hardware or software environments, but excluding
 * applications which incorporate this software.  Users further agree to use
 * their best efforts to return to Digital any such changes, enhancements or
 * extensions that they make and inform Digital of noteworthy uses of this
 * software.  Correspondence should be provided to Digital at:
 * 
 *                       Director of Licensing
 *                       Western Research Laboratory
 *                       Digital Equipment Corporation
 *                       250 University Avenue
 *                       Palo Alto, California  94301  
 * 
 * This software may be distributed (but not offered for sale or transferred
 * for compensation) to third parties, provided such third parties agree to
 * abide by the terms and conditions of this notice.  
 * 
 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
 * SOFTWARE.
 */
