Home | History | Annotate | Download | only in gpxe
      1 #ifndef _GPXE_PROFILE_H
      2 #define _GPXE_PROFILE_H
      3 
      4 /** @file
      5  *
      6  * Profiling
      7  *
      8  */
      9 
     10 FILE_LICENCE ( GPL2_OR_LATER );
     11 
     12 #include <stdint.h>
     13 
     14 /**
     15  * A data structure for storing profiling information
     16  */
     17 union profiler {
     18 	/** Timestamp (in CPU-specific "ticks") */
     19 	uint64_t timestamp;
     20 	/** Registers returned by rdtsc.
     21 	 *
     22 	 * This part should really be architecture-specific code.
     23 	 */
     24 	struct {
     25 		uint32_t eax;
     26 		uint32_t edx;
     27 	} rdtsc;
     28 };
     29 
     30 /**
     31  * Static per-object profiler, for use with simple_profile()
     32  */
     33 static union profiler simple_profiler;
     34 
     35 /**
     36  * Perform profiling
     37  *
     38  * @v profiler		Profiler data structure
     39  * @ret delta		Elapsed ticks since last call to profile().
     40  *
     41  * Call profile() both before and after the code you wish to measure.
     42  * The "after" call will return the measurement.  For example:
     43  *
     44  * @code
     45  *
     46  *     profile ( &profiler );
     47  *     ... do something here ...
     48  *     printf ( "It took %ld ticks to execute\n", profile ( &profiler ) );
     49  *
     50  * @endcode
     51  */
     52 static inline __attribute__ (( always_inline )) unsigned long
     53 profile ( union profiler *profiler ) {
     54 	uint64_t last_timestamp = profiler->timestamp;
     55 
     56 	__asm__ __volatile__ ( "rdtsc" :
     57 			       "=a" ( profiler->rdtsc.eax ),
     58 			       "=d" ( profiler->rdtsc.edx ) );
     59 	return ( profiler->timestamp - last_timestamp );
     60 }
     61 
     62 /**
     63  * Perform profiling
     64  *
     65  * @ret delta		Elapsed ticks since last call to profile().
     66  *
     67  * When you only need one profiler, you can avoid the hassle of
     68  * creating your own @c profiler data structure by using
     69  * simple_profile() instead.
     70  *
     71  * simple_profile() is equivalent to profile(&simple_profiler), where
     72  * @c simple_profiler is a @c profiler data structure that is static
     73  * to each object which includes @c profile.h.
     74  */
     75 static inline __attribute__ (( always_inline )) unsigned long
     76 simple_profile ( void ) {
     77 	return profile ( &simple_profiler );
     78 }
     79 
     80 #endif /* _GPXE_PROFILE_H */
     81