Browse Source

[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 10 years ago
parent
commit
6f410a16d9

+ 2
- 2
src/arch/i386/interface/pxeparent/pxeparent.c View File

240
 			         "D" ( __from_data16 ( &pxeparent_params ) )
240
 			         "D" ( __from_data16 ( &pxeparent_params ) )
241
 			       : "ecx", "esi" );
241
 			       : "ecx", "esi" );
242
 	profile_stop ( &profiler->total );
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
 	profile_stop_at ( &profiler->p2r, started );
244
 	profile_stop_at ( &profiler->p2r, started );
245
 	profile_start_at ( &profiler->ext, started );
245
 	profile_start_at ( &profiler->ext, started );
246
 	profile_stop_at ( &profiler->ext, stopped );
246
 	profile_stop_at ( &profiler->ext, stopped );
247
 	profile_start_at ( &profiler->r2p, stopped );
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
 	/* Determine return status code based on PXENV_EXIT and
250
 	/* Determine return status code based on PXENV_EXIT and
251
 	 * PXENV_STATUS
251
 	 * PXENV_STATUS

+ 30
- 3
src/arch/i386/transitions/librm_mgmt.c View File

8
 FILE_LICENCE ( GPL2_OR_LATER );
8
 FILE_LICENCE ( GPL2_OR_LATER );
9
 
9
 
10
 #include <stdint.h>
10
 #include <stdint.h>
11
+#include <ipxe/profile.h>
11
 #include <realmode.h>
12
 #include <realmode.h>
12
 #include <pic8259.h>
13
 #include <pic8259.h>
13
 
14
 
30
 	.limit = ( sizeof ( idt ) - 1 ),
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
  * Allocate space on the real-mode stack and copy data there from a
41
  * Allocate space on the real-mode stack and copy data there from a
35
  * user buffer
42
  * user buffer
103
 	idtr.base = virt_to_phys ( idt );
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
  * Interrupt handler
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
 	uint32_t discard_eax;
136
 	uint32_t discard_eax;
113
 
137
 
114
 	/* Reissue interrupt in real mode */
138
 	/* Reissue interrupt in real mode */
139
+	profile_start ( profiler );
115
 	__asm__ __volatile__ ( REAL_CODE ( "movb %%al, %%cs:(1f + 1)\n\t"
140
 	__asm__ __volatile__ ( REAL_CODE ( "movb %%al, %%cs:(1f + 1)\n\t"
116
 					   "\n1:\n\t"
141
 					   "\n1:\n\t"
117
 					   "int $0x00\n\t" )
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
 PROVIDE_UACCESS_INLINE ( librm, phys_to_user );
148
 PROVIDE_UACCESS_INLINE ( librm, phys_to_user );

+ 3
- 0
src/core/profile.c View File

40
  * to avoid the use of floating-point instructions.
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
  * Format a hex fraction (for debugging)
47
  * Format a hex fraction (for debugging)
45
  *
48
  *

+ 79
- 12
src/include/ipxe/profile.h View File

58
 #define __profiler
58
 #define __profiler
59
 #endif
59
 #endif
60
 
60
 
61
+extern unsigned long profile_excluded;
62
+
61
 extern void profile_update ( struct profiler *profiler, unsigned long sample );
63
 extern void profile_update ( struct profiler *profiler, unsigned long sample );
62
 extern unsigned long profile_mean ( struct profiler *profiler );
64
 extern unsigned long profile_mean ( struct profiler *profiler );
63
 extern unsigned long profile_variance ( struct profiler *profiler );
65
 extern unsigned long profile_variance ( struct profiler *profiler );
64
 extern unsigned long profile_stddev ( struct profiler *profiler );
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
  * Start profiling
121
  * Start profiling
68
  *
122
  *
74
 
128
 
75
 	/* If profiling is active then record start timestamp */
129
 	/* If profiling is active then record start timestamp */
76
 	if ( PROFILING )
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
 }
161
 }
92
 
162
 
93
 /**
163
 /**
94
- * Record profiling result
164
+ * Stop profiling
95
  *
165
  *
96
  * @v profiler		Profiler
166
  * @v profiler		Profiler
97
- * @v stopped		Stop timestamp
98
  */
167
  */
99
 static inline __attribute__ (( always_inline )) void
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
 	/* If profiling is active then record end timestamp and update stats */
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
  * @v profiler		Profiler
179
  * @v profiler		Profiler
113
  */
180
  */
114
 static inline __attribute__ (( always_inline )) void
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
 	if ( PROFILING )
185
 	if ( PROFILING )
119
-		profile_stop_at ( profiler, profile_timestamp() );
186
+		profile_excluded += profile_elapsed ( profiler );
120
 }
187
 }
121
 
188
 
122
 #endif /* _IPXE_PROFILE_H */
189
 #endif /* _IPXE_PROFILE_H */

Loading…
Cancel
Save