0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include <stdio.h>
0013 #include <stdlib.h>
0014 #include <unistd.h>
0015 #include <signal.h>
0016 #include <inttypes.h>
0017 #include <wait.h>
0018
0019
0020 #include <sys/prctl.h>
0021 #include <linux/prctl.h>
0022
0023
0024 #ifndef PR_GET_TSC
0025 #define PR_GET_TSC 25
0026 #define PR_SET_TSC 26
0027 # define PR_TSC_ENABLE 1
0028 # define PR_TSC_SIGSEGV 2
0029 #endif
0030
0031
0032
0033 static uint64_t rdtsc(void)
0034 {
0035 uint32_t lo, hi;
0036
0037 __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
0038 return (uint64_t)hi << 32 | lo;
0039 }
0040
0041 int should_segv = 0;
0042
0043 static void sigsegv_cb(int sig)
0044 {
0045 if (!should_segv)
0046 {
0047 fprintf(stderr, "FATAL ERROR, rdtsc() failed while enabled\n");
0048 exit(0);
0049 }
0050 if (prctl(PR_SET_TSC, PR_TSC_ENABLE) < 0)
0051 {
0052 perror("prctl");
0053 exit(0);
0054 }
0055 should_segv = 0;
0056
0057 rdtsc();
0058 }
0059
0060 static void task(void)
0061 {
0062 signal(SIGSEGV, sigsegv_cb);
0063 alarm(10);
0064 for(;;)
0065 {
0066 rdtsc();
0067 if (should_segv)
0068 {
0069 fprintf(stderr, "FATAL ERROR, rdtsc() succeeded while disabled\n");
0070 exit(0);
0071 }
0072 if (prctl(PR_SET_TSC, PR_TSC_SIGSEGV) < 0)
0073 {
0074 perror("prctl");
0075 exit(0);
0076 }
0077 should_segv = 1;
0078 }
0079 }
0080
0081
0082 int main(void)
0083 {
0084 int n_tasks = 100, i;
0085
0086 fprintf(stderr, "[No further output means we're allright]\n");
0087
0088 for (i=0; i<n_tasks; i++)
0089 if (fork() == 0)
0090 task();
0091
0092 for (i=0; i<n_tasks; i++)
0093 wait(NULL);
0094
0095 exit(0);
0096 }
0097