aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@google.com>2011-11-09 20:06:31 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2011-11-09 20:06:31 +0000
commite14304eff546e4ef3dc33e6439d793f999e81c91 (patch)
treeb16db4d1e1ec9a11ee2ee00a183a6daa8b383c59 /gcc
parent8ee9fac21ec877d5e0bbcd3460eb584bbeccf836 (diff)
downloadgcc-e14304eff546e4ef3dc33e6439d793f999e81c91.zip
gcc-e14304eff546e4ef3dc33e6439d793f999e81c91.tar.gz
gcc-e14304eff546e4ef3dc33e6439d793f999e81c91.tar.bz2
generic-morestack.c: Include <string.h>.
libgcc/: * generic-morestack.c: Include <string.h>. (uintptr_type): Define. (struct initial_sp): Add dont_block_signals field. Reduce size of extra array by 1. (allocate_segment): Set prev field to NULL. Don't set __morestack_current_segment or __morestack_segments. (__generic_morestack): Update current->prev and *pp after calling allocate_segment. (__morestack_block_signals): Don't do anything if dont_block_signals is set. (__morestack_unblock_signals): Likewise. (__generic_findstack): Check for initial_sp == NULL. Add casts to uintptr_type. (__splitstack_block_signals): New function. (enum __splitstack_content_offsets): Define. (__splitstack_getcontext, __splitstack_setcontext): New functions. (__splitstack_makecontext): New function. (__splitstack_block_signals_context): New function. (__splitstack_find_context): New function. * config/i386/morestack.S (__morestack_get_guard): New function. (__morestack_set_guard, __morestack_make_guard): New functions. * libgcc-std.ver.in: Add new functions to GCC_4.7.0. gcc/testsuite/: * lib/target-supports.exp (check_effective_target_ucontext_h): New procedure. * gcc.dg/split-5.c: New test. From-SVN: r181234
Diffstat (limited to 'gcc')
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.dg/split-5.c171
-rw-r--r--gcc/testsuite/lib/target-supports.exp8
3 files changed, 185 insertions, 0 deletions
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 4052135..ad7fbea 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2011-11-09 Ian Lance Taylor <iant@google.com>
+
+ * lib/target-supports.exp (check_effective_target_ucontext_h): New
+ procedure.
+ * gcc.dg/split-5.c: New test.
+
2011-11-09 Patrick Marlier <patrick.marlier@gmail.com>
* gcc.dg/tm/memopt-1.c: Adjust regexp.
diff --git a/gcc/testsuite/gcc.dg/split-5.c b/gcc/testsuite/gcc.dg/split-5.c
new file mode 100644
index 0000000..601640f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/split-5.c
@@ -0,0 +1,171 @@
+/* { dg-do run } */
+/* { dg-require-effective-target split_stack } */
+/* { dg-require-effective-target pthread_h } */
+/* { dg-require-effective-target ucontext_h } */
+/* { dg-options "-pthread -fsplit-stack" } */
+
+#include <stdlib.h>
+#include <pthread.h>
+#include <ucontext.h>
+
+extern void __splitstack_getcontext (void *context[10]);
+
+extern void __splitstack_setcontext (void *context[10]);
+
+extern void *__splitstack_makecontext (size_t, void *context[10], size_t *);
+
+extern void __splitstack_block_signals (int *, int *);
+
+extern void __splitstack_block_signals_context (void *context[10], int *,
+ int *);
+
+extern void *__splitstack_find (void *, void *, size_t *, void **, void **,
+ void **);
+
+extern void *__splitstack_find_context (void *context[10], size_t *, void **,
+ void **, void **);
+
+static ucontext_t c1;
+static void *s1[10];
+
+static ucontext_t c2;
+static void *s2[10];
+
+static void swap (ucontext_t *, void *fs[10], ucontext_t *, void *ts[10])
+ __attribute__ ((no_split_stack));
+
+static void
+swap (ucontext_t *fu, void *fs[10], ucontext_t *tu, void *ts[10])
+{
+ __splitstack_getcontext (fs);
+ __splitstack_setcontext (ts);
+ swapcontext (fu, tu);
+ __splitstack_setcontext (fs);
+}
+
+/* Use a noinline function to ensure that the buffer is not removed
+ from the stack. */
+static void use_buffer (char *buf) __attribute__ ((noinline));
+static void
+use_buffer (char *buf)
+{
+ buf[0] = '\0';
+}
+
+static void
+down (int i, const char *msg, ucontext_t *me, void *mes[10],
+ ucontext_t *other, void *others[10])
+{
+ char buf[10000];
+
+ if (i > 0)
+ {
+ use_buffer (buf);
+ swap (me, mes, other, others);
+ down (i - 1, msg, me, mes, other, others);
+ }
+ else
+ {
+ int c = 0;
+ void *stack;
+ size_t stack_size;
+ void *next_segment = NULL;
+ void *next_sp = NULL;
+ void *initial_sp = NULL;
+
+ stack = __splitstack_find_context (mes, &stack_size, &next_segment,
+ &next_sp, &initial_sp);
+ if (stack != NULL)
+ {
+ ++c;
+ while (__splitstack_find (next_segment, next_sp, &stack_size,
+ &next_segment, &next_sp, &initial_sp)
+ != NULL)
+ ++c;
+ }
+ }
+}
+
+static void
+go1 (void)
+{
+ down (1000, "go1", &c1, s1, &c2, s2);
+ pthread_exit (NULL);
+}
+
+static void
+go2 (void)
+{
+ down (1000, "go2", &c2, s2, &c1, s1);
+ pthread_exit (NULL);
+}
+
+struct thread_context
+{
+ ucontext_t *u;
+ void **s;
+};
+
+static void *start_thread (void *) __attribute__ ((no_split_stack));
+
+static void *
+start_thread (void *context)
+{
+ struct thread_context *tc = (struct thread_context *) context;
+ int block;
+
+ block = 0;
+ __splitstack_block_signals (&block, NULL);
+ __splitstack_setcontext (tc->s);
+ setcontext (tc->u);
+ abort ();
+}
+
+int
+main (int argc __attribute__ ((unused)), char **argv __attribute__ ((unused)))
+{
+ pthread_t tid;
+ int err;
+ size_t size;
+ struct thread_context tc;
+ int block;
+
+ if (getcontext (&c1) < 0)
+ abort ();
+
+ c2 = c1;
+
+ c1.uc_stack.ss_sp = __splitstack_makecontext (8192, &s1[0], &size);
+ if (c1.uc_stack.ss_sp == NULL)
+ abort ();
+ c1.uc_stack.ss_flags = 0;
+ c1.uc_stack.ss_size = size;
+ c1.uc_link = NULL;
+ block = 0;
+ __splitstack_block_signals_context (&s1[0], &block, NULL);
+ makecontext (&c1, go1, 0);
+
+ c2.uc_stack.ss_sp = __splitstack_makecontext (8192, &s2[0], &size);
+ if (c2.uc_stack.ss_sp == NULL)
+ abort ();
+ c2.uc_stack.ss_flags = 0;
+ c2.uc_stack.ss_size = size;
+ c2.uc_link = NULL;
+ __splitstack_block_signals_context (&s2[0], &block, NULL);
+ makecontext (&c2, go2, 0);
+
+ block = 0;
+ __splitstack_block_signals (&block, NULL);
+
+ tc.u = &c1;
+ tc.s = &s1[0];
+ err = pthread_create (&tid, NULL, start_thread, &tc);
+ if (err != 0)
+ abort ();
+
+ err = pthread_join (tid, NULL);
+ if (err != 0)
+ abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index 944a668..9430910 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -4401,3 +4401,11 @@ proc check_effective_target_non_strict_align {} {
void foo(void) { z = (c *) y; }
} "-Wcast-align"]
}
+
+# Return 1 if the target has <ucontext.h>.
+
+proc check_effective_target_ucontext_h { } {
+ return [check_no_compiler_messages ucontext_h assembly {
+ #include <ucontext.h>
+ }]
+}