aboutsummaryrefslogtreecommitdiff
path: root/libgcc/generic-morestack.c
diff options
context:
space:
mode:
authorian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>2011-11-28 05:44:31 +0000
committerian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>2011-11-28 05:44:31 +0000
commitbda4944f9fd4e25eef1c093ff7ba7f7aaa709539 (patch)
tree7e1df6a92bc29c787ad99524223f6d3134895e11 /libgcc/generic-morestack.c
parent7998d4e5eeb2bcb6fca8ac85bc8b747ec0285fba (diff)
* 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@181771 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libgcc/generic-morestack.c')
-rw-r--r--libgcc/generic-morestack.c76
1 files changed, 73 insertions, 3 deletions
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. */