| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <unistd.h> |
| #include <signal.h> |
| #include <inttypes.h> |
| #include <wait.h> |
| |
| |
| #include <sys/prctl.h> |
| #include <linux/prctl.h> |
| |
| |
| #ifndef PR_GET_TSC |
| #define PR_GET_TSC 25 |
| #define PR_SET_TSC 26 |
| # define PR_TSC_ENABLE 1 |
| # define PR_TSC_SIGSEGV 2 |
| #endif |
| |
| static uint64_t rdtsc(void) |
| { |
| uint32_t lo, hi; |
| |
| __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi)); |
| return (uint64_t)hi << 32 | lo; |
| } |
| |
| static void sigsegv_expect(int sig) |
| { |
| <------> |
| } |
| |
| static void segvtask(void) |
| { |
| <------>if (prctl(PR_SET_TSC, PR_TSC_SIGSEGV) < 0) |
| <------>{ |
| <------><------>perror("prctl"); |
| <------><------>exit(0); |
| <------>} |
| <------>signal(SIGSEGV, sigsegv_expect); |
| <------>alarm(10); |
| <------>rdtsc(); |
| <------>fprintf(stderr, "FATAL ERROR, rdtsc() succeeded while disabled\n"); |
| <------>exit(0); |
| } |
| |
| |
| static void sigsegv_fail(int sig) |
| { |
| <------>fprintf(stderr, "FATAL ERROR, rdtsc() failed while enabled\n"); |
| <------>exit(0); |
| } |
| |
| static void rdtsctask(void) |
| { |
| <------>if (prctl(PR_SET_TSC, PR_TSC_ENABLE) < 0) |
| <------>{ |
| <------><------>perror("prctl"); |
| <------><------>exit(0); |
| <------>} |
| <------>signal(SIGSEGV, sigsegv_fail); |
| <------>alarm(10); |
| <------>for(;;) rdtsc(); |
| } |
| |
| |
| int main(void) |
| { |
| <------>int n_tasks = 100, i; |
| |
| <------>fprintf(stderr, "[No further output means we're allright]\n"); |
| |
| <------>for (i=0; i<n_tasks; i++) |
| <------><------>if (fork() == 0) |
| <------><------>{ |
| <------><------><------>if (i & 1) |
| <------><------><------><------>segvtask(); |
| <------><------><------>else |
| <------><------><------><------>rdtsctask(); |
| <------><------>} |
| |
| <------>for (i=0; i<n_tasks; i++) |
| <------><------>wait(NULL); |
| |
| <------>exit(0); |
| } |
| |
| |