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