111
|
1 /* { dg-do run } */
|
|
2 /* { dg-require-effective-target split_stack } */
|
|
3 /* { dg-require-effective-target pthread_h } */
|
|
4 /* { dg-require-effective-target ucontext_h } */
|
|
5 /* { dg-options "-pthread -fsplit-stack" } */
|
|
6
|
|
7 #include <stdlib.h>
|
|
8 #include <pthread.h>
|
|
9 #include <ucontext.h>
|
|
10
|
|
11 extern void __splitstack_getcontext (void *context[10]);
|
|
12
|
|
13 extern void __splitstack_setcontext (void *context[10]);
|
|
14
|
|
15 extern void *__splitstack_makecontext (size_t, void *context[10], size_t *);
|
|
16
|
|
17 extern void __splitstack_block_signals (int *, int *);
|
|
18
|
|
19 extern void __splitstack_block_signals_context (void *context[10], int *,
|
|
20 int *);
|
|
21
|
|
22 extern void *__splitstack_find (void *, void *, size_t *, void **, void **,
|
|
23 void **);
|
|
24
|
|
25 extern void *__splitstack_find_context (void *context[10], size_t *, void **,
|
|
26 void **, void **);
|
|
27
|
|
28 static ucontext_t c1;
|
|
29 static void *s1[10];
|
|
30
|
|
31 static ucontext_t c2;
|
|
32 static void *s2[10];
|
|
33
|
|
34 static void swap (ucontext_t *, void *fs[10], ucontext_t *, void *ts[10])
|
|
35 __attribute__ ((no_split_stack));
|
|
36
|
|
37 static void
|
|
38 swap (ucontext_t *fu, void *fs[10], ucontext_t *tu, void *ts[10])
|
|
39 {
|
|
40 __splitstack_getcontext (fs);
|
|
41 __splitstack_setcontext (ts);
|
|
42 swapcontext (fu, tu);
|
|
43 __splitstack_setcontext (fs);
|
|
44 }
|
|
45
|
|
46 /* Use a noinline function to ensure that the buffer is not removed
|
|
47 from the stack. */
|
|
48 static void use_buffer (char *buf) __attribute__ ((noinline));
|
|
49 static void
|
|
50 use_buffer (char *buf)
|
|
51 {
|
|
52 buf[0] = '\0';
|
|
53 }
|
|
54
|
|
55 static void
|
|
56 down (int i, const char *msg, ucontext_t *me, void *mes[10],
|
|
57 ucontext_t *other, void *others[10])
|
|
58 {
|
|
59 char buf[10000];
|
|
60
|
|
61 if (i > 0)
|
|
62 {
|
|
63 use_buffer (buf);
|
|
64 swap (me, mes, other, others);
|
|
65 down (i - 1, msg, me, mes, other, others);
|
|
66 }
|
|
67 else
|
|
68 {
|
|
69 int c = 0;
|
|
70 void *stack;
|
|
71 size_t stack_size;
|
|
72 void *next_segment = NULL;
|
|
73 void *next_sp = NULL;
|
|
74 void *initial_sp = NULL;
|
|
75
|
|
76 stack = __splitstack_find_context (mes, &stack_size, &next_segment,
|
|
77 &next_sp, &initial_sp);
|
|
78 if (stack != NULL)
|
|
79 {
|
|
80 ++c;
|
|
81 while (__splitstack_find (next_segment, next_sp, &stack_size,
|
|
82 &next_segment, &next_sp, &initial_sp)
|
|
83 != NULL)
|
|
84 ++c;
|
|
85 }
|
|
86 }
|
|
87 }
|
|
88
|
|
89 static void
|
|
90 go1 (void)
|
|
91 {
|
|
92 down (1000, "go1", &c1, s1, &c2, s2);
|
|
93 pthread_exit (NULL);
|
|
94 }
|
|
95
|
|
96 static void
|
|
97 go2 (void)
|
|
98 {
|
|
99 down (1000, "go2", &c2, s2, &c1, s1);
|
|
100 pthread_exit (NULL);
|
|
101 }
|
|
102
|
|
103 struct thread_context
|
|
104 {
|
|
105 ucontext_t *u;
|
|
106 void **s;
|
|
107 };
|
|
108
|
|
109 static void *start_thread (void *) __attribute__ ((no_split_stack));
|
|
110
|
|
111 static void *
|
|
112 start_thread (void *context)
|
|
113 {
|
|
114 struct thread_context *tc = (struct thread_context *) context;
|
|
115 int block;
|
|
116
|
|
117 block = 0;
|
|
118 __splitstack_block_signals (&block, NULL);
|
|
119 __splitstack_setcontext (tc->s);
|
|
120 setcontext (tc->u);
|
|
121 abort ();
|
|
122 }
|
|
123
|
|
124 int
|
|
125 main (int argc __attribute__ ((unused)), char **argv __attribute__ ((unused)))
|
|
126 {
|
|
127 pthread_t tid;
|
|
128 int err;
|
|
129 size_t size;
|
|
130 struct thread_context tc;
|
|
131 int block;
|
|
132
|
|
133 if (getcontext (&c1) < 0)
|
|
134 abort ();
|
|
135
|
|
136 c2 = c1;
|
|
137
|
|
138 c1.uc_stack.ss_sp = __splitstack_makecontext (8192, &s1[0], &size);
|
|
139 if (c1.uc_stack.ss_sp == NULL)
|
|
140 abort ();
|
|
141 c1.uc_stack.ss_flags = 0;
|
|
142 c1.uc_stack.ss_size = size;
|
|
143 c1.uc_link = NULL;
|
|
144 block = 0;
|
|
145 __splitstack_block_signals_context (&s1[0], &block, NULL);
|
|
146 makecontext (&c1, go1, 0);
|
|
147
|
|
148 c2.uc_stack.ss_sp = __splitstack_makecontext (8192, &s2[0], &size);
|
|
149 if (c2.uc_stack.ss_sp == NULL)
|
|
150 abort ();
|
|
151 c2.uc_stack.ss_flags = 0;
|
|
152 c2.uc_stack.ss_size = size;
|
|
153 c2.uc_link = NULL;
|
|
154 __splitstack_block_signals_context (&s2[0], &block, NULL);
|
|
155 makecontext (&c2, go2, 0);
|
|
156
|
|
157 block = 0;
|
|
158 __splitstack_block_signals (&block, NULL);
|
|
159
|
|
160 tc.u = &c1;
|
|
161 tc.s = &s1[0];
|
|
162 err = pthread_create (&tid, NULL, start_thread, &tc);
|
|
163 if (err != 0)
|
|
164 abort ();
|
|
165
|
|
166 err = pthread_join (tid, NULL);
|
|
167 if (err != 0)
|
|
168 abort ();
|
|
169
|
|
170 return 0;
|
|
171 }
|