summaryrefslogtreecommitdiffstats
path: root/src/include/ipxe/profile.h
blob: 0b15fe5450ed4ae92bb15fa56de0e35dca6d68ba (plain) (blame)
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#ifndef _IPXE_PROFILE_H
#define _IPXE_PROFILE_H

/** @file
 *
 * Profiling
 *
 */

FILE_LICENCE ( GPL2_OR_LATER );

#include <stdint.h>
#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 */
	uint64_t started;
	/** 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 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 );

/**
 * 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 )
		profiler->started = profile_timestamp();
}

/**
 * Record profiling result
 *
 * @v profiler		Profiler
 */
static inline __attribute__ (( always_inline )) void
profile_stop ( struct profiler *profiler ) {
	uint64_t ended;

	/* If profiling is active then record end timestamp and update stats */
	if ( PROFILING ) {
		ended = profile_timestamp();
		profile_update ( profiler, ( ended - profiler->started ) );
	}
}

#endif /* _IPXE_PROFILE_H */