1 | ;
|
---|
2 | ; PROFIL.ASM -- Implement profil()
|
---|
3 | ;
|
---|
4 | ; Copyright (c) 1995 by Eberhard Mattes
|
---|
5 | ;
|
---|
6 | ; This file is part of emx.
|
---|
7 | ;
|
---|
8 | ; emx is free software; you can redistribute it and/or modify it
|
---|
9 | ; under the terms of the GNU General Public License as published by
|
---|
10 | ; the Free Software Foundation; either version 2, or (at your option)
|
---|
11 | ; any later version.
|
---|
12 | ;
|
---|
13 | ; emx is distributed in the hope that it will be useful,
|
---|
14 | ; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
15 | ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
16 | ; GNU General Public License for more details.
|
---|
17 | ;
|
---|
18 | ; You should have received a copy of the GNU General Public License
|
---|
19 | ; along with emx; see the file COPYING. If not, write to
|
---|
20 | ; the Free Software Foundation, 59 Temple Place - Suite 330,
|
---|
21 | ; Boston, MA 02111-1307, USA.
|
---|
22 | ;
|
---|
23 | ; See emx.asm for a special exception.
|
---|
24 | ;
|
---|
25 |
|
---|
26 | __PROFIL = 1
|
---|
27 | INCLUDE EMX.INC
|
---|
28 | INCLUDE SIGNAL.INC
|
---|
29 | INCLUDE PROCESS.INC
|
---|
30 | INCLUDE PMINT.INC
|
---|
31 | INCLUDE PROFIL.INC
|
---|
32 | INCLUDE ERRORS.INC
|
---|
33 |
|
---|
34 | PUBLIC DO_PROFIL, PROFIL_SUSPEND, PROFIL_RESUME, PROFIL_TICK
|
---|
35 | PUBLIC PROFIL_COUNT
|
---|
36 |
|
---|
37 | ;
|
---|
38 | ; I/O port addresses of the MC146818 RTC chip
|
---|
39 | ;
|
---|
40 | RTC_ADDR = 70H
|
---|
41 | RTC_DATA = 71H
|
---|
42 |
|
---|
43 |
|
---|
44 | SV_DATA SEGMENT
|
---|
45 | ;
|
---|
46 | ; Number of processes being profiled. We don't need the RTC interrupt
|
---|
47 | ; if the number is zero.
|
---|
48 | ;
|
---|
49 | PROFIL_COUNT DW 0
|
---|
50 |
|
---|
51 | ;
|
---|
52 | ; The following two variables attempt to avoid lossage when using
|
---|
53 | ; the kernel debugge on the profiling code.
|
---|
54 | ;
|
---|
55 | PROFIL_SUSPENDED DB FALSE
|
---|
56 | PROFIL_RESUMED DB FALSE
|
---|
57 |
|
---|
58 | ;
|
---|
59 | ; The original values of registers 0A and 0B of the RTC chip.
|
---|
60 | ;
|
---|
61 | OLD_RTC_REG0A DB ?
|
---|
62 | OLD_RTC_REG0B DB ?
|
---|
63 |
|
---|
64 | SV_DATA ENDS
|
---|
65 |
|
---|
66 |
|
---|
67 | SV_CODE SEGMENT
|
---|
68 |
|
---|
69 | ASSUME CS:SV_CODE, DS:NOTHING
|
---|
70 |
|
---|
71 | ;
|
---|
72 | ; profil()
|
---|
73 | ;
|
---|
74 | ; In: ES:ESI Pointer to PROFIL structure
|
---|
75 | ; DI Pointer to process table entry
|
---|
76 | ;
|
---|
77 | ; Out: EAX errno
|
---|
78 | ;
|
---|
79 | TALIGN 4
|
---|
80 | ASSUME ESI:NEAR32 PTR PROFIL
|
---|
81 | ASSUME DI:PTR PROCESS
|
---|
82 | ASSUME DS:SV_DATA
|
---|
83 | DO_PROFIL PROC NEAR
|
---|
84 | CMP ES:[ESI].PRF_CB, SIZE PROFIL
|
---|
85 | JNE SHORT PROFIL_EINVAL
|
---|
86 | ;
|
---|
87 | ; Turn off profiling if scale <= 2 or bufsiz = 0
|
---|
88 | ;
|
---|
89 | CMP ES:[ESI].PRF_SCALE, 1
|
---|
90 | JBE SHORT PROFIL_OFF
|
---|
91 | CMP ES:[ESI].PRF_BUFSIZ, 0
|
---|
92 | JE SHORT PROFIL_OFF
|
---|
93 | ;
|
---|
94 | ; Copy the values into the process table
|
---|
95 | ;
|
---|
96 | MOV EAX, ES:[ESI].PRF_BUFF
|
---|
97 | MOV [DI].P_PRF_BUFF, EAX
|
---|
98 | MOV EAX, ES:[ESI].PRF_BUFSIZ
|
---|
99 | AND EAX, NOT 3
|
---|
100 | MOV [DI].P_PRF_BUFSIZ, EAX
|
---|
101 | MOV EAX, ES:[ESI].PRF_OFFSET
|
---|
102 | MOV [DI].P_PRF_OFFSET, EAX
|
---|
103 | MOV EAX, ES:[ESI].PRF_SCALE
|
---|
104 | MOV [DI].P_PRF_SCALE, EAX
|
---|
105 | ;
|
---|
106 | ; Start profiling
|
---|
107 | ;
|
---|
108 | CALL PROFIL_START
|
---|
109 | JC SHORT PROFIL_EINVAL
|
---|
110 | XOR EAX, EAX
|
---|
111 | RET
|
---|
112 |
|
---|
113 | ;
|
---|
114 | ; Stop profiling
|
---|
115 | ;
|
---|
116 | TALIGN 4
|
---|
117 | PROFIL_OFF: XOR EAX, EAX
|
---|
118 | XCHG EAX, [DI].P_PRF_SCALE
|
---|
119 | TEST EAX, EAX
|
---|
120 | JZ SHORT PROFIL_OK
|
---|
121 | CALL PROFIL_STOP
|
---|
122 | PROFIL_OK: XOR EAX, EAX
|
---|
123 | RET
|
---|
124 |
|
---|
125 | PROFIL_EINVAL: MOV EAX, EINVAL
|
---|
126 | RET
|
---|
127 | DO_PROFIL ENDP
|
---|
128 |
|
---|
129 | ASSUME ESI:NOTHING
|
---|
130 | ASSUME DI:NOTHING
|
---|
131 |
|
---|
132 | ;
|
---|
133 | ; Start profiling one process
|
---|
134 | ;
|
---|
135 | ; Out: CY Error
|
---|
136 | ;
|
---|
137 | ASSUME DS:SV_DATA
|
---|
138 | PROFIL_START PROC NEAR
|
---|
139 | INC PROFIL_COUNT
|
---|
140 | CMP PROFIL_COUNT, 1
|
---|
141 | JNE SHORT DONE
|
---|
142 | CLI
|
---|
143 | CALL PROFIL_RESUME
|
---|
144 | JNC SHORT OK
|
---|
145 | MOV PROFIL_COUNT, 0
|
---|
146 | OK: STI
|
---|
147 | DONE: RET
|
---|
148 | PROFIL_START ENDP
|
---|
149 |
|
---|
150 | ;
|
---|
151 | ; Stop profiling one process
|
---|
152 | ;
|
---|
153 | ASSUME DS:SV_DATA
|
---|
154 | PROFIL_STOP PROC NEAR
|
---|
155 | CMP PROFIL_COUNT, 0
|
---|
156 | JE SHORT DONE
|
---|
157 | DEC PROFIL_COUNT
|
---|
158 | JNZ SHORT DONE
|
---|
159 | CLI
|
---|
160 | CALL PROFIL_SUSPEND
|
---|
161 | STI
|
---|
162 | DONE: RET
|
---|
163 | PROFIL_STOP ENDP
|
---|
164 |
|
---|
165 | ;
|
---|
166 | ; Timer tick for profiler, called by PMINT for IRQ8 if PROFIL_COUNT
|
---|
167 | ; is non-zero
|
---|
168 | ;
|
---|
169 | TALIGN 4
|
---|
170 | ASSUME DS:SV_DATA
|
---|
171 | ASSUME BP:PTR ISTACKFRAME
|
---|
172 | PROFIL_TICK PROC NEAR
|
---|
173 | MOV AL, 0CH ; Read status register
|
---|
174 | CALL RTC_READ
|
---|
175 | TEST AL, 40H ; Periodic interrupt pending?
|
---|
176 | JZ SHORT DONE ; No -> done
|
---|
177 | CMP I_CS, L_CODE_SEL ; Profile user code only
|
---|
178 | JNE SHORT DONE
|
---|
179 | MOV BX, PROCESS_PTR
|
---|
180 | CMP BX, NO_PROCESS ; User process active?
|
---|
181 | JE SHORT DONE ; No -> done
|
---|
182 | ASSUME BX:PTR PROCESS
|
---|
183 | CMP [BX].P_PRF_SCALE, 0 ; Profiling that process?
|
---|
184 | JE SHORT DONE ; No -> done
|
---|
185 | MOV EAX, I_EIP ; Compute counter offset
|
---|
186 | SUB EAX, [BX].P_PRF_OFFSET
|
---|
187 | JC SHORT DONE
|
---|
188 | MUL [BX].P_PRF_SCALE
|
---|
189 | SHRD EAX, EDX, 16
|
---|
190 | AND EAX, NOT 3
|
---|
191 | CMP EAX, [BX].P_PRF_BUFSIZ ; Within buffer?
|
---|
192 | JAE SHORT DONE ; No -> done
|
---|
193 | MOV EDX, [BX].P_PRF_BUFF
|
---|
194 | MOV CX, L_DATA_SEL
|
---|
195 | MOV ES, CX
|
---|
196 | INC DWORD PTR ES:[EDX+EAX] ; Increment counter
|
---|
197 | DONE: MOV AL, 20H ; EOI
|
---|
198 | OUT 0A0H, AL ; Slave PIC
|
---|
199 | OUT 20H, AL ; Master PIC
|
---|
200 | RET
|
---|
201 | PROFIL_TICK ENDP
|
---|
202 | ASSUME BP:NOTHING
|
---|
203 | ASSUME BX:NOTHING
|
---|
204 |
|
---|
205 |
|
---|
206 | ;
|
---|
207 | ; Suspend generating profiler interrupts.
|
---|
208 | ;
|
---|
209 | ; This should be done before executing real-mode-code. Call with
|
---|
210 | ; interrupts disabled!
|
---|
211 | ;
|
---|
212 | ; Important: PROFIL_RESUME must have been called at least once!
|
---|
213 | ;
|
---|
214 | ASSUME DS:SV_DATA
|
---|
215 | TALIGN 4
|
---|
216 | PROFIL_SUSPEND PROC NEAR
|
---|
217 | MOV PROFIL_RESUMED, FALSE
|
---|
218 | CMP PROFIL_SUSPENDED, FALSE
|
---|
219 | JNE SHORT DONE
|
---|
220 | MOV PROFIL_SUSPENDED, NOT FALSE
|
---|
221 | ;
|
---|
222 | ; Disable the RTC interrupt (IRQ8) in the slave interrupt controller
|
---|
223 | ;
|
---|
224 | IN AL, 0A1H
|
---|
225 | OR AL, 01H
|
---|
226 | CALL IO_DELAY
|
---|
227 | OUT 0A1H, AL
|
---|
228 | ;
|
---|
229 | ; Stop the RTC from generating interrupts
|
---|
230 | ;
|
---|
231 | MOV AL, 0BH
|
---|
232 | MOV AH, OLD_RTC_REG0B
|
---|
233 | CALL RTC_WRITE
|
---|
234 | ;
|
---|
235 | ; Restore the original interrupt rate
|
---|
236 | ;
|
---|
237 | MOV AL, 0AH
|
---|
238 | MOV AH, OLD_RTC_REG0A
|
---|
239 | CALL RTC_WRITE
|
---|
240 | CALL IO_DELAY
|
---|
241 | CALL RTC_CLEAN
|
---|
242 | DONE: RET
|
---|
243 | PROFIL_SUSPEND ENDP
|
---|
244 |
|
---|
245 |
|
---|
246 | ;
|
---|
247 | ; Resume generating profiler interrupts.
|
---|
248 | ;
|
---|
249 | ; This should be done after executing real-mode-code. Call with
|
---|
250 | ; interrupts disabled!
|
---|
251 | ;
|
---|
252 | ; Out: CY Cannot enable profiler interrupts
|
---|
253 | ;
|
---|
254 | ASSUME DS:SV_DATA
|
---|
255 | TALIGN 4
|
---|
256 | PROFIL_RESUME PROC NEAR
|
---|
257 | MOV PROFIL_SUSPENDED, FALSE
|
---|
258 | CMP PROFIL_RESUMED, FALSE
|
---|
259 | JNE SHORT DONE
|
---|
260 | MOV PROFIL_RESUMED, NOT FALSE
|
---|
261 | ;
|
---|
262 | ; Read and save the current values of RTC registers 0A and 0B
|
---|
263 | ;
|
---|
264 | MOV AL, 0AH
|
---|
265 | CALL RTC_READ
|
---|
266 | MOV OLD_RTC_REG0A, AL
|
---|
267 |
|
---|
268 | MOV AL, 0BH
|
---|
269 | CALL RTC_READ
|
---|
270 | MOV OLD_RTC_REG0B, AL
|
---|
271 | ;
|
---|
272 | ; Don't profile if RTC interrupts are used by someone else
|
---|
273 | ; or if square-wave output is enabled
|
---|
274 | ;
|
---|
275 | TEST AL, 78H
|
---|
276 | JNZ SHORT FAIL
|
---|
277 | ;
|
---|
278 | ; Set the interrupt rate to 1024Hz
|
---|
279 | ;
|
---|
280 | MOV AH, OLD_RTC_REG0A
|
---|
281 | AND AH, 0F0H
|
---|
282 | OR AH, 06H
|
---|
283 | MOV AL, 0AH
|
---|
284 | CALL RTC_WRITE
|
---|
285 | ;
|
---|
286 | ; Enable the RTC's periodic interrupt
|
---|
287 | ;
|
---|
288 | MOV AH, OLD_RTC_REG0B
|
---|
289 | OR AH, 40H ; Enable periodic interrupt
|
---|
290 | AND AH, NOT 30H ; Disable alarm & update-ended
|
---|
291 | MOV AL, 0BH ; interrupts
|
---|
292 | CALL RTC_WRITE
|
---|
293 | ;
|
---|
294 | ; Clear pending interrupts
|
---|
295 | ;
|
---|
296 | MOV AL, 0CH
|
---|
297 | CALL RTC_READ
|
---|
298 | ;
|
---|
299 | ; Enable the RTC interrupt (IRQ8) in the slave interrupt controller
|
---|
300 | ;
|
---|
301 | IN AL, 0A1H
|
---|
302 | AND AL, NOT 01H
|
---|
303 | CALL IO_DELAY
|
---|
304 | OUT 0A1H, AL
|
---|
305 | DONE: CLC
|
---|
306 | RET
|
---|
307 |
|
---|
308 | FAIL: CALL RTC_CLEAN
|
---|
309 | STC
|
---|
310 | RET
|
---|
311 | PROFIL_RESUME ENDP
|
---|
312 |
|
---|
313 |
|
---|
314 | ;
|
---|
315 | ; Read an RTC register
|
---|
316 | ;
|
---|
317 | ; In: AL Register number
|
---|
318 | ;
|
---|
319 | ; Out: AL Register contents
|
---|
320 | ;
|
---|
321 | ; Note: This routine enables NMIs
|
---|
322 | ; Call with interrupts disabled!
|
---|
323 | ;
|
---|
324 | TALIGN 4
|
---|
325 | RTC_READ PROC NEAR
|
---|
326 | OUT RTC_ADDR, AL
|
---|
327 | CALL IO_DELAY
|
---|
328 | IN AL, RTC_DATA
|
---|
329 | RET
|
---|
330 | RTC_READ ENDP
|
---|
331 |
|
---|
332 | ;
|
---|
333 | ; Write an RTC register
|
---|
334 | ;
|
---|
335 | ; In: AL Register number
|
---|
336 | ; AH Value
|
---|
337 | ;
|
---|
338 | ; Note: This routine enables NMIs
|
---|
339 | ; Call with interrupts disabled!
|
---|
340 | ;
|
---|
341 | TALIGN 4
|
---|
342 | RTC_WRITE PROC NEAR
|
---|
343 | OUT RTC_ADDR, AL
|
---|
344 | CALL IO_DELAY
|
---|
345 | MOV AL, AH
|
---|
346 | OUT RTC_DATA, AL
|
---|
347 | RET
|
---|
348 | RTC_WRITE ENDP
|
---|
349 |
|
---|
350 | ;
|
---|
351 | ; Set the RTC address register to 0CH
|
---|
352 | ;
|
---|
353 | ; (BIOS does this after reading or writing a RTC register.)
|
---|
354 | ;
|
---|
355 | ; Note: This routine enables NMIs
|
---|
356 | ;
|
---|
357 | TALIGN 4
|
---|
358 | RTC_CLEAN PROC NEAR
|
---|
359 | MOV AL, 0CH
|
---|
360 | OUT RTC_ADDR, AL
|
---|
361 | RET
|
---|
362 | RTC_CLEAN ENDP
|
---|
363 |
|
---|
364 | ;
|
---|
365 | ; Delay between two accesses to I/O ports of the same chip
|
---|
366 | ;
|
---|
367 | TALIGN 4
|
---|
368 | IO_DELAY PROC NEAR
|
---|
369 | MOV CX, 4
|
---|
370 | TALIGN 4
|
---|
371 | LOOP1: DEC CX
|
---|
372 | JNZ LOOP1
|
---|
373 | RET
|
---|
374 | IO_DELAY ENDP
|
---|
375 |
|
---|
376 | SV_CODE ENDS
|
---|
377 |
|
---|
378 | END
|
---|