Restartable sequences: tests: introduce simple rseq start/finish
[deliverable/linux.git] / tools / testing / selftests / rseq / basic_test.c
CommitLineData
b54c5158
MD
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
15volatile int signals_delivered;
16volatile __thread struct rseq_state sigtest_start;
17static struct rseq_lock rseq_lock;
18
19void 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 */
43void test_critical_section(void)
44{
45 struct rseq_state start;
46 uint32_t event_counter;
47
a2ac5f39 48 start = rseq_start_rlock(&rseq_lock);
b54c5158
MD
49 event_counter = start.event_counter;
50 do {
a2ac5f39 51 start = rseq_start_rlock(&rseq_lock);
b54c5158
MD
52 } while (start.event_counter == event_counter);
53}
54
55void test_signal_interrupt_handler(int signo)
56{
57 struct rseq_state current;
58
a2ac5f39 59 current = rseq_start_rlock(&rseq_lock);
b54c5158
MD
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
68void 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 {
a2ac5f39 76 sigtest_start = rseq_start_rlock(&rseq_lock);
b54c5158
MD
77 } while (signals_delivered < 10);
78 setitimer(ITIMER_PROF, NULL, NULL);
79}
80
81int 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
103init_thread_error:
104 if (rseq_destroy_lock(&rseq_lock))
105 perror("rseq_destroy_lock");
106 return -1;
107}
This page took 0.02833 seconds and 5 git commands to generate.