iPXE
profile.h
Go to the documentation of this file.
00001 #ifndef _IPXE_PROFILE_H
00002 #define _IPXE_PROFILE_H
00003 
00004 /** @file
00005  *
00006  * Profiling
00007  *
00008  */
00009 
00010 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
00011 
00012 #include <bits/profile.h>
00013 #include <ipxe/tables.h>
00014 
00015 #ifndef PROFILING
00016 #ifdef NDEBUG
00017 #define PROFILING 0
00018 #else
00019 #define PROFILING 1
00020 #endif
00021 #endif
00022 
00023 /**
00024  * A data structure for storing profiling information
00025  */
00026 struct profiler {
00027         /** Name */
00028         const char *name;
00029         /** Start timestamp */
00030         unsigned long started;
00031         /** Stop timestamp */
00032         unsigned long stopped;
00033         /** Number of samples */
00034         unsigned int count;
00035         /** Mean sample value (scaled) */
00036         unsigned long mean;
00037         /** Mean sample value MSB
00038          *
00039          * This is the highest bit set in the raw (unscaled) value
00040          * (i.e. one less than would be returned by flsl(raw_mean)).
00041          */
00042         unsigned int mean_msb;
00043         /** Accumulated variance (scaled) */
00044         unsigned long long accvar;
00045         /** Accumulated variance MSB
00046          *
00047          * This is the highest bit set in the raw (unscaled) value
00048          * (i.e. one less than would be returned by flsll(raw_accvar)).
00049          */
00050         unsigned int accvar_msb;
00051 };
00052 
00053 /** Profiler table */
00054 #define PROFILERS __table ( struct profiler, "profilers" )
00055 
00056 /** Declare a profiler */
00057 #if PROFILING
00058 #define __profiler __table_entry ( PROFILERS, 01 )
00059 #else
00060 #define __profiler
00061 #endif
00062 
00063 extern unsigned long profile_excluded;
00064 
00065 extern void profile_update ( struct profiler *profiler, unsigned long sample );
00066 extern unsigned long profile_mean ( struct profiler *profiler );
00067 extern unsigned long profile_variance ( struct profiler *profiler );
00068 extern unsigned long profile_stddev ( struct profiler *profiler );
00069 
00070 /**
00071  * Get start time
00072  *
00073  * @v profiler          Profiler
00074  * @ret started         Start time
00075  */
00076 static inline __attribute__ (( always_inline )) unsigned long
00077 profile_started ( struct profiler *profiler ) {
00078 
00079         /* If profiling is active then return start time */
00080         if ( PROFILING ) {
00081                 return ( profiler->started + profile_excluded );
00082         } else {
00083                 return 0;
00084         }
00085 }
00086 
00087 /**
00088  * Get stop time
00089  *
00090  * @v profiler          Profiler
00091  * @ret stopped         Stop time
00092  */
00093 static inline __attribute__ (( always_inline )) unsigned long
00094 profile_stopped ( struct profiler *profiler ) {
00095 
00096         /* If profiling is active then return start time */
00097         if ( PROFILING ) {
00098                 return ( profiler->stopped + profile_excluded );
00099         } else {
00100                 return 0;
00101         }
00102 }
00103 
00104 /**
00105  * Get elapsed time
00106  *
00107  * @v profiler          Profiler
00108  * @ret elapsed         Elapsed time
00109  */
00110 static inline __attribute__ (( always_inline )) unsigned long
00111 profile_elapsed ( struct profiler *profiler ) {
00112 
00113         /* If profiling is active then return elapsed time */
00114         if ( PROFILING ) {
00115                 return ( profile_stopped ( profiler ) -
00116                          profile_started ( profiler ) );
00117         } else {
00118                 return 0;
00119         }
00120 }
00121 
00122 /**
00123  * Start profiling
00124  *
00125  * @v profiler          Profiler
00126  * @v started           Start timestamp
00127  */
00128 static inline __attribute__ (( always_inline )) void
00129 profile_start_at ( struct profiler *profiler, unsigned long started ) {
00130 
00131         /* If profiling is active then record start timestamp */
00132         if ( PROFILING )
00133                 profiler->started = ( started - profile_excluded );
00134 }
00135 
00136 /**
00137  * Stop profiling
00138  *
00139  * @v profiler          Profiler
00140  * @v stopped           Stop timestamp
00141  */
00142 static inline __attribute__ (( always_inline )) void
00143 profile_stop_at ( struct profiler *profiler, unsigned long stopped ) {
00144 
00145         /* If profiling is active then record end timestamp and update stats */
00146         if ( PROFILING ) {
00147                 profiler->stopped = ( stopped - profile_excluded );
00148                 profile_update ( profiler, profile_elapsed ( profiler ) );
00149         }
00150 }
00151 
00152 /**
00153  * Start profiling
00154  *
00155  * @v profiler          Profiler
00156  */
00157 static inline __attribute__ (( always_inline )) void
00158 profile_start ( struct profiler *profiler ) {
00159 
00160         /* If profiling is active then record start timestamp */
00161         if ( PROFILING )
00162                 profile_start_at ( profiler, profile_timestamp() );
00163 }
00164 
00165 /**
00166  * Stop profiling
00167  *
00168  * @v profiler          Profiler
00169  */
00170 static inline __attribute__ (( always_inline )) void
00171 profile_stop ( struct profiler *profiler ) {
00172 
00173         /* If profiling is active then record end timestamp and update stats */
00174         if ( PROFILING )
00175                 profile_stop_at ( profiler, profile_timestamp() );
00176 }
00177 
00178 /**
00179  * Exclude time from other ongoing profiling results
00180  *
00181  * @v profiler          Profiler
00182  */
00183 static inline __attribute__ (( always_inline )) void
00184 profile_exclude ( struct profiler *profiler ) {
00185 
00186         /* If profiling is active then update accumulated excluded time */
00187         if ( PROFILING )
00188                 profile_excluded += profile_elapsed ( profiler );
00189 }
00190 
00191 /**
00192  * Record profiling sample in custom units
00193  *
00194  * @v profiler          Profiler
00195  * @v sample            Profiling sample
00196  */
00197 static inline __attribute__ (( always_inline )) void
00198 profile_custom ( struct profiler *profiler, unsigned long sample ) {
00199 
00200         /* If profiling is active then update stats */
00201         if ( PROFILING )
00202                 profile_update ( profiler, sample );
00203 }
00204 
00205 #endif /* _IPXE_PROFILE_H */