Merge tag 'arc-3.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vgupta/arc
[sfrench/cifs-2.6.git] / Documentation / prctl / disable-tsc-ctxt-sw-stress-test.c
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
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <unistd.h>
14 #include <signal.h>
15 #include <inttypes.h>
16 #include <wait.h>
17
18
19 #include <sys/prctl.h>
20 #include <linux/prctl.h>
21
22 /* Get/set the process' ability to use the timestamp counter instruction */
23 #ifndef PR_GET_TSC
24 #define PR_GET_TSC 25
25 #define PR_SET_TSC 26
26 # define PR_TSC_ENABLE          1   /* allow the use of the timestamp counter */
27 # define PR_TSC_SIGSEGV         2   /* throw a SIGSEGV instead of reading the TSC */
28 #endif
29
30 static uint64_t rdtsc(void)
31 {
32 uint32_t lo, hi;
33 /* We cannot use "=A", since this would use %rax on x86_64 */
34 __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
35 return (uint64_t)hi << 32 | lo;
36 }
37
38 static void sigsegv_expect(int sig)
39 {
40         /* */
41 }
42
43 static void segvtask(void)
44 {
45         if (prctl(PR_SET_TSC, PR_TSC_SIGSEGV) < 0)
46         {
47                 perror("prctl");
48                 exit(0);
49         }
50         signal(SIGSEGV, sigsegv_expect);
51         alarm(10);
52         rdtsc();
53         fprintf(stderr, "FATAL ERROR, rdtsc() succeeded while disabled\n");
54         exit(0);
55 }
56
57
58 static void sigsegv_fail(int sig)
59 {
60         fprintf(stderr, "FATAL ERROR, rdtsc() failed while enabled\n");
61         exit(0);
62 }
63
64 static void rdtsctask(void)
65 {
66         if (prctl(PR_SET_TSC, PR_TSC_ENABLE) < 0)
67         {
68                 perror("prctl");
69                 exit(0);
70         }
71         signal(SIGSEGV, sigsegv_fail);
72         alarm(10);
73         for(;;) rdtsc();
74 }
75
76
77 int main(int argc, char **argv)
78 {
79         int n_tasks = 100, i;
80
81         fprintf(stderr, "[No further output means we're allright]\n");
82
83         for (i=0; i<n_tasks; i++)
84                 if (fork() == 0)
85                 {
86                         if (i & 1)
87                                 segvtask();
88                         else
89                                 rdtsctask();
90                 }
91
92         for (i=0; i<n_tasks; i++)
93                 wait(NULL);
94
95         exit(0);
96 }
97