aboutsummaryrefslogtreecommitdiffstats
path: root/gpxe/src/include/gpxe/profile.h
blob: a5bdd3a45b4a21858c1be29482f0b2d95e88d14c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#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 */