Procházet zdrojové kódy

[profile] Allow interrupts to be excluded from profiling results

Interrupt processing adds noise to profiling results.  Allow
interrupts (from within protected mode) to be profiled separately,
with time spent within the interrupt handler being excluded from any
other profiling currently in progress.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown před 10 roky
rodič
revize
6f410a16d9

+ 2
- 2
src/arch/i386/interface/pxeparent/pxeparent.c Zobrazit soubor

@@ -240,12 +240,12 @@ int pxeparent_call ( SEGOFF16_t entry, unsigned int function,
240 240
 			         "D" ( __from_data16 ( &pxeparent_params ) )
241 241
 			       : "ecx", "esi" );
242 242
 	profile_stop ( &profiler->total );
243
-	profile_start_at ( &profiler->p2r, profiler->total.started );
243
+	profile_start_at ( &profiler->p2r, profile_started ( &profiler->total));
244 244
 	profile_stop_at ( &profiler->p2r, started );
245 245
 	profile_start_at ( &profiler->ext, started );
246 246
 	profile_stop_at ( &profiler->ext, stopped );
247 247
 	profile_start_at ( &profiler->r2p, stopped );
248
-	profile_stop_at ( &profiler->r2p, profiler->total.stopped );
248
+	profile_stop_at ( &profiler->r2p, profile_stopped ( &profiler->total ));
249 249
 
250 250
 	/* Determine return status code based on PXENV_EXIT and
251 251
 	 * PXENV_STATUS

+ 30
- 3
src/arch/i386/transitions/librm_mgmt.c Zobrazit soubor

@@ -8,6 +8,7 @@
8 8
 FILE_LICENCE ( GPL2_OR_LATER );
9 9
 
10 10
 #include <stdint.h>
11
+#include <ipxe/profile.h>
11 12
 #include <realmode.h>
12 13
 #include <pic8259.h>
13 14
 
@@ -30,6 +31,12 @@ struct idtr idtr = {
30 31
 	.limit = ( sizeof ( idt ) - 1 ),
31 32
 };
32 33
 
34
+/** Timer interrupt profiler */
35
+static struct profiler timer_irq_profiler __profiler = { .name = "irq.timer" };
36
+
37
+/** Other interrupt profiler */
38
+static struct profiler other_irq_profiler __profiler = { .name = "irq.other" };
39
+
33 40
 /**
34 41
  * Allocate space on the real-mode stack and copy data there from a
35 42
  * user buffer
@@ -103,19 +110,39 @@ void init_idt ( void ) {
103 110
 	idtr.base = virt_to_phys ( idt );
104 111
 }
105 112
 
113
+/**
114
+ * Determine interrupt profiler (for debugging)
115
+ *
116
+ * @v intr		Interrupt number
117
+ * @ret profiler	Profiler
118
+ */
119
+static struct profiler * interrupt_profiler ( int intr ) {
120
+
121
+	switch ( intr ) {
122
+	case IRQ_INT ( 0 ) :
123
+		return &timer_irq_profiler;
124
+	default:
125
+		return &other_irq_profiler;
126
+	}
127
+}
128
+
106 129
 /**
107 130
  * Interrupt handler
108 131
  *
109
- * @v irq		Interrupt number
132
+ * @v intr		Interrupt number
110 133
  */
111
-void __attribute__ (( cdecl, regparm ( 1 ) )) interrupt ( int irq ) {
134
+void __attribute__ (( cdecl, regparm ( 1 ) )) interrupt ( int intr ) {
135
+	struct profiler *profiler = interrupt_profiler ( intr );
112 136
 	uint32_t discard_eax;
113 137
 
114 138
 	/* Reissue interrupt in real mode */
139
+	profile_start ( profiler );
115 140
 	__asm__ __volatile__ ( REAL_CODE ( "movb %%al, %%cs:(1f + 1)\n\t"
116 141
 					   "\n1:\n\t"
117 142
 					   "int $0x00\n\t" )
118
-			       : "=a" ( discard_eax ) : "0" ( irq ) );
143
+			       : "=a" ( discard_eax ) : "0" ( intr ) );
144
+	profile_stop ( profiler );
145
+	profile_exclude ( profiler );
119 146
 }
120 147
 
121 148
 PROVIDE_UACCESS_INLINE ( librm, phys_to_user );

+ 3
- 0
src/core/profile.c Zobrazit soubor

@@ -40,6 +40,9 @@ FILE_LICENCE ( GPL2_OR_LATER );
40 40
  * to avoid the use of floating-point instructions.
41 41
  */
42 42
 
43
+/** Accumulated time excluded from profiling */
44
+unsigned long profile_excluded;
45
+
43 46
 /**
44 47
  * Format a hex fraction (for debugging)
45 48
  *

+ 79
- 12
src/include/ipxe/profile.h Zobrazit soubor

@@ -58,11 +58,65 @@ struct profiler {
58 58
 #define __profiler
59 59
 #endif
60 60
 
61
+extern unsigned long profile_excluded;
62
+
61 63
 extern void profile_update ( struct profiler *profiler, unsigned long sample );
62 64
 extern unsigned long profile_mean ( struct profiler *profiler );
63 65
 extern unsigned long profile_variance ( struct profiler *profiler );
64 66
 extern unsigned long profile_stddev ( struct profiler *profiler );
65 67
 
68
+/**
69
+ * Get start time
70
+ *
71
+ * @v profiler		Profiler
72
+ * @ret started		Start time
73
+ */
74
+static inline __attribute__ (( always_inline )) unsigned long
75
+profile_started ( struct profiler *profiler ) {
76
+
77
+	/* If profiling is active then return start time */
78
+	if ( PROFILING ) {
79
+		return ( profiler->started + profile_excluded );
80
+	} else {
81
+		return 0;
82
+	}
83
+}
84
+
85
+/**
86
+ * Get stop time
87
+ *
88
+ * @v profiler		Profiler
89
+ * @ret stopped		Stop time
90
+ */
91
+static inline __attribute__ (( always_inline )) unsigned long
92
+profile_stopped ( struct profiler *profiler ) {
93
+
94
+	/* If profiling is active then return start time */
95
+	if ( PROFILING ) {
96
+		return ( profiler->stopped + profile_excluded );
97
+	} else {
98
+		return 0;
99
+	}
100
+}
101
+
102
+/**
103
+ * Get elapsed time
104
+ *
105
+ * @v profiler		Profiler
106
+ * @ret elapsed		Elapsed time
107
+ */
108
+static inline __attribute__ (( always_inline )) unsigned long
109
+profile_elapsed ( struct profiler *profiler ) {
110
+
111
+	/* If profiling is active then return elapsed time */
112
+	if ( PROFILING ) {
113
+		return ( profile_stopped ( profiler ) -
114
+			 profile_started ( profiler ) );
115
+	} else {
116
+		return 0;
117
+	}
118
+}
119
+
66 120
 /**
67 121
  * Start profiling
68 122
  *
@@ -74,7 +128,23 @@ profile_start_at ( struct profiler *profiler, unsigned long started ) {
74 128
 
75 129
 	/* If profiling is active then record start timestamp */
76 130
 	if ( PROFILING )
77
-		profiler->started = started;
131
+		profiler->started = ( started - profile_excluded );
132
+}
133
+
134
+/**
135
+ * Stop profiling
136
+ *
137
+ * @v profiler		Profiler
138
+ * @v stopped		Stop timestamp
139
+ */
140
+static inline __attribute__ (( always_inline )) void
141
+profile_stop_at ( struct profiler *profiler, unsigned long stopped ) {
142
+
143
+	/* If profiling is active then record end timestamp and update stats */
144
+	if ( PROFILING ) {
145
+		profiler->stopped = ( stopped - profile_excluded );
146
+		profile_update ( profiler, profile_elapsed ( profiler ) );
147
+	}
78 148
 }
79 149
 
80 150
 /**
@@ -91,32 +161,29 @@ profile_start ( struct profiler *profiler ) {
91 161
 }
92 162
 
93 163
 /**
94
- * Record profiling result
164
+ * Stop profiling
95 165
  *
96 166
  * @v profiler		Profiler
97
- * @v stopped		Stop timestamp
98 167
  */
99 168
 static inline __attribute__ (( always_inline )) void
100
-profile_stop_at ( struct profiler *profiler, unsigned long stopped ) {
169
+profile_stop ( struct profiler *profiler ) {
101 170
 
102 171
 	/* If profiling is active then record end timestamp and update stats */
103
-	if ( PROFILING ) {
104
-		profiler->stopped = stopped;
105
-		profile_update ( profiler, ( stopped - profiler->started ) );
106
-	}
172
+	if ( PROFILING )
173
+		profile_stop_at ( profiler, profile_timestamp() );
107 174
 }
108 175
 
109 176
 /**
110
- * Record profiling result
177
+ * Exclude time from other ongoing profiling results
111 178
  *
112 179
  * @v profiler		Profiler
113 180
  */
114 181
 static inline __attribute__ (( always_inline )) void
115
-profile_stop ( struct profiler *profiler ) {
182
+profile_exclude ( struct profiler *profiler ) {
116 183
 
117
-	/* If profiling is active then record end timestamp and update stats */
184
+	/* If profiling is active then update accumulated excluded time */
118 185
 	if ( PROFILING )
119
-		profile_stop_at ( profiler, profile_timestamp() );
186
+		profile_excluded += profile_elapsed ( profiler );
120 187
 }
121 188
 
122 189
 #endif /* _IPXE_PROFILE_H */

Načítá se…
Zrušit
Uložit