diff options
author | Ian Lance Taylor <iant@google.com> | 2011-11-09 20:06:31 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2011-11-09 20:06:31 +0000 |
commit | e14304eff546e4ef3dc33e6439d793f999e81c91 (patch) | |
tree | b16db4d1e1ec9a11ee2ee00a183a6daa8b383c59 /gcc | |
parent | 8ee9fac21ec877d5e0bbcd3460eb584bbeccf836 (diff) | |
download | gcc-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/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/split-5.c | 171 | ||||
-rw-r--r-- | gcc/testsuite/lib/target-supports.exp | 8 |
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> + }] +} |