mirror of https://github.com/ipxe/ipxe.git
Added basic profiling support
parent
a677f1bfd3
commit
b4e559d7e2
|
@ -0,0 +1,78 @@
|
||||||
|
#ifndef _GPXE_PROFILE_H
|
||||||
|
#define _GPXE_PROFILE_H
|
||||||
|
|
||||||
|
/** @file
|
||||||
|
*
|
||||||
|
* Profiling
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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 */
|
Loading…
Reference in New Issue