From a01207c473dcab88eb0ac769d2d9c68d7c9e0588 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Mon, 28 Nov 2011 05:44:31 +0000 Subject: [PATCH] generic-morestack.c (__splitstack_find): Check for NULL old stack value. * generic-morestack.c (__splitstack_find): Check for NULL old stack value. (__splitstack_resetcontext): New function. (__splitstack_releasecontext): New function. * libgcc-std.ver.in: Add new functions to GCC_4.7.0. From-SVN: r181771 --- libgcc/ChangeLog | 8 ++++ libgcc/generic-morestack.c | 76 ++++++++++++++++++++++++++++++++++++-- libgcc/libgcc-std.ver.in | 2 + 3 files changed, 83 insertions(+), 3 deletions(-) diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog index 4217f323cf7..4b244f41022 100644 --- a/libgcc/ChangeLog +++ b/libgcc/ChangeLog @@ -1,3 +1,11 @@ +2011-11-27 Ian Lance Taylor + + * generic-morestack.c (__splitstack_find): Check for NULL old + stack value. + (__splitstack_resetcontext): New function. + (__splitstack_releasecontext): New function. + * libgcc-std.ver.in: Add new functions to GCC_4.7.0. + 2011-11-27 Iain Sandoe * config/darwin-crt-tm.c: Correct comments, use correct licence. diff --git a/libgcc/generic-morestack.c b/libgcc/generic-morestack.c index 00a3b1c3bf0..4dbaa0e4cdc 100644 --- a/libgcc/generic-morestack.c +++ b/libgcc/generic-morestack.c @@ -115,6 +115,14 @@ extern void * __splitstack_makecontext (size_t, void *context[10], size_t *) __attribute__ ((visibility ("default"))); +extern void * +__splitstack_resetcontext (void *context[10], size_t *) + __attribute__ ((visibility ("default"))); + +extern void +__splitstack_releasecontext (void *context[10]) + __attribute__ ((visibility ("default"))); + extern void __splitstack_block_signals_context (void *context[10], int *, int *) __attribute__ ((visibility ("default"))); @@ -911,15 +919,23 @@ __splitstack_find (void *segment_arg, void *sp, size_t *len, nsp = (char *) segment->old_stack; + if (nsp == NULL) + { + /* We've reached the top of the stack. */ + *next_segment = (void *) (uintptr_type) 2; + } + else + { #if defined (__x86_64__) - nsp -= 12 * sizeof (void *); + nsp -= 12 * sizeof (void *); #elif defined (__i386__) - nsp -= 6 * sizeof (void *); + nsp -= 6 * sizeof (void *); #else #error "unrecognized target" #endif - *next_sp = (void *) nsp; + *next_sp = (void *) nsp; + } #ifdef STACK_GROWS_DOWNWARD *len = (char *) (segment + 1) + segment->size - (char *) sp; @@ -1037,6 +1053,60 @@ __splitstack_makecontext (size_t stack_size, void *context[NUMBER_OFFSETS], return (void *) (segment + 1); } +/* Given an existing split stack context, reset it back to the start + of the stack. Return the stack pointer and size, appropriate for + use with makecontext. This may be used if a coroutine exits, in + order to reuse the stack segments for a new coroutine. */ + +void * +__splitstack_resetcontext (void *context[10], size_t *size) +{ + struct stack_segment *segment; + void *initial_sp; + size_t initial_size; + void *ret; + + /* Reset the context assuming that MORESTACK_SEGMENTS, INITIAL_SP + and INITIAL_SP_LEN are correct. */ + + segment = context[MORESTACK_SEGMENTS]; + context[CURRENT_SEGMENT] = segment; + context[CURRENT_STACK] = NULL; + if (segment == NULL) + { + initial_sp = context[INITIAL_SP]; + initial_size = (uintptr_type) context[INITIAL_SP_LEN]; + ret = initial_sp; +#ifdef STACK_GROWS_DOWNWARD + ret = (void *) ((char *) ret - initial_size); +#endif + } + else + { +#ifdef STACK_GROWS_DOWNWARD + initial_sp = (void *) ((char *) (segment + 1) + segment->size); +#else + initial_sp = (void *) (segment + 1); +#endif + initial_size = segment->size; + ret = (void *) (segment + 1); + } + context[STACK_GUARD] = __morestack_make_guard (initial_sp, initial_size); + context[BLOCK_SIGNALS] = NULL; + *size = initial_size; + return ret; +} + +/* Release all the memory associated with a splitstack context. This + may be used if a coroutine exits and the associated stack should be + freed. */ + +void +__splitstack_releasecontext (void *context[10]) +{ + __morestack_release_segments (context[MORESTACK_SEGMENTS], 1); +} + /* Like __splitstack_block_signals, but operating on CONTEXT, rather than on the current state. */ diff --git a/libgcc/libgcc-std.ver.in b/libgcc/libgcc-std.ver.in index 2d66612d1c5..ec702952f9b 100644 --- a/libgcc/libgcc-std.ver.in +++ b/libgcc/libgcc-std.ver.in @@ -1932,4 +1932,6 @@ GCC_4.7.0 { __splitstack_makecontext __splitstack_block_signals_context __splitstack_find_context + __splitstack_resetcontext + __splitstack_releasecontext }