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