/* The following contains adapted code from the kernel, thus is Licensed under the GPLv2 */ #include #define HZ 1000 #define NSEC_PER_SEC 1000000000LL #define PMTMR_TICKS_PER_SEC 3579545 #define CLOCK_TICK_RATE 1193182 #define LATCH ((CLOCK_TICK_RATE + HZ/2) / HZ) /* For divider */ #define CLOCK_TICK_OVERFLOW (LATCH * HZ - CLOCK_TICK_RATE) #define SH_DIV(NOM,DEN,LSH) ( (((NOM) / (DEN)) << (LSH)) \ + ((((NOM) % (DEN)) << (LSH)) + (DEN) / 2) / (DEN)) #define ACTHZ (SH_DIV (CLOCK_TICK_RATE, LATCH, 8)) #define NSEC_PER_JIFFY ((unsigned long)((((unsigned long long)NSEC_PER_SEC)<<8)/ACTHZ)) #define CLOCK_TICK_ADJUST 0 #define XCLOCK_TICK_ADJUST (((long long)CLOCK_TICK_OVERFLOW * NSEC_PER_SEC) / \ (long long)CLOCK_TICK_RATE) unsigned long hz2mult(unsigned long hz, unsigned long shift) { unsigned long long tmp = NSEC_PER_SEC << shift; return (tmp + hz/2)/hz; } void calculate_values(char* name, unsigned long mult, unsigned long shift, unsigned long ntp_hz) { unsigned long long tmp; unsigned long long length_nsec = (NSEC_PER_SEC + CLOCK_TICK_ADJUST); unsigned long long interval_length = length_nsec/ntp_hz; long long error; // printf("\n%s\n==========\n", name); printf("%s ", name); tmp = interval_length; tmp <<= shift; tmp += mult/2; tmp /= mult; if(tmp == 0) { printf("dived to zero!\n"); tmp = 1; } // printf("%llu cycles per %llu ns\n", tmp, interval_length); // printf("%llu ns per cycle\n", (1*mult)>>shift); // printf("%llu ns per interval\n", (tmp*mult)>>shift); error = ((interval_length*ntp_hz) << shift) - ((tmp*ntp_hz*mult)); error >>= shift; printf("%lld ppb error\n",error); } void main(void) { unsigned long shift, mult; printf("HZ=%ld CLOCK_TICK_ADJUST=%ld\n", HZ, CLOCK_TICK_ADJUST); /* jiffies */ calculate_values("jiffies ", NSEC_PER_JIFFY << 8, 8, HZ); calculate_values("jiffies NOHZ", NSEC_PER_JIFFY << 8, 8, 2); /* pit */ calculate_values("pit ", hz2mult(CLOCK_TICK_RATE,20), 20, HZ); calculate_values("pit NOHZ", hz2mult(CLOCK_TICK_RATE,20), 20, 2); /* acpi_pm */ calculate_values("acpi_pm ", hz2mult(PMTMR_TICKS_PER_SEC,22), 22, HZ); calculate_values("acpi_pm NOHZ", hz2mult(PMTMR_TICKS_PER_SEC,22), 22, 2); printf("\n"); }