| #ifndef _GPXE_PROFILE_H |
| #define _GPXE_PROFILE_H |
| |
| /** @file |
| * |
| * Profiling |
| * |
| */ |
| |
| FILE_LICENCE ( GPL2_OR_LATER ); |
| |
| #include <stdint.h> |
| |
| /** |
| * A data structure for storing profiling information |
| */ |
| union profiler { |
| /** Timestamp (in CPU-specific "ticks") */ |
| uint64_t timestamp; |
| /** Registers returned by rdtsc. |
| * |
| * This part should really be architecture-specific code. |
| */ |
| struct { |
| uint32_t eax; |
| uint32_t edx; |
| } rdtsc; |
| }; |
| |
| /** |
| * Static per-object profiler, for use with simple_profile() |
| */ |
| static union profiler simple_profiler; |
| |
| /** |
| * Perform profiling |
| * |
| * @v profiler Profiler data structure |
| * @ret delta Elapsed ticks since last call to profile(). |
| * |
| * Call profile() both before and after the code you wish to measure. |
| * The "after" call will return the measurement. For example: |
| * |
| * @code |
| * |
| * profile ( &profiler ); |
| * ... do something here ... |
| * printf ( "It took %ld ticks to execute\n", profile ( &profiler ) ); |
| * |
| * @endcode |
| */ |
| static inline __attribute__ (( always_inline )) unsigned long |
| profile ( union profiler *profiler ) { |
| uint64_t last_timestamp = profiler->timestamp; |
| |
| __asm__ __volatile__ ( "rdtsc" : |
| "=a" ( profiler->rdtsc.eax ), |
| "=d" ( profiler->rdtsc.edx ) ); |
| return ( profiler->timestamp - last_timestamp ); |
| } |
| |
| /** |
| * Perform profiling |
| * |
| * @ret delta Elapsed ticks since last call to profile(). |
| * |
| * When you only need one profiler, you can avoid the hassle of |
| * creating your own @c profiler data structure by using |
| * simple_profile() instead. |
| * |
| * simple_profile() is equivalent to profile(&simple_profiler), where |
| * @c simple_profiler is a @c profiler data structure that is static |
| * to each object which includes @c profile.h. |
| */ |
| static inline __attribute__ (( always_inline )) unsigned long |
| simple_profile ( void ) { |
| return profile ( &simple_profiler ); |
| } |
| |
| #endif /* _GPXE_PROFILE_H */ |