Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / ipxe / src / include / ipxe / profile.h
diff --git a/qemu/roms/ipxe/src/include/ipxe/profile.h b/qemu/roms/ipxe/src/include/ipxe/profile.h
new file mode 100644 (file)
index 0000000..3a745fc
--- /dev/null
@@ -0,0 +1,189 @@
+#ifndef _IPXE_PROFILE_H
+#define _IPXE_PROFILE_H
+
+/** @file
+ *
+ * Profiling
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <bits/profile.h>
+#include <ipxe/tables.h>
+
+#ifdef NDEBUG
+#define PROFILING 0
+#else
+#define PROFILING 1
+#endif
+
+/**
+ * A data structure for storing profiling information
+ */
+struct profiler {
+       /** Name */
+       const char *name;
+       /** Start timestamp */
+       unsigned long started;
+       /** Stop timestamp */
+       unsigned long stopped;
+       /** Number of samples */
+       unsigned int count;
+       /** Mean sample value (scaled) */
+       unsigned long mean;
+       /** Mean sample value MSB
+        *
+        * This is the highest bit set in the raw (unscaled) value
+        * (i.e. one less than would be returned by flsl(raw_mean)).
+        */
+       unsigned int mean_msb;
+       /** Accumulated variance (scaled) */
+       unsigned long long accvar;
+       /** Accumulated variance MSB
+        *
+        * This is the highest bit set in the raw (unscaled) value
+        * (i.e. one less than would be returned by flsll(raw_accvar)).
+        */
+       unsigned int accvar_msb;
+};
+
+/** Profiler table */
+#define PROFILERS __table ( struct profiler, "profilers" )
+
+/** Declare a profiler */
+#if PROFILING
+#define __profiler __table_entry ( PROFILERS, 01 )
+#else
+#define __profiler
+#endif
+
+extern unsigned long profile_excluded;
+
+extern void profile_update ( struct profiler *profiler, unsigned long sample );
+extern unsigned long profile_mean ( struct profiler *profiler );
+extern unsigned long profile_variance ( struct profiler *profiler );
+extern unsigned long profile_stddev ( struct profiler *profiler );
+
+/**
+ * Get start time
+ *
+ * @v profiler         Profiler
+ * @ret started                Start time
+ */
+static inline __attribute__ (( always_inline )) unsigned long
+profile_started ( struct profiler *profiler ) {
+
+       /* If profiling is active then return start time */
+       if ( PROFILING ) {
+               return ( profiler->started + profile_excluded );
+       } else {
+               return 0;
+       }
+}
+
+/**
+ * Get stop time
+ *
+ * @v profiler         Profiler
+ * @ret stopped                Stop time
+ */
+static inline __attribute__ (( always_inline )) unsigned long
+profile_stopped ( struct profiler *profiler ) {
+
+       /* If profiling is active then return start time */
+       if ( PROFILING ) {
+               return ( profiler->stopped + profile_excluded );
+       } else {
+               return 0;
+       }
+}
+
+/**
+ * Get elapsed time
+ *
+ * @v profiler         Profiler
+ * @ret elapsed                Elapsed time
+ */
+static inline __attribute__ (( always_inline )) unsigned long
+profile_elapsed ( struct profiler *profiler ) {
+
+       /* If profiling is active then return elapsed time */
+       if ( PROFILING ) {
+               return ( profile_stopped ( profiler ) -
+                        profile_started ( profiler ) );
+       } else {
+               return 0;
+       }
+}
+
+/**
+ * Start profiling
+ *
+ * @v profiler         Profiler
+ * @v started          Start timestamp
+ */
+static inline __attribute__ (( always_inline )) void
+profile_start_at ( struct profiler *profiler, unsigned long started ) {
+
+       /* If profiling is active then record start timestamp */
+       if ( PROFILING )
+               profiler->started = ( started - profile_excluded );
+}
+
+/**
+ * Stop profiling
+ *
+ * @v profiler         Profiler
+ * @v stopped          Stop timestamp
+ */
+static inline __attribute__ (( always_inline )) void
+profile_stop_at ( struct profiler *profiler, unsigned long stopped ) {
+
+       /* If profiling is active then record end timestamp and update stats */
+       if ( PROFILING ) {
+               profiler->stopped = ( stopped - profile_excluded );
+               profile_update ( profiler, profile_elapsed ( profiler ) );
+       }
+}
+
+/**
+ * Start profiling
+ *
+ * @v profiler         Profiler
+ */
+static inline __attribute__ (( always_inline )) void
+profile_start ( struct profiler *profiler ) {
+
+       /* If profiling is active then record start timestamp */
+       if ( PROFILING )
+               profile_start_at ( profiler, profile_timestamp() );
+}
+
+/**
+ * Stop profiling
+ *
+ * @v profiler         Profiler
+ */
+static inline __attribute__ (( always_inline )) void
+profile_stop ( struct profiler *profiler ) {
+
+       /* If profiling is active then record end timestamp and update stats */
+       if ( PROFILING )
+               profile_stop_at ( profiler, profile_timestamp() );
+}
+
+/**
+ * Exclude time from other ongoing profiling results
+ *
+ * @v profiler         Profiler
+ */
+static inline __attribute__ (( always_inline )) void
+profile_exclude ( struct profiler *profiler ) {
+
+       /* If profiling is active then update accumulated excluded time */
+       if ( PROFILING )
+               profile_excluded += profile_elapsed ( profiler );
+}
+
+#endif /* _IPXE_PROFILE_H */