Main Page | Namespace List | Class Hierarchy | Class List | File List | Namespace Members | Class Members | File Members

instrumentation.h

Go to the documentation of this file.
00001 /*
00002  * instrumentation.h
00003  *
00004  * Copyright (c) 2003 The University of Utah and the Flux Group.
00005  * All rights reserved.
00006  *
00007  * This file is licensed under the terms of the GNU Public License.  
00008  * See the file "license.terms" for restrictions on redistribution 
00009  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
00010  */
00011 
00012 #ifndef _misc_instrumentation_h
00013 #define _misc_instrumentation_h
00014 
00015 /**
00016  * @file instrumentation.h
00017  *
00018  * Header file for instrumentation tools.  Instrumenting blocks of code or
00019  * expressions is done by adding a call to CB_INSTR_POINT in the configure.in
00020  * file and surrounding the code with a macro call.  For example, to do high
00021  * resolution timings of the following code:
00022  *
00023  * @code
00024  *   for( lpc = 0; lpc < 100; lpc++ )
00025  *   {
00026  *       ...
00027  *   }
00028  * @endcode
00029  *
00030  * You would modify the configure.in to include:
00031  *
00032  * @code
00033  *   CB_INSTR_POINT([my_point],
00034  *                  [HRTIME_INSTR],
00035  *                  [My instrumentation point])
00036  * @endcode
00037  *
00038  * Where 'my_point' is the name of the instrumentation point, HRTIME_INSTR is
00039  * the C macro that will record the timings, and 'My instrumentation point' is
00040  * the description of the point.  The result of this call will be two new
00041  * definitions in the config.h: 'INSTR_my_point' and 'INSTR_my_point_data'.
00042  * The first C macro is used to surround the code block and the second contains
00043  * the data used to initialize the instrumentation point structure (iPoint).
00044  * With these new definitions, we can modify our original code to add
00045  * instrumentation:
00046  *
00047  * @code
00048  *   #if defined(INSTR_my_point_data)
00049  *   static struct iPoint IP_my_point = {
00050  *       INSTR_my_point_data
00051  *   };
00052  *   #endif
00053  * ...
00054  *   INSTR_my_point(&IP_my_point, ({
00055  *       for( lpc = 0; lpc < 100; lpc++ )
00056  *       {
00057  *           ...
00058  *       }
00059  *   }));
00060  * @endcode
00061  *
00062  * (Notice the parentheses around the code block, these are required for things
00063  * to parse correctly.)
00064  *
00065  * Finally, to enable this instrumentation point, you either need to use
00066  * --enable-instrumentation to enable all of the points, or
00067  * --enable-instrumentation=my_point to enable only this point.
00068  *
00069  * @see configure.in
00070  * @see instrumentation_test.c
00071  */
00072 
00073 #ifdef __cplusplus
00074 extern "C" {
00075 #endif
00076 
00077 #include <stdio.h>
00078 #include <sys/time.h>
00079 
00080 /**
00081  * Container for low-resolution timer values.
00082  */
00083 typedef unsigned long long lrtime_t;
00084 
00085 /**
00086  * @return A low-resolution time stamp.  The current resolution is on the order
00087  * of milliseconds.
00088  */
00089 static inline lrtime_t lrtime(void);
00090 
00091 static inline lrtime_t lrtime(void)
00092 {
00093     struct timeval tv;
00094     lrtime_t retval;
00095     
00096     gettimeofday(&tv, 0);
00097     retval = (lrtime_t)tv.tv_usec / (lrtime_t)(1000);
00098     retval += ((lrtime_t)tv.tv_sec * (lrtime_t)(1000));
00099     return( retval );
00100 }
00101 
00102 /**
00103  * Container for high-resolution timer values.
00104  */
00105 typedef unsigned long long hrtime_t;
00106 
00107 /**
00108  * @return A high-resolution time stamp.
00109  */
00110 static inline hrtime_t hrtime(void);
00111 
00112 #if defined(i386)
00113 static inline hrtime_t hrtime(void)
00114 {
00115     unsigned long long retval;
00116     
00117     __asm__ __volatile__ ("rdtsc" : "=A" (retval) );
00118     return( retval );
00119 }
00120 #else
00121 #warning "CPU timestamp counter not available, using gettimeofday"
00122 static inline hrtime_t hrtime(void)
00123 {
00124     struct timeval tv;
00125     hrtime_t retval;
00126     
00127     gettimeofday(&tv, 0);
00128     retval = (hrtime_t)tv.tv_usec;
00129     retval += ((hrtime_t)tv.tv_sec * (hrtime_t)(1000 * 1000));
00130     return( retval );
00131 }
00132 #endif
00133 
00134 enum {
00135     IPB_DROP_HISTORY_START,
00136 };
00137 
00138 /*
00139  * IPF_DROP_HISTORY_START - Drop data values at the start of the history
00140  *   instead of the tail.
00141  */
00142 enum {
00143     IPF_DROP_HISTORY_START,
00144 };
00145 
00146 /*
00147  * ip_Name - The name of this instrumentation point.
00148  * ip_Description - A description of this instrumentation point, can be NULL.
00149  * ip_Flags - XXX
00150  * ip_History.data - An array that can contain atleast ip_History.length
00151  *   elements that should be used to record data values as they are posted.  If
00152  *   left NULL, the values won't be recorded and only statistics will be
00153  *   available.
00154  * ip_History.length - The maximum number of elements that can be placed in
00155  *   the 'data' array.
00156  * ip_History.start - The index where the oldest recorded value is in the
00157  *   'data' array.  Normally, this will be zero, unless the
00158  *   IPF_DROP_HISTORY_START flag is set and the 'data' array overflowed.
00159  * ip_History.lost - The number of data values that were not added to the
00160  *   'data' array because it overflowed.
00161  * ip_Format - The format to use when printing values.  If this is NULL, the
00162  *   default format, '%10.2f  ', is used.
00163  * ip_Count - The number of data values posted to this instrumentation point.
00164  * ip_Total - The sum of the data values posted.
00165  * ip_Minimum - The minimum observed data value that has been posted.
00166  * ip_Maximum - The maximum observed data value that has been posted.
00167  * ip_Succ - Link to the next instrumentation point in the global linked list.
00168  *   Note, the instrumentation point is not added to the list until the first
00169  *   data value is posted.
00170  */
00171 struct iPoint {
00172     const char *ip_Name;
00173     const char *ip_Description;
00174     unsigned long ip_Flags;
00175     struct {
00176         double *data;
00177         size_t length;
00178         unsigned int start;
00179         unsigned int lost;
00180     } ip_History;
00181     const char *ip_Format;
00182     unsigned long long ip_Count;
00183     double ip_Total;
00184     double ip_Minimum;
00185     double ip_Maximum;
00186     struct iPoint *ip_Succ;
00187 };
00188 
00189 /**
00190  * Macro used to statically initialize the ip_History field of the iPoint
00191  * structure.
00192  *
00193  * @param history A statically allocated array of doubles.
00194  */
00195 #define IPOINT_INIT_HISTORY(history) { \
00196     history, \
00197     sizeof(history) / sizeof(double) \
00198 }
00199 
00200 /**
00201  * Macro used to perform high-resolution timings of a block of code.
00202  *
00203  * @param point The iPoint to use when recording data.
00204  * @param block The code block to instrument.
00205  *
00206  * @see NOINSTR
00207  */
00208 #define HRTIME_INSTR(point, block) { \
00209     hrtime_t _start, _end; \
00210 \
00211     _start = hrtime(); \
00212     block; \
00213     _end = hrtime(); \
00214     iPostFloatData(point, (_end - _start)); \
00215 }
00216 
00217 /**
00218  * Macro used to perform low-resolution timings of a block of code.
00219  *
00220  * @param point The iPoint to use when recording data.
00221  * @param block The code block to instrument.
00222  *
00223  * @see NOINSTR
00224  */
00225 #define LRTIME_INSTR(point, block) { \
00226     lrtime_t _start, _end; \
00227 \
00228     _start = lrtime(); \
00229     block; \
00230     _end = lrtime(); \
00231     iPostFloatData(point, (_end - _start)); \
00232 }
00233 
00234 /**
00235  * Macro used to record the value of an numeral expression.
00236  *
00237  * @param point The iPoint to use when recording data.
00238  * @param expr An expression that results in a number value.
00239  *
00240  * @see NOINSTR
00241  */
00242 #define ACCUM_INSTR(point, expr) { \
00243     iPostFloatData(point, (double)(expr)); \
00244 }
00245 
00246 /**
00247  * Macro used to avoid instrumenting a block of code.
00248  *
00249  * @param point Not used.  This is only here so it can mimic the other INSTR
00250  * macros.
00251  * @param block A block of code to execute.
00252  *
00253  * @see NOINSTR
00254  */
00255 #define NOINSTR(point, block) block
00256 
00257 /*
00258  * The structure of global data needed by the instrumentation infrastructure.
00259  *
00260  * iid_OutputFileName - The name of the file where results should be written.
00261  * If NULL, a file be created with a name having the form:
00262  * '<PACKAGE>-instrumentation-<pid>.txt'.  If it is a '-', the results will be
00263  * written to standard out.
00264  * iid_FirstPoint - The first instrumentation point in the list.
00265  * iid_NullPoint - A special instrumentation point value used to detect whether
00266  * an iPoint object is in the global list or not.
00267  */
00268 struct iInstrumentationData {
00269     const char *iid_OutputFileName;
00270     struct iPoint *iid_FirstPoint;
00271     struct iPoint iid_NullPoint;
00272 };
00273 
00274 /**
00275  * The global data needed by the instrumentation infrastructure.
00276  */
00277 extern struct iInstrumentationData instrumentation_data;
00278 
00279 /**
00280  * Post a floating point data value to an instrumentation point.
00281  *
00282  * @param ip The instrumentation point to add the given value to.
00283  * @param value The value to add.
00284  */
00285 void iPostFloatData(struct iPoint *ip, double value);
00286 
00287 /**
00288  * Print the collected values for an instrumentation point.
00289  *
00290  * @param file The file to print the data to.
00291  * @param ip The instrumentation point to print out.
00292  */
00293 void iPrintPoint(FILE *file, struct iPoint *ip);
00294 
00295 /**
00296  * Print all of the instrumentation points that have had data posted to them.
00297  *
00298  * @param file The file to print the data to.
00299  */
00300 void iPrintPoints(FILE *file);
00301 
00302 /**
00303  * An atexit(3) function that calls iPrintPoints with a file whose name is
00304  * taken from instrumentation_data.iid_OutputFileName or derived from the
00305  * package name and process ID.
00306  */
00307 void iPrintPointsAtExit(void);
00308 
00309 #ifdef __cplusplus
00310 }
00311 #endif
00312 
00313 #endif

Generated on Mon Dec 1 16:29:06 2003 for CPU Broker by doxygen 1.3.4