Restartable sequences: tests: introduce simple rseq start/finish
[deliverable/linux.git] / tools / testing / selftests / rseq / basic_test.c
1 /*
2 * Basic test coverage for critical regions and rseq_current_cpu().
3 */
4
5 #define _GNU_SOURCE
6 #include <assert.h>
7 #include <sched.h>
8 #include <signal.h>
9 #include <stdio.h>
10 #include <string.h>
11 #include <sys/time.h>
12
13 #include <rseq.h>
14
15 volatile int signals_delivered;
16 volatile __thread struct rseq_state sigtest_start;
17 static struct rseq_lock rseq_lock;
18
19 void test_cpu_pointer(void)
20 {
21 cpu_set_t affinity, test_affinity;
22 int i;
23
24 sched_getaffinity(0, sizeof(affinity), &affinity);
25 CPU_ZERO(&test_affinity);
26 for (i = 0; i < CPU_SETSIZE; i++) {
27 if (CPU_ISSET(i, &affinity)) {
28 CPU_SET(i, &test_affinity);
29 sched_setaffinity(0, sizeof(test_affinity),
30 &test_affinity);
31 assert(rseq_current_cpu() == sched_getcpu());
32 assert(rseq_current_cpu() == i);
33 CPU_CLR(i, &test_affinity);
34 }
35 }
36 sched_setaffinity(0, sizeof(affinity), &affinity);
37 }
38
39 /*
40 * This depends solely on some environmental event triggering a counter
41 * increase.
42 */
43 void test_critical_section(void)
44 {
45 struct rseq_state start;
46 uint32_t event_counter;
47
48 start = rseq_start_rlock(&rseq_lock);
49 event_counter = start.event_counter;
50 do {
51 start = rseq_start_rlock(&rseq_lock);
52 } while (start.event_counter == event_counter);
53 }
54
55 void test_signal_interrupt_handler(int signo)
56 {
57 struct rseq_state current;
58
59 current = rseq_start_rlock(&rseq_lock);
60 /*
61 * The potential critical section bordered by 'start' must be
62 * invalid.
63 */
64 assert(current.event_counter != sigtest_start.event_counter);
65 signals_delivered++;
66 }
67
68 void test_signal_interrupts(void)
69 {
70 struct itimerval it = { { 0, 1 }, { 0, 1 } };
71
72 setitimer(ITIMER_PROF, &it, NULL);
73 signal(SIGPROF, test_signal_interrupt_handler);
74
75 do {
76 sigtest_start = rseq_start_rlock(&rseq_lock);
77 } while (signals_delivered < 10);
78 setitimer(ITIMER_PROF, NULL, NULL);
79 }
80
81 int main(int argc, char **argv)
82 {
83 if (rseq_init_lock(&rseq_lock)) {
84 perror("rseq_init_lock");
85 return -1;
86 }
87 if (rseq_register_current_thread())
88 goto init_thread_error;
89 printf("testing current cpu\n");
90 test_cpu_pointer();
91 printf("testing critical section\n");
92 test_critical_section();
93 printf("testing critical section is interrupted by signal\n");
94 test_signal_interrupts();
95 if (rseq_unregister_current_thread())
96 goto init_thread_error;
97 if (rseq_destroy_lock(&rseq_lock)) {
98 perror("rseq_destroy_lock");
99 return -1;
100 }
101 return 0;
102
103 init_thread_error:
104 if (rseq_destroy_lock(&rseq_lock))
105 perror("rseq_destroy_lock");
106 return -1;
107 }
This page took 0.032273 seconds and 5 git commands to generate.