Added basic profiling support
authorMichael Brown <mcb30@etherboot.org>
Thu, 24 Aug 2006 16:22:56 +0000 (16:22 +0000)
committerMichael Brown <mcb30@etherboot.org>
Thu, 24 Aug 2006 16:22:56 +0000 (16:22 +0000)
src/include/gpxe/profile.h [new file with mode: 0644]

diff --git a/src/include/gpxe/profile.h b/src/include/gpxe/profile.h
new file mode 100644 (file)
index 0000000..d46ca05
--- /dev/null
@@ -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 */