7 static unsigned long ticks;
12 INTERFACE[{ia32,amd64}-!profile]:
19 IMPLEMENTATION[profile]:
27 #include "mem_layout.h"
30 #include "processor.h"
31 #include "unistd.h" // pr_base, pr_off, pr_size, pr_scale
32 #include "thread.h" // for stack checking
34 unsigned long Profile::ticks = 0;
35 bool Profile::exit = false;
37 static bool profile_active = false;
39 extern "C" void profile_interrupt_entry();
48 // We assume that our member functions generally are called in cli
51 // set up profiling and initialize profiling interrupt
56 atexit(dump_if_active);
57 Idt::set_entry (0x20 + Config::profile_irq,
58 (unsigned) profile_interrupt_entry, false);
67 monstartup((char*)&Mem_layout::start, (char*)&Mem_layout::end,
68 Config::profiling_rate);
69 profile_active = true;
70 Pit::init(Config::profiling_rate);
71 Pic::enable(Config::profile_irq);
81 Pic::disable(Config::profile_irq);
83 profile_active = false;
89 Profile::stop_and_dump()
93 Pic::disable(Config::profile_irq);
95 profile_active = false;
99 // irq routine invoked by profile_interrupt_entry in entry.S
102 * Scale is a fixed-point number with the binary point 16 bits
103 * into the value, and is <= 1.0. pc is at most 32 bits, so the
104 * intermediate result is at most 48 bits.
106 #define PC_TO_INDEX(pc, off, scale) \
107 ((Address)(((unsigned long long)((pc) - (off)) * \
108 (unsigned long long)((scale))) >> 16) & ~1)
110 PUBLIC static inline NOEXPORT
112 Profile::handle_profile_interrupt(Address pc)
114 // runs with disabled irqs
115 Pic::disable_locked(Config::profile_irq);
116 Pic::acknowledge_locked(Config::profile_irq);
117 Pic::enable_locked(Config::profile_irq);
127 || (i = PC_TO_INDEX(pc, pr_off, pr_scale)) >= pr_size)
128 return; // out of range - ignore
130 *reinterpret_cast<unsigned short*>(pr_base + i) += 1;
136 extern "C" FIASCO_FASTCALL
138 profile_interrupt(Address pc)
140 Profile::handle_profile_interrupt(pc);
145 profile_mcount_wrap(unsigned short *frompcindex, char *selfpc )
147 // For lack of a better place, so stack checking here:
149 static bool overrun = false;
152 Address sp = Proc::stack_pointer();
153 if (((Address)current()) + sizeof(Thread) + 0x20 > sp)
156 panic("stack overrun: current=0x%x, esp=0x%x",
157 (Address)current(), sp);
161 __mcount_internal (frompcindex, selfpc);
164 /* The GNU Glibc has this to say:
166 We need a special version of the `mcount' function since for ix86 it
167 must not clobber any register. This has several reasons:
168 - there is a bug in gcc as of version 2.7.2.2 which prohibits the
169 use of profiling together with nested functions
170 - the ELF `fixup' function uses GCC's regparm feature
171 - some (future) systems might want to pass parameters in registers. */
174 #define STR(x) __STR(x)
176 asm(".p2align 4 \n\t"
183 "movl 12(%esp), %eax \n\t"
184 "movl 4(%ebp), %ecx \n\t"
188 "call " STR(profile_mcount_wrap) "\n\t"
197 //---------------------------------------------------------------------------
198 IMPLEMENTATION[{ia32,amd64}-!profile]:
200 PUBLIC static inline void Profile::init() {}
201 PUBLIC static inline void Profile::start() {}
202 PUBLIC static inline void Profile::stop() {}
203 PUBLIC static inline void Profile::stop_and_dump() {}