disable-tsc-ctxt-sw-stress-test.c 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. /*
  2. * Tests for prctl(PR_GET_TSC, ...) / prctl(PR_SET_TSC, ...)
  3. *
  4. * Tests if the control register is updated correctly
  5. * at context switches
  6. *
  7. * Warning: this test will cause a very high load for a few seconds
  8. *
  9. */
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <unistd.h>
  13. #include <signal.h>
  14. #include <inttypes.h>
  15. #include <wait.h>
  16. #include <sys/prctl.h>
  17. #include <linux/prctl.h>
  18. /* Get/set the process' ability to use the timestamp counter instruction */
  19. #ifndef PR_GET_TSC
  20. #define PR_GET_TSC 25
  21. #define PR_SET_TSC 26
  22. # define PR_TSC_ENABLE 1 /* allow the use of the timestamp counter */
  23. # define PR_TSC_SIGSEGV 2 /* throw a SIGSEGV instead of reading the TSC */
  24. #endif
  25. static uint64_t rdtsc(void)
  26. {
  27. uint32_t lo, hi;
  28. /* We cannot use "=A", since this would use %rax on x86_64 */
  29. __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
  30. return (uint64_t)hi << 32 | lo;
  31. }
  32. static void sigsegv_expect(int sig)
  33. {
  34. /* */
  35. }
  36. static void segvtask(void)
  37. {
  38. if (prctl(PR_SET_TSC, PR_TSC_SIGSEGV) < 0)
  39. {
  40. perror("prctl");
  41. exit(0);
  42. }
  43. signal(SIGSEGV, sigsegv_expect);
  44. alarm(10);
  45. rdtsc();
  46. fprintf(stderr, "FATAL ERROR, rdtsc() succeeded while disabled\n");
  47. exit(0);
  48. }
  49. static void sigsegv_fail(int sig)
  50. {
  51. fprintf(stderr, "FATAL ERROR, rdtsc() failed while enabled\n");
  52. exit(0);
  53. }
  54. static void rdtsctask(void)
  55. {
  56. if (prctl(PR_SET_TSC, PR_TSC_ENABLE) < 0)
  57. {
  58. perror("prctl");
  59. exit(0);
  60. }
  61. signal(SIGSEGV, sigsegv_fail);
  62. alarm(10);
  63. for(;;) rdtsc();
  64. }
  65. int main(int argc, char **argv)
  66. {
  67. int n_tasks = 100, i;
  68. fprintf(stderr, "[No further output means we're allright]\n");
  69. for (i=0; i<n_tasks; i++)
  70. if (fork() == 0)
  71. {
  72. if (i & 1)
  73. segvtask();
  74. else
  75. rdtsctask();
  76. }
  77. for (i=0; i<n_tasks; i++)
  78. wait(NULL);
  79. exit(0);
  80. }