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 | |
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
-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 | ||||
-rw-r--r-- | libgcc/ChangeLog | 25 | ||||
-rw-r--r-- | libgcc/config/i386/morestack.S | 78 | ||||
-rw-r--r-- | libgcc/generic-morestack.c | 252 | ||||
-rw-r--r-- | libgcc/libgcc-std.ver.in | 8 |
7 files changed, 527 insertions, 21 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> + }] +} diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog index 0e99994..bfaa1a0 100644 --- a/libgcc/ChangeLog +++ b/libgcc/ChangeLog @@ -1,3 +1,28 @@ +2011-11-09 Ian Lance Taylor <iant@google.com> + + * 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. + 2011-11-09 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> * config.host (i[34567]86-*-cygwin*): Move i386/t-mingw-pthread ... diff --git a/libgcc/config/i386/morestack.S b/libgcc/config/i386/morestack.S index 85c20ed..0667590 100644 --- a/libgcc/config/i386/morestack.S +++ b/libgcc/config/i386/morestack.S @@ -1,5 +1,5 @@ # x86/x86_64 support for -fsplit-stack. -# Copyright (C) 2009, 2010 Free Software Foundation, Inc. +# Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc. # Contributed by Ian Lance Taylor <iant@google.com>. # This file is part of GCC. @@ -620,6 +620,82 @@ __stack_split_initialize: .size __stack_split_initialize, . - __stack_split_initialize #endif +# Routines to get and set the guard, for __splitstack_getcontext, +# __splitstack_setcontext, and __splitstack_makecontext. + +# void *__morestack_get_guard (void) returns the current stack guard. + .text + .global __morestack_get_guard + .hidden __morestack_get_guard + +#ifdef __ELF__ + .type __morestack_get_guard,@function +#endif + +__morestack_get_guard: + +#ifndef __x86_64__ + movl %gs:0x30,%eax +#else +#ifdef __LP64__ + movq %fs:0x70,%rax +#else + movl %fs:0x40,%eax +#endif +#endif + ret + +#ifdef __ELF__ + .size __morestack_get_guard, . - __morestack_get_guard +#endif + +# void __morestack_set_guard (void *) sets the stack guard. + .global __morestack_set_guard + .hidden __morestack_set_guard + +#ifdef __ELF__ + .type __morestack_set_guard,@function +#endif + +__morestack_set_guard: + +#ifndef __x86_64__ + movl 4(%esp),%eax + movl %eax,%gs:0x30 +#else + X86_64_SAVE_NEW_STACK_BOUNDARY (di) +#endif + ret + +#ifdef __ELF__ + .size __morestack_set_guard, . - __morestack_set_guard +#endif + +# void *__morestack_make_guard (void *, size_t) returns the stack +# guard value for a stack. + .global __morestack_make_guard + .hidden __morestack_make_guard + +#ifdef __ELF__ + .type __morestack_make_guard,@function +#endif + +__morestack_make_guard: + +#ifndef __x86_64__ + movl 4(%esp),%eax + subl 8(%esp),%eax + addl $BACKOFF,%eax +#else + subq %rsi,%rdi + addq $BACKOFF,%rdi + movq %rdi,%rax +#endif + ret + +#ifdef __ELF__ + .size __morestack_make_guard, . - __morestack_make_guard +#endif # Make __stack_split_initialize a high priority constructor. FIXME: # This is ELF specific. diff --git a/libgcc/generic-morestack.c b/libgcc/generic-morestack.c index 07bc2a6..00a3b1c 100644 --- a/libgcc/generic-morestack.c +++ b/libgcc/generic-morestack.c @@ -41,12 +41,15 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #include <errno.h> #include <signal.h> #include <stdlib.h> +#include <string.h> #include <unistd.h> #include <sys/mman.h> #include <sys/uio.h> #include "generic-morestack.h" +typedef unsigned uintptr_type __attribute__ ((mode (pointer))); + /* This file contains subroutines that are used by code compiled with -fsplit-stack. */ @@ -88,14 +91,50 @@ extern void * __morestack_allocate_stack_space (size_t size) __attribute__ ((visibility ("hidden"))); -/* This is a function which -fsplit-stack code can call to get a list - of the stacks. Since it is not called only by the compiler, it is - not hidden. */ +/* These are functions which -fsplit-stack code can call. These are + not called by the compiler, and are not hidden. FIXME: These + should be in some header file somewhere, somehow. */ extern void * __splitstack_find (void *, void *, size_t *, void **, void **, void **) __attribute__ ((visibility ("default"))); +extern void +__splitstack_block_signals (int *, int *) + __attribute__ ((visibility ("default"))); + +extern void +__splitstack_getcontext (void *context[10]) + __attribute__ ((no_split_stack, visibility ("default"))); + +extern void +__splitstack_setcontext (void *context[10]) + __attribute__ ((no_split_stack, visibility ("default"))); + +extern void * +__splitstack_makecontext (size_t, void *context[10], size_t *) + __attribute__ ((visibility ("default"))); + +extern void +__splitstack_block_signals_context (void *context[10], int *, int *) + __attribute__ ((visibility ("default"))); + +extern void * +__splitstack_find_context (void *context[10], size_t *, void **, void **, + void **) + __attribute__ ((visibility ("default"))); + +/* These functions must be defined by the processor specific code. */ + +extern void *__morestack_get_guard (void) + __attribute__ ((no_split_stack, visibility ("hidden"))); + +extern void __morestack_set_guard (void *) + __attribute__ ((no_split_stack, visibility ("hidden"))); + +extern void *__morestack_make_guard (void *, size_t) + __attribute__ ((no_split_stack, visibility ("hidden"))); + /* When we allocate a stack segment we put this header at the start. */ @@ -138,8 +177,13 @@ struct initial_sp /* A signal mask, put here so that the thread can use it without needing stack space. */ sigset_t mask; + /* Non-zero if we should not block signals. This is a reversed flag + so that the default zero value is the safe value. The type is + uintptr_type because it replaced one of the void * pointers in + extra. */ + uintptr_type dont_block_signals; /* Some extra space for later extensibility. */ - void *extra[5]; + void *extra[4]; }; /* A list of memory blocks allocated by dynamic stack allocation. @@ -339,18 +383,13 @@ allocate_segment (size_t frame_size) pss = (struct stack_segment *) space; - pss->prev = __morestack_current_segment; + pss->prev = NULL; pss->next = NULL; pss->size = allocate - overhead; pss->dynamic_allocation = NULL; pss->free_dynamic_allocation = NULL; pss->extra = NULL; - if (__morestack_current_segment != NULL) - __morestack_current_segment->next = pss; - else - __morestack_segments = pss; - return pss; } @@ -513,7 +552,11 @@ __generic_morestack (size_t *pframe_size, void *old_stack, size_t param_size) current = *pp; if (current == NULL) - current = allocate_segment (frame_size + param_size); + { + current = allocate_segment (frame_size + param_size); + current->prev = __morestack_current_segment; + *pp = current; + } current->old_stack = old_stack; @@ -614,7 +657,9 @@ extern int pthread_sigmask (int, const sigset_t *, sigset_t *) void __morestack_block_signals (void) { - if (pthread_sigmask) + if (__morestack_initial_sp.dont_block_signals) + ; + else if (pthread_sigmask) pthread_sigmask (SIG_BLOCK, &__morestack_fullmask, &__morestack_initial_sp.mask); else @@ -627,7 +672,9 @@ __morestack_block_signals (void) void __morestack_unblock_signals (void) { - if (pthread_sigmask) + if (__morestack_initial_sp.dont_block_signals) + ; + else if (pthread_sigmask) pthread_sigmask (SIG_SETMASK, &__morestack_initial_sp.mask, NULL); else sigprocmask (SIG_SETMASK, &__morestack_initial_sp.mask, NULL); @@ -727,6 +774,10 @@ __generic_findstack (void *stack) } /* We have popped back to the original stack. */ + + if (__morestack_initial_sp.sp == NULL) + return 0; + #ifdef STACK_GROWS_DOWNWARD if ((char *) stack >= (char *) __morestack_initial_sp.sp) used = 0; @@ -796,11 +847,14 @@ __splitstack_find (void *segment_arg, void *sp, size_t *len, void *ret; char *nsp; - if (segment_arg == (void *) 1) + if (segment_arg == (void *) (uintptr_type) 1) { char *isp = (char *) *initial_sp; - *next_segment = (void *) 2; + if (isp == NULL) + return NULL; + + *next_segment = (void *) (uintptr_type) 2; *next_sp = NULL; #ifdef STACK_GROWS_DOWNWARD if ((char *) sp >= isp) @@ -814,7 +868,7 @@ __splitstack_find (void *segment_arg, void *sp, size_t *len, return (void *) isp; #endif } - else if (segment_arg == (void *) 2) + else if (segment_arg == (void *) (uintptr_type) 2) return NULL; else if (segment_arg != NULL) segment = (struct stack_segment *) segment_arg; @@ -826,8 +880,8 @@ __splitstack_find (void *segment_arg, void *sp, size_t *len, while (1) { if (segment == NULL) - return __splitstack_find ((void *) 1, sp, len, next_segment, - next_sp, initial_sp); + return __splitstack_find ((void *) (uintptr_type) 1, sp, len, + next_segment, next_sp, initial_sp); if ((char *) sp >= (char *) (segment + 1) && (char *) sp <= (char *) (segment + 1) + segment->size) break; @@ -836,7 +890,7 @@ __splitstack_find (void *segment_arg, void *sp, size_t *len, } if (segment->prev == NULL) - *next_segment = (void *) 1; + *next_segment = (void *) (uintptr_type) 1; else *next_segment = segment->prev; @@ -878,4 +932,164 @@ __splitstack_find (void *segment_arg, void *sp, size_t *len, return ret; } +/* Tell the split stack code whether it has to block signals while + manipulating the stack. This is for programs in which some threads + block all signals. If a thread already blocks signals, there is no + need for the split stack code to block them as well. If NEW is not + NULL, then if *NEW is non-zero signals will be blocked while + splitting the stack, otherwise they will not. If OLD is not NULL, + *OLD will be set to the old value. */ + +void +__splitstack_block_signals (int *new, int *old) +{ + if (old != NULL) + *old = __morestack_initial_sp.dont_block_signals ? 0 : 1; + if (new != NULL) + __morestack_initial_sp.dont_block_signals = *new ? 0 : 1; +} + +/* The offsets into the arrays used by __splitstack_getcontext and + __splitstack_setcontext. */ + +enum __splitstack_context_offsets +{ + MORESTACK_SEGMENTS = 0, + CURRENT_SEGMENT = 1, + CURRENT_STACK = 2, + STACK_GUARD = 3, + INITIAL_SP = 4, + INITIAL_SP_LEN = 5, + BLOCK_SIGNALS = 6, + + NUMBER_OFFSETS = 10 +}; + +/* Get the current split stack context. This may be used for + coroutine switching, similar to getcontext. The argument should + have at least 10 void *pointers for extensibility, although we + don't currently use all of them. This would normally be called + immediately before a call to getcontext or swapcontext or + setjmp. */ + +void +__splitstack_getcontext (void *context[NUMBER_OFFSETS]) +{ + memset (context, 0, NUMBER_OFFSETS * sizeof (void *)); + context[MORESTACK_SEGMENTS] = (void *) __morestack_segments; + context[CURRENT_SEGMENT] = (void *) __morestack_current_segment; + context[CURRENT_STACK] = (void *) &context; + context[STACK_GUARD] = __morestack_get_guard (); + context[INITIAL_SP] = (void *) __morestack_initial_sp.sp; + context[INITIAL_SP_LEN] = (void *) (uintptr_type) __morestack_initial_sp.len; + context[BLOCK_SIGNALS] = (void *) __morestack_initial_sp.dont_block_signals; +} + +/* Set the current split stack context. The argument should be a + context previously passed to __splitstack_getcontext. This would + normally be called immediately after a call to getcontext or + swapcontext or setjmp if something jumped to it. */ + +void +__splitstack_setcontext (void *context[NUMBER_OFFSETS]) +{ + __morestack_segments = (struct stack_segment *) context[MORESTACK_SEGMENTS]; + __morestack_current_segment = + (struct stack_segment *) context[CURRENT_SEGMENT]; + __morestack_set_guard (context[STACK_GUARD]); + __morestack_initial_sp.sp = context[INITIAL_SP]; + __morestack_initial_sp.len = (size_t) context[INITIAL_SP_LEN]; + __morestack_initial_sp.dont_block_signals = + (uintptr_type) context[BLOCK_SIGNALS]; +} + +/* Create a new split stack context. This will allocate a new stack + segment which may be used by a coroutine. STACK_SIZE is the + minimum size of the new stack. The caller is responsible for + actually setting the stack pointer. This would normally be called + before a call to makecontext, and the returned stack pointer and + size would be used to set the uc_stack field. A function called + via makecontext on a stack created by __splitstack_makecontext may + not return. Note that the returned pointer points to the lowest + address in the stack space, and thus may not be the value to which + to set the stack pointer. */ + +void * +__splitstack_makecontext (size_t stack_size, void *context[NUMBER_OFFSETS], + size_t *size) +{ + struct stack_segment *segment; + void *initial_sp; + + memset (context, 0, NUMBER_OFFSETS * sizeof (void *)); + segment = allocate_segment (stack_size); + context[MORESTACK_SEGMENTS] = segment; + context[CURRENT_SEGMENT] = segment; +#ifdef STACK_GROWS_DOWNWARD + initial_sp = (void *) ((char *) (segment + 1) + segment->size); +#else + initial_sp = (void *) (segment + 1); +#endif + context[STACK_GUARD] = __morestack_make_guard (initial_sp, segment->size); + context[INITIAL_SP] = NULL; + context[INITIAL_SP_LEN] = 0; + *size = segment->size; + return (void *) (segment + 1); +} + +/* Like __splitstack_block_signals, but operating on CONTEXT, rather + than on the current state. */ + +void +__splitstack_block_signals_context (void *context[NUMBER_OFFSETS], int *new, + int *old) +{ + if (old != NULL) + *old = ((uintptr_type) context[BLOCK_SIGNALS]) != 0 ? 0 : 1; + if (new != NULL) + context[BLOCK_SIGNALS] = (void *) (uintptr_type) (*new ? 0 : 1); +} + +/* Find the stack segments associated with a split stack context. + This will return the address of the first stack segment and set + *STACK_SIZE to its size. It will set next_segment, next_sp, and + initial_sp which may be passed to __splitstack_find to find the + remaining segments. */ + +void * +__splitstack_find_context (void *context[NUMBER_OFFSETS], size_t *stack_size, + void **next_segment, void **next_sp, + void **initial_sp) +{ + void *sp; + struct stack_segment *segment; + + *initial_sp = context[INITIAL_SP]; + + sp = context[CURRENT_STACK]; + if (sp == NULL) + { + /* Most likely this context was created but was never used. The + value 2 is a code used by __splitstack_find to mean that we + have reached the end of the list of stacks. */ + *next_segment = (void *) (uintptr_type) 2; + *next_sp = NULL; + *initial_sp = NULL; + return NULL; + } + + segment = context[CURRENT_SEGMENT]; + if (segment == NULL) + { + /* Most likely this context was saved by a thread which was not + created using __splistack_makecontext and which has never + split the stack. The value 1 is a code used by + __splitstack_find to look at the initial stack. */ + segment = (struct stack_segment *) (uintptr_type) 1; + } + + return __splitstack_find (segment, sp, stack_size, next_segment, next_sp, + initial_sp); +} + #endif /* !defined (inhibit_libc) */ diff --git a/libgcc/libgcc-std.ver.in b/libgcc/libgcc-std.ver.in index 2946468..2d66612 100644 --- a/libgcc/libgcc-std.ver.in +++ b/libgcc/libgcc-std.ver.in @@ -1,5 +1,5 @@ # Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, -# 2008, 2010 Free Software Foundation, Inc. +# 2008, 2010, 2011 Free Software Foundation, Inc. # # This file is part of GCC. # @@ -1926,4 +1926,10 @@ GCC_4.7.0 { __PFX__clrsbsi2 __PFX__clrsbdi2 __PFX__clrsbti2 + __splitstack_block_signals + __splitstack_getcontext + __splitstack_setcontext + __splitstack_makecontext + __splitstack_block_signals_context + __splitstack_find_context } |