1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
/*
* Verify that unwinding from a signal handler works when variable width
* SVE registers are pushed onto the stack
*/
#if defined(__ARM_FEATURE_SVE) && defined(__ARM_FEATURE_SVE_VECTOR_OPERATORS)
#include <arm_sve.h>
#include <libunwind.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
int64_t z[100];
void signal_handler(int signum)
{
unw_cursor_t cursor;
unw_context_t context;
const char* expected[] = {
"signal_frame",
"kill",
"sum",
"square",
"main",
};
unw_getcontext(&context);
unw_init_local(&cursor, &context);
for (unsigned int depth = 0; depth < sizeof(expected) / sizeof(expected[0]); ++depth)
{
unw_word_t offset, pc;
int unw_rc = unw_step(&cursor);
if (unw_rc <= 0) {
printf("Frame: %d unw_step error: %d\n", depth, unw_rc);
exit(-1);
}
unw_rc = unw_get_reg(&cursor, UNW_REG_IP, &pc);
if (pc == 0 || unw_rc != 0) {
printf("Frame: %d unw_get_reg error: %d\n", depth, unw_rc);
exit(-1);
}
char sym[256];
unw_rc = unw_is_signal_frame(&cursor);
if (unw_rc > 0)
{
strcpy(sym, "signal_frame");
}
else if (unw_rc < 0)
{
printf("Frame: %d unw_is_signal_frame error: %d\n", depth, unw_rc);
exit(-1);
}
else
{
unw_rc = unw_get_proc_name(&cursor, sym, sizeof(sym), &offset);
if (unw_rc)
{
printf("Frame: %d unw_get_proc_name error: %d\n", depth, unw_rc);
exit(-1);
}
}
if (strcmp(sym, expected[depth]) != 0)
{
printf("Frame: %d expected %s but found %s\n", depth, expected[depth], sym);
exit(-1);
}
}
exit(0); /* PASS */
}
int64_t sum(svint64_t z0)
{
int64_t ret = svaddv_s64(svptrue_b64(), z0);
kill (getpid (), SIGUSR1);
return ret;
}
int64_t square(svint64_t z0)
{
int64_t res = 0;
for (int i = 0; i < 100; ++i)
{
z0 = svmul_s64_z(svptrue_b64(), z0, z0);
res += sum(z0);
}
return res;
}
int main()
{
signal(SIGUSR1, signal_handler);
for (unsigned int i = 0; i < sizeof(z) / sizeof(z[0]); ++i)
z[i] = rand();
svint64_t z0 = svld1(svptrue_b64(), &z[0]);
square(z0);
/*
* Shouldn't get here, exit is called from signal handler
*/
printf("Signal handler wasn't called\n");
return -1;
}
#else /* !__ARM_FEATURE_SVE */
int
main ()
{
return 77; /* SKIP */
}
#endif
|