]>
Commit | Line | Data |
---|---|---|
7fe924d9 S |
1 | /* |
2 | * Copyright 2015, Sam Bobroff, IBM Corp. | |
3 | * Licensed under GPLv2. | |
4 | * | |
5 | * Test the kernel's system call code to ensure that a system call | |
6 | * made from within an active HTM transaction is aborted with the | |
7 | * correct failure code. | |
8 | * Conversely, ensure that a system call made from within a | |
9 | * suspended transaction can succeed. | |
10 | */ | |
11 | ||
12 | #include <stdio.h> | |
13 | #include <unistd.h> | |
14 | #include <sys/syscall.h> | |
15 | #include <asm/tm.h> | |
7fe924d9 S |
16 | #include <sys/time.h> |
17 | #include <stdlib.h> | |
18 | ||
19 | #include "utils.h" | |
34dc8b27 | 20 | #include "tm.h" |
7fe924d9 S |
21 | |
22 | extern int getppid_tm_active(void); | |
23 | extern int getppid_tm_suspended(void); | |
24 | ||
25 | unsigned retries = 0; | |
26 | ||
27 | #define TEST_DURATION 10 /* seconds */ | |
28 | #define TM_RETRIES 100 | |
29 | ||
7fe924d9 S |
30 | pid_t getppid_tm(bool suspend) |
31 | { | |
32 | int i; | |
33 | pid_t pid; | |
34 | ||
35 | for (i = 0; i < TM_RETRIES; i++) { | |
36 | if (suspend) | |
37 | pid = getppid_tm_suspended(); | |
38 | else | |
39 | pid = getppid_tm_active(); | |
40 | ||
41 | if (pid >= 0) | |
42 | return pid; | |
43 | ||
44 | if (failure_is_persistent()) { | |
45 | if (failure_is_syscall()) | |
46 | return -1; | |
47 | ||
48 | printf("Unexpected persistent transaction failure.\n"); | |
49 | printf("TEXASR 0x%016lx, TFIAR 0x%016lx.\n", | |
50 | __builtin_get_texasr(), __builtin_get_tfiar()); | |
51 | exit(-1); | |
52 | } | |
53 | ||
54 | retries++; | |
55 | } | |
56 | ||
57 | printf("Exceeded limit of %d temporary transaction failures.\n", TM_RETRIES); | |
58 | printf("TEXASR 0x%016lx, TFIAR 0x%016lx.\n", | |
59 | __builtin_get_texasr(), __builtin_get_tfiar()); | |
60 | ||
61 | exit(-1); | |
62 | } | |
63 | ||
64 | int tm_syscall(void) | |
65 | { | |
66 | unsigned count = 0; | |
67 | struct timeval end, now; | |
68 | ||
20d09927 ME |
69 | SKIP_IF(!have_htm_nosc()); |
70 | ||
7fe924d9 S |
71 | setbuf(stdout, NULL); |
72 | ||
73 | printf("Testing transactional syscalls for %d seconds...\n", TEST_DURATION); | |
74 | ||
75 | gettimeofday(&end, NULL); | |
76 | now.tv_sec = TEST_DURATION; | |
77 | now.tv_usec = 0; | |
78 | timeradd(&end, &now, &end); | |
79 | ||
80 | for (count = 0; timercmp(&now, &end, <); count++) { | |
81 | /* | |
82 | * Test a syscall within a suspended transaction and verify | |
83 | * that it succeeds. | |
84 | */ | |
85 | FAIL_IF(getppid_tm(true) == -1); /* Should succeed. */ | |
86 | ||
87 | /* | |
88 | * Test a syscall within an active transaction and verify that | |
89 | * it fails with the correct failure code. | |
90 | */ | |
91 | FAIL_IF(getppid_tm(false) != -1); /* Should fail... */ | |
92 | FAIL_IF(!failure_is_persistent()); /* ...persistently... */ | |
93 | FAIL_IF(!failure_is_syscall()); /* ...with code syscall. */ | |
94 | gettimeofday(&now, 0); | |
95 | } | |
96 | ||
97 | printf("%d active and suspended transactions behaved correctly.\n", count); | |
98 | printf("(There were %d transaction retries.)\n", retries); | |
99 | ||
100 | return 0; | |
101 | } | |
102 | ||
103 | int main(void) | |
104 | { | |
105 | return test_harness(tm_syscall, "tm_syscall"); | |
106 | } |