* Return the time elapsed since the last call. The units are machine- * dependent. */
| 192 | * dependent. |
| 193 | */ |
| 194 | int |
| 195 | cputime() |
| 196 | { |
| 197 | u_int count; |
| 198 | int delta; |
| 199 | #if (defined(I586_CPU) || defined(I686_CPU)) && \ |
| 200 | defined(PERFMON) && defined(I586_PMC_GUPROF) && !defined(SMP) |
| 201 | u_quad_t event_count; |
| 202 | #endif |
| 203 | u_char high, low; |
| 204 | static u_int prev_count; |
| 205 | |
| 206 | #if defined(I586_CPU) || defined(I686_CPU) |
| 207 | if (cputime_clock == CPUTIME_CLOCK_TSC) { |
| 208 | /* |
| 209 | * Scale the TSC a little to make cputime()'s frequency |
| 210 | * fit in an int, assuming that the TSC frequency fits |
| 211 | * in a u_int. Use a fixed scale since dynamic scaling |
| 212 | * would be slower and we can't really use the low bit |
| 213 | * of precision. |
| 214 | */ |
| 215 | count = (u_int)rdtsc() & ~1u; |
| 216 | delta = (int)(count - prev_count) >> 1; |
| 217 | prev_count = count; |
| 218 | return (delta); |
| 219 | } |
| 220 | #if defined(PERFMON) && defined(I586_PMC_GUPROF) && !defined(SMP) |
| 221 | if (cputime_clock == CPUTIME_CLOCK_I586_PMC) { |
| 222 | /* |
| 223 | * XXX permon_read() should be inlined so that the |
| 224 | * perfmon module doesn't need to be compiled with |
| 225 | * profiling disabled and so that it is fast. |
| 226 | */ |
| 227 | perfmon_read(0, &event_count); |
| 228 | |
| 229 | count = (u_int)event_count; |
| 230 | delta = (int)(count - prev_count); |
| 231 | prev_count = count; |
| 232 | return (delta); |
| 233 | } |
| 234 | #endif /* PERFMON && I586_PMC_GUPROF && !SMP */ |
| 235 | #endif /* I586_CPU || I686_CPU */ |
| 236 | |
| 237 | /* |
| 238 | * Read the current value of the 8254 timer counter 0. |
| 239 | */ |
| 240 | outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH); |
| 241 | low = inb(TIMER_CNTR0); |
| 242 | high = inb(TIMER_CNTR0); |
| 243 | count = ((high << 8) | low) << CPUTIME_CLOCK_I8254_SHIFT; |
| 244 | |
| 245 | /* |
| 246 | * The timer counts down from TIMER_CNTR0_MAX to 0 and then resets. |
| 247 | * While profiling is enabled, this routine is called at least twice |
| 248 | * per timer reset (for mcounting and mexitcounting hardclock()), |
| 249 | * so at most one reset has occurred since the last call, and one |
| 250 | * has occurred iff the current count is larger than the previous |
| 251 | * count. This allows counter underflow to be detected faster |
no test coverage detected