1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * Copyright 2016, Cyril Bur, IBM Corp. |
4 | * |
5 | * Sending one self a signal should always get delivered. |
6 | */ |
7 | |
8 | #include <errno.h> |
9 | #include <stdlib.h> |
10 | #include <stdio.h> |
11 | #include <string.h> |
12 | #include <signal.h> |
13 | #include <unistd.h> |
14 | |
15 | #include <altivec.h> |
16 | |
17 | #include "utils.h" |
18 | #include "../tm/tm.h" |
19 | |
20 | #define MAX_ATTEMPT 500000 |
21 | #define TIMEOUT 10 |
22 | |
23 | extern long tm_signal_self(pid_t pid, int sig, long *ret); |
24 | |
25 | static sig_atomic_t signaled; |
26 | static sig_atomic_t fail; |
27 | |
28 | static void signal_handler(int sig) |
29 | { |
30 | if (tcheck_active()) { |
31 | fail = 2; |
32 | return; |
33 | } |
34 | |
35 | if (sig == SIGUSR1) |
36 | signaled = 1; |
37 | else |
38 | fail = 1; |
39 | } |
40 | |
41 | static int test_signal_tm() |
42 | { |
43 | int i; |
44 | struct sigaction act; |
45 | |
46 | act.sa_handler = signal_handler; |
47 | act.sa_flags = 0; |
48 | sigemptyset(&act.sa_mask); |
49 | if (sigaction(SIGUSR1, &act, NULL) < 0) { |
50 | perror("sigaction SIGUSR1" ); |
51 | exit(1); |
52 | } |
53 | if (sigaction(SIGALRM, &act, NULL) < 0) { |
54 | perror("sigaction SIGALRM" ); |
55 | exit(1); |
56 | } |
57 | |
58 | SKIP_IF(!have_htm()); |
59 | SKIP_IF(htm_is_synthetic()); |
60 | |
61 | for (i = 0; i < MAX_ATTEMPT; i++) { |
62 | /* |
63 | * If anything bad happens in ASM and we fail to set ret |
64 | * because *handwave* TM this will cause failure |
65 | */ |
66 | long ret = 0xdead; |
67 | long rc = 0xbeef; |
68 | |
69 | alarm(0); /* Disable any pending */ |
70 | signaled = 0; |
71 | alarm(TIMEOUT); |
72 | FAIL_IF(tcheck_transactional()); |
73 | rc = tm_signal_self(getpid(), SIGUSR1, &ret); |
74 | if (ret == 0xdead) |
75 | /* |
76 | * This basically means the transaction aborted before we |
77 | * even got to the suspend... this is crazy but it |
78 | * happens. |
79 | * Yes this also means we might never make forward |
80 | * progress... the alarm() will trip eventually... |
81 | */ |
82 | continue; |
83 | |
84 | if (rc || ret) { |
85 | /* Ret is actually an errno */ |
86 | printf("TEXASR 0x%016lx, TFIAR 0x%016lx\n" , |
87 | __builtin_get_texasr(), __builtin_get_tfiar()); |
88 | fprintf(stderr, "(%d) Fail reason: %d rc=0x%lx ret=0x%lx\n" , |
89 | i, fail, rc, ret); |
90 | FAIL_IF(ret); |
91 | } |
92 | while(!signaled && !fail) |
93 | asm volatile("" : : :"memory" ); |
94 | if (!signaled) { |
95 | fprintf(stderr, "(%d) Fail reason: %d rc=0x%lx ret=0x%lx\n" , |
96 | i, fail, rc, ret); |
97 | FAIL_IF(fail); /* For the line number */ |
98 | } |
99 | } |
100 | |
101 | return 0; |
102 | } |
103 | |
104 | int main(void) |
105 | { |
106 | return test_harness(test_signal_tm, "signal_tm" ); |
107 | } |
108 | |