public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* Patch RFA: Add context switching splitstack routines
@ 2011-11-07 21:44 Ian Lance Taylor
  2011-11-09 21:01 ` Ian Lance Taylor
  0 siblings, 1 reply; 2+ messages in thread
From: Ian Lance Taylor @ 2011-11-07 21:44 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 2526 bytes --]

This patch adds some support for context switching to the -fsplit-stack
support routines in libgcc.  I intend to use this in the Go library to
support multiplexing multiple goroutines onto a single pthread.  They
work similarly to getcontext/setcontext/makecontext.

This patch also adds control over whether the -fsplit-stack support
routines block signals or not.  This is intended for use by programs in
which most threads block signals.  If the thread already blocks signals,
there is no need for the -fsplit-stack routines to also block signals.
This is important because it is one of the slowest parts of splitting
the stack at present.

I believe that the only part of this patch which requires approval is
the small new function in target-supports.exp.  I would of course
appreciate comments on the API and ABI of the other functions.  I have
not yet completed, or even really started, the work in the Go library,
but I want to get these functions in before the 4.7 cutoff.  I will
continue working on the Go library after the cutoff, as changes there
will only affect Go.

My goal is to have gc 4.7 have full support for the Go 1 release, which
will be a stable version of Go to be supported for at least a year.

Ian


libgcc/ChangeLog:

2011-11-07  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.

gcc/testsuite/ChangeLog:

2011-11-07  Ian Lance Taylor  <iant@google.com>

	* lib/target-supports.exp (check_effective_target_ucontext_h): New
	procedure.
	* gcc.dg/split-5.c: New test.



[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: patch --]
[-- Type: text/x-diff, Size: 19827 bytes --]

Index: libgcc/generic-morestack.c
===================================================================
--- libgcc/generic-morestack.c	(revision 181110)
+++ libgcc/generic-morestack.c	(working copy)
@@ -41,12 +41,15 @@ see the files COPYING3 and COPYING.RUNTI
 #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
   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 s
 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, vo
   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, vo
       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, vo
       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, vo
     }
 
   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, vo
   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) */
Index: libgcc/config/i386/morestack.S
===================================================================
--- libgcc/config/i386/morestack.S	(revision 181110)
+++ libgcc/config/i386/morestack.S	(working copy)
@@ -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.
Index: libgcc/libgcc-std.ver.in
===================================================================
--- libgcc/libgcc-std.ver.in	(revision 181110)
+++ libgcc/libgcc-std.ver.in	(working copy)
@@ -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
 }
Index: gcc/testsuite/lib/target-supports.exp
===================================================================
--- gcc/testsuite/lib/target-supports.exp	(revision 181110)
+++ gcc/testsuite/lib/target-supports.exp	(working copy)
@@ -4313,3 +4313,11 @@ proc check_effective_target_non_strict_a
 	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>
+    }]
+}
Index: gcc/testsuite/gcc.dg/split-5.c
===================================================================
--- gcc/testsuite/gcc.dg/split-5.c	(revision 0)
+++ gcc/testsuite/gcc.dg/split-5.c	(revision 0)
@@ -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;
+}

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: Patch RFA: Add context switching splitstack routines
  2011-11-07 21:44 Patch RFA: Add context switching splitstack routines Ian Lance Taylor
@ 2011-11-09 21:01 ` Ian Lance Taylor
  0 siblings, 0 replies; 2+ messages in thread
From: Ian Lance Taylor @ 2011-11-09 21:01 UTC (permalink / raw)
  To: gcc-patches

Ian Lance Taylor <iant@google.com> writes:

> libgcc/ChangeLog:
>
> 2011-11-07  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.
>
> gcc/testsuite/ChangeLog:
>
> 2011-11-07  Ian Lance Taylor  <iant@google.com>
>
> 	* lib/target-supports.exp (check_effective_target_ucontext_h): New
> 	procedure.
> 	* gcc.dg/split-5.c: New test.

Jakub approved the change to target-supports.exp off-line.

I committed the patch.

Ian

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2011-11-09 20:13 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-11-07 21:44 Patch RFA: Add context switching splitstack routines Ian Lance Taylor
2011-11-09 21:01 ` Ian Lance Taylor

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).