- /*
- * Inhibit interrupts. Determine the incremental
- * time since the last interrupt. (This could be
- * done in assembler for a bit more speed).
- */
- do {
- READ_8254(val); /* read clock */
- READ_8254(val2); /* read clock */
- } while (val2 > val || val2 < val - 10);
- if (val > clks_per_int_99) {
- outb(0x0a, 0x20); /* see if interrupt pending */
- if (inb(0x20) & 1)
- result = rtclock.intr_nsec; /* yes, add a tick */
- }
- result += ((clks_per_int - val) * time_per_clk) / ZHZ;
- if (result < last_ival) {
- if (rtc_print_lost_tick)
- printf( "rtclock: missed clock interrupt.\n" );
- }
+ int x, y;
+ uint64_t cycles;
+ uint32_t c[15]; // array for holding sampled cycle counts
+ mach_timespec_t tst[15]; // array for holding time values. NOTE for some reason tv_sec not work
+
+ for (x=0; x<15; x++) { // quick sample 15 times
+ tst[x].tv_sec = 0;
+ tst[x].tv_nsec = 0;
+ sysclk_gettime_internal(&tst[x]);
+ rdtsc_hilo(&y, &c[x]);
+ }
+ y = 0;
+ cycles = 0;
+ for (x=0; x<14; x++) {
+ // simple formula really. calculate the numerator as the number of elapsed processor
+ // cycles * 1000 to adjust for the resolution we want. The denominator is the
+ // elapsed "real" time in nano-seconds. The result will be the processor speed in
+ // Mhz. any overflows will be discarded before they are added
+ if ((c[x+1] > c[x]) && (tst[x+1].tv_nsec > tst[x].tv_nsec)) {
+ cycles += ((uint64_t)(c[x+1]-c[x]) * NSEC_PER_SEC ) / (uint64_t)(tst[x+1].tv_nsec - tst[x].tv_nsec); // elapsed nsecs
+ y +=1;
+ }
+ }
+ if (y>0) { // we got more than 1 valid sample. This also takes care of the case of if the clock isn't running
+ cycles = cycles / y; // calc our average
+ }
+ rtc_cyc_per_sec = cycles;
+ rdtsc_hilo(&rtc_last_int_tsc_hi, &rtc_last_int_tsc_lo);
+}