prof_machdep.c revision 13107
1#include <sys/param.h> 2#include <sys/systm.h> 3#include <machine/clock.h> 4#include <i386/isa/isa.h> 5#include <i386/isa/timerreg.h> 6 7#ifdef GUPROF 8extern u_int cputime __P((void)); 9#endif 10 11#ifdef __GNUC__ 12asm(" 13GM_STATE = 0 14GMON_PROF_OFF = 3 15 16 .text 17 .align 4,0x90 18 .globl __mcount 19__mcount: 20 # 21 # Check that we are profiling. Do it early for speed. 22 # 23 cmpl $GMON_PROF_OFF,__gmonparam+GM_STATE 24 je Lmcount_exit 25 # 26 # __mcount is the same as mcount except the caller hasn't changed 27 # the stack except to call here, so the caller's raddr is above 28 # our raddr. 29 # 30 movl 4(%esp),%edx 31 jmp Lgot_frompc 32 33 .align 4,0x90 34 .globl mcount 35mcount: 36 cmpl $GMON_PROF_OFF,__gmonparam+GM_STATE 37 je Lmcount_exit 38 # 39 # The caller's stack frame has already been built, so %ebp is 40 # the caller's frame pointer. The caller's raddr is in the 41 # caller's frame following the caller's caller's frame pointer. 42 # 43 movl 4(%ebp),%edx 44Lgot_frompc: 45 # 46 # Our raddr is the caller's pc. 47 # 48 movl (%esp),%eax 49 50 pushf 51 pushl %eax 52 pushl %edx 53 cli 54 call _mcount 55 addl $8,%esp 56 popf 57Lmcount_exit: 58 ret 59"); 60#else /* !__GNUC__ */ 61#error 62#endif /* __GNUC__ */ 63 64#ifdef GUPROF 65/* 66 * mexitcount saves the return register(s), loads selfpc and calls 67 * mexitcount(selfpc) to do the work. Someday it should be in a machine 68 * dependent file together with cputime(), __mcount and mcount. cputime() 69 * can't just be put in machdep.c because it has to be compiled without -pg. 70 */ 71#ifdef __GNUC__ 72asm(" 73 .text 74# 75# Dummy label to be seen when gprof -u hides mexitcount. 76# 77 .align 4,0x90 78 .globl __mexitcount 79__mexitcount: 80 nop 81 82GMON_PROF_HIRES = 4 83 84 .align 4,0x90 85 .globl mexitcount 86mexitcount: 87 cmpl $GMON_PROF_HIRES,__gmonparam+GM_STATE 88 jne Lmexitcount_exit 89 pushl %edx 90 pushl %eax 91 movl 8(%esp),%eax 92 pushf 93 pushl %eax 94 cli 95 call _mexitcount 96 addl $4,%esp 97 popf 98 popl %eax 99 popl %edx 100Lmexitcount_exit: 101 ret 102"); 103#else /* !__GNUC__ */ 104#error 105#endif /* __GNUC__ */ 106 107/* 108 * Return the time elapsed since the last call. The units are machine- 109 * dependent. 110 */ 111u_int 112cputime() 113{ 114 u_int count; 115 u_int delta; 116 u_char low; 117 static u_int prev_count; 118 119 /* 120 * Read the current value of the 8254 timer counter 0. 121 */ 122 outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH); 123 low = inb(TIMER_CNTR0); 124 count = low | (inb(TIMER_CNTR0) << 8); 125 126 /* 127 * The timer counts down from TIMER_CNTR0_MAX to 0 and then resets. 128 * While profiling is enabled, this routine is called at least twice 129 * per timer reset (for mcounting and mexitcounting hardclock()), 130 * so at most one reset has occurred since the last call, and one 131 * has occurred iff the current count is larger than the previous 132 * count. This allows counter underflow to be detected faster 133 * than in microtime(). 134 */ 135 delta = prev_count - count; 136 prev_count = count; 137 if ((int) delta <= 0) 138 return (delta + timer0_max_count); 139 return (delta); 140} 141#else /* not GUPROF */ 142#ifdef __GNUC__ 143asm(" 144 .text 145 .align 4,0x90 146 .globl mexitcount 147mexitcount: 148 ret 149"); 150#else /* !__GNUC__ */ 151#error 152#endif /* __GNUC__ */ 153#endif /* GUPROF */ 154