1
0

dev4ns.c 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. #include <sys/types.h>
  2. #include <fcntl.h>
  3. #include <time.h>
  4. #include <stdio.h>
  5. #include <unistd.h>
  6. #include <sys/time.h>
  7. static int fddev = -1;
  8. static int prev[3];
  9. static unsigned long long prevcycles = 0;
  10. static int now[3];
  11. static long long cyclespersec = 0;
  12. static void readdev(unsigned int *result)
  13. {
  14. if (read(fddev,result,12) == 12) return;
  15. result[0] = result[1] = result[2] = 0;
  16. }
  17. long long cpucycles_dev4ns(void)
  18. {
  19. unsigned long long delta4;
  20. int deltan;
  21. int deltas;
  22. unsigned long long guesscycles;
  23. if (fddev == -1) {
  24. fddev = open("/dev/cpucycles4ns",O_RDONLY);
  25. readdev(prev);
  26. }
  27. readdev(now);
  28. delta4 = (unsigned int) (now[0] - prev[0]); /* unsigned change in number of cycles mod 2^32 */
  29. deltan = now[1] - prev[1]; /* signed change in number of nanoseconds mod 10^9 */
  30. deltas = now[2] - prev[2]; /* signed change in number of seconds */
  31. if ((deltas == 0 && deltan < 200000000) || (deltas == 1 && deltan < -800000000))
  32. return prevcycles + delta4;
  33. prev[0] = now[0];
  34. prev[1] = now[1];
  35. prev[2] = now[2];
  36. if ((deltas == 0 && deltan < 300000000) || (deltas == 1 && deltan < -700000000)) {
  37. // actual number of cycles cannot have increased by 2^32 in <0.3ms
  38. cyclespersec = 1000000000 * (unsigned long long) delta4;
  39. cyclespersec /= deltan + 1000000000 * (long long) deltas;
  40. } else {
  41. guesscycles = deltas * cyclespersec;
  42. guesscycles += (deltan * cyclespersec) / 1000000000;
  43. while (delta4 + 2147483648ULL < guesscycles) delta4 += 4294967296ULL;
  44. /* XXX: could do longer-term extrapolation here */
  45. }
  46. prevcycles += delta4;
  47. return prevcycles;
  48. }
  49. long long cpucycles_dev4ns_persecond(void)
  50. {
  51. while (!cyclespersec) cpucycles_dev4ns();
  52. return cyclespersec;
  53. }