Re: Go patch committed: Multiplex goroutines onto OS threads

2012-02-10 Thread Rainer Orth
Ian Lance Taylor i...@google.com writes:

 Ian Lance Taylor i...@google.com writes:

 Right now it looks like there is a bug, or at least an incompatibility,
 in the 64-bit versions of getcontext and setcontext.  It looks like
 calling setcontext on the 32-bit version does not change the value of
 TLS variables, which is also the case on GNU/Linux.  In the 64-bit
 version, calling setcontext does change the value of TLS variables.
 That is, on the 64-bit version, getcontext preserves the value of TLS
 variables and setcontext restores the old value.  (Of course it's really
 the pointer, not the TLS variables themselves).  This incompatibility
 has to be a bug, and of course I would prefer that the incompatibility
 be resolved in favor of the implementation used on GNU/Linux.

 Well, I thought I could fix this in a sensible way, but I really
 couldn't.  It's a fairly serious bug.  Calling setcontext in thread T2
 when getcontext was called in thread T1 causes T2 to start using T1's
 TLS variables, T1's pthread_getspecific values, and even T1's
 pthread_self.  I couldn't figure out any way that T2 could do any thread
 specific.

 So I cheated and wrote a system-specific hack.  With this patch applied,
 I see only 4 failures running the testsuite on x86/x86_64 Solaris.
 Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu, where the
 code is not used.  Committed to mainline.

Excellent, works like a charm, thanks.  The patches for Solaris 10 and
11 are expected within the next month or two.  I only noticed two
problems:

* On Solaris 8/x86 with native TLS, SETCONTEXT_CLOBBERS_TLS was
  incorrectly defined, causing a proc.c compilation failure:

/vol/gcc/src/hg/trunk/local/libgo/runtime/proc.c:105:4: error: #error unknown 
case for SETCONTEXT_CLOBBERS_TLS
/vol/gcc/src/hg/trunk/local/libgo/runtime/proc.c: In function 'runtime_gogo':
/vol/gcc/src/hg/trunk/local/libgo/runtime/proc.c:299:2: error: implicit 
declaration of function 'fixcontext' [-Werror=implicit-function-declaration]
/vol/gcc/src/hg/trunk/local/libgo/runtime/proc.c: In function 
'runtime_schedinit':
/vol/gcc/src/hg/trunk/local/libgo/runtime/proc.c:366:2: error: implicit 
declaration of function 'initcontext' [-Werror=implicit-function-declaration]
cc1: all warnings being treated as errors
make[4]: *** [proc.lo] Error 1

  The configure test failed like this:

configure:14894: ./conftest
ld.so.1: conftest: fatal: conftest: object requires TLS, but TLS failed to initi
alize
/vol/gcc/src/hg/trunk/local/libgo/configure[20]: 28491 Killed

  The problem is that on Solaris 8 one needs to link with -pthread which
  takes care of finding the correct libthread.so.  The following patch
  takes care of that and gives decent testsuite results.

* In the cross-compilation case, one needs to test both the
  i?86-*-solaris2.1[01] and x86_64-*-solaris2.1[10] target triplets, but
  only for 64-bit.  The first is the default, while one can configure
  for the second if need be.  The patch contains the necessary change,
  adapted from libgcc/configure.ac's type size detection.  Besides, the
  bug affects both Solaris 10 and 11, so the workaround should trigger
  on either, too.

Rainer


diff --git a/libgo/configure.ac b/libgo/configure.ac
--- a/libgo/configure.ac
+++ b/libgo/configure.ac
@@ -584,8 +584,12 @@ fi
 dnl See whether setcontext changes the value of TLS variables.
 AC_CACHE_CHECK([whether setcontext clobbers TLS variables],
 [libgo_cv_lib_setcontext_clobbers_tls],
-[LIBS_hold=$LIBS
+[CFLAGS_hold=$CFLAGS
+CFLAGS=$PTHREAD_CFLAGS
+LIBS_hold=$LIBS
 LIBS=$LIBS $PTHREAD_LIBS
+AC_CHECK_SIZEOF([void *])
+AS_VAR_ARITH([ptr_type_size], [$ac_cv_sizeof_void_p \* 8])
 AC_RUN_IFELSE(
   [AC_LANG_SOURCE([
 #include pthread.h
@@ -650,11 +654,14 @@ main ()
 ])],
 [libgo_cv_lib_setcontext_clobbers_tls=no],
 [libgo_cv_lib_setcontext_clobbers_tls=yes],
-[case $target in
-  x86_64*-*-solaris2.10) libgo_cv_lib_setcontext_clobbers_tls=yes ;;
-  *) libgo_cv_lib_setcontext_clobbers_tls=no ;;
+[case $target:$ptr_type_size in
+  i?86-*-solaris2.1[[01]]:64 | x86_64*-*-solaris2.1[[01]]:64)
+libgo_cv_lib_setcontext_clobbers_tls=yes ;;
+  *)
+libgo_cv_lib_setcontext_clobbers_tls=no ;;
  esac
 ])
+CFLAGS=$CFLAGS_hold
 LIBS=$LIBS_hold
 ])
 if test $libgo_cv_lib_setcontext_clobbers_tls = yes; then

-- 
-
Rainer Orth, Center for Biotechnology, Bielefeld University


Re: Go patch committed: Multiplex goroutines onto OS threads

2012-02-10 Thread Ian Lance Taylor
Rainer Orth r...@cebitec.uni-bielefeld.de writes:

 * On Solaris 8/x86 with native TLS, SETCONTEXT_CLOBBERS_TLS was
   incorrectly defined, causing a proc.c compilation failure:

 /vol/gcc/src/hg/trunk/local/libgo/runtime/proc.c:105:4: error: #error unknown 
 case for SETCONTEXT_CLOBBERS_TLS
 /vol/gcc/src/hg/trunk/local/libgo/runtime/proc.c: In function 'runtime_gogo':
 /vol/gcc/src/hg/trunk/local/libgo/runtime/proc.c:299:2: error: implicit 
 declaration of function 'fixcontext' [-Werror=implicit-function-declaration]
 /vol/gcc/src/hg/trunk/local/libgo/runtime/proc.c: In function 
 'runtime_schedinit':
 /vol/gcc/src/hg/trunk/local/libgo/runtime/proc.c:366:2: error: implicit 
 declaration of function 'initcontext' [-Werror=implicit-function-declaration]
 cc1: all warnings being treated as errors
 make[4]: *** [proc.lo] Error 1

   The configure test failed like this:

 configure:14894: ./conftest
 ld.so.1: conftest: fatal: conftest: object requires TLS, but TLS failed to 
 initi
 alize
 /vol/gcc/src/hg/trunk/local/libgo/configure[20]: 28491 Killed

   The problem is that on Solaris 8 one needs to link with -pthread which
   takes care of finding the correct libthread.so.  The following patch
   takes care of that and gives decent testsuite results.

 * In the cross-compilation case, one needs to test both the
   i?86-*-solaris2.1[01] and x86_64-*-solaris2.1[10] target triplets, but
   only for 64-bit.  The first is the default, while one can configure
   for the second if need be.  The patch contains the necessary change,
   adapted from libgcc/configure.ac's type size detection.  Besides, the
   bug affects both Solaris 10 and 11, so the workaround should trigger
   on either, too.

Thanks.  Committed.

Ian


Re: Go patch committed: Multiplex goroutines onto OS threads

2012-02-07 Thread Ian Lance Taylor
Ian Lance Taylor i...@google.com writes:

 Right now it looks like there is a bug, or at least an incompatibility,
 in the 64-bit versions of getcontext and setcontext.  It looks like
 calling setcontext on the 32-bit version does not change the value of
 TLS variables, which is also the case on GNU/Linux.  In the 64-bit
 version, calling setcontext does change the value of TLS variables.
 That is, on the 64-bit version, getcontext preserves the value of TLS
 variables and setcontext restores the old value.  (Of course it's really
 the pointer, not the TLS variables themselves).  This incompatibility
 has to be a bug, and of course I would prefer that the incompatibility
 be resolved in favor of the implementation used on GNU/Linux.

Well, I thought I could fix this in a sensible way, but I really
couldn't.  It's a fairly serious bug.  Calling setcontext in thread T2
when getcontext was called in thread T1 causes T2 to start using T1's
TLS variables, T1's pthread_getspecific values, and even T1's
pthread_self.  I couldn't figure out any way that T2 could do any thread
specific.

So I cheated and wrote a system-specific hack.  With this patch applied,
I see only 4 failures running the testsuite on x86/x86_64 Solaris.
Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu, where the
code is not used.  Committed to mainline.

Ian

diff -r d9bce1ef2e17 libgo/configure.ac
--- a/libgo/configure.ac	Tue Feb 07 11:19:23 2012 -0800
+++ b/libgo/configure.ac	Tue Feb 07 21:19:06 2012 -0800
@@ -549,6 +549,87 @@
 STRUCT_EPOLL_EVENT_FD_OFFSET=${libgo_cv_c_epoll_event_fd_offset}
 AC_SUBST(STRUCT_EPOLL_EVENT_FD_OFFSET)
 
+dnl See whether setcontext changes the value of TLS variables.
+AC_CACHE_CHECK([whether setcontext clobbers TLS variables],
+[libgo_cv_lib_setcontext_clobbers_tls],
+[LIBS_hold=$LIBS
+LIBS=$LIBS $PTHREAD_LIBS
+AC_RUN_IFELSE(
+  [AC_LANG_SOURCE([
+#include pthread.h
+#include stdlib.h
+#include ucontext.h
+#include unistd.h
+
+__thread int tls;
+
+static char stack[[10 * 1024 * 1024]];
+static ucontext_t c;
+
+/* Called via makecontext/setcontext.  */
+
+static void
+cfn (void)
+{
+  exit (tls);
+}
+
+/* Called via pthread_create.  */
+
+static void *
+tfn (void *dummy)
+{
+  /* The thread should still see this value after calling
+ setcontext.  */
+  tls = 0;
+
+  setcontext (c);
+
+  /* The call to setcontext should not return.  */
+  abort ();
+}
+
+int
+main ()
+{
+  pthread_t tid;
+
+  /* The thread should not see this value.  */
+  tls = 1;
+
+  if (getcontext (c)  0)
+abort ();
+
+  c.uc_stack.ss_sp = stack;
+  c.uc_stack.ss_flags = 0;
+  c.uc_stack.ss_size = sizeof stack;
+  c.uc_link = NULL;
+  makecontext (c, cfn, 0);
+
+  if (pthread_create (tid, NULL, tfn, NULL) != 0)
+abort ();
+
+  if (pthread_join (tid, NULL) != 0)
+abort ();
+
+  /* The thread should have called exit.  */
+  abort ();
+}
+])],
+[libgo_cv_lib_setcontext_clobbers_tls=no],
+[libgo_cv_lib_setcontext_clobbers_tls=yes],
+[case $target in
+  x86_64*-*-solaris2.10) libgo_cv_lib_setcontext_clobbers_tls=yes ;;
+  *) libgo_cv_lib_setcontext_clobbers_tls=no ;;
+ esac
+])
+LIBS=$LIBS_hold
+])
+if test $libgo_cv_lib_setcontext_clobbers_tls = yes; then
+  AC_DEFINE(SETCONTEXT_CLOBBERS_TLS, 1,
+	[Define if setcontext clobbers TLS variables])
+fi
+
 AC_CACHE_SAVE
 
 if test ${multilib} = yes; then
diff -r d9bce1ef2e17 libgo/runtime/proc.c
--- a/libgo/runtime/proc.c	Tue Feb 07 11:19:23 2012 -0800
+++ b/libgo/runtime/proc.c	Tue Feb 07 21:19:06 2012 -0800
@@ -60,6 +60,54 @@
 static __thread G *g;
 static __thread M *m;
 
+#ifndef SETCONTEXT_CLOBBERS_TLS
+
+static inline void
+initcontext(void)
+{
+}
+
+static inline void
+fixcontext(ucontext_t *c __attribute__ ((unused)))
+{
+}
+
+# else
+
+# if defined(__x86_64__)  defined(__sun__)
+
+// x86_64 Solaris 10 and 11 have a bug: setcontext switches the %fs
+// register to that of the thread which called getcontext.  The effect
+// is that the address of all __thread variables changes.  This bug
+// also affects pthread_self() and pthread_getspecific.  We work
+// around it by clobbering the context field directly to keep %fs the
+// same.
+
+static __thread greg_t fs;
+
+static inline void
+initcontext(void)
+{
+	ucontext_t c;
+
+	getcontext(c);
+	fs = c.uc_mcontext.gregs[REG_FSBASE];
+}
+
+static inline void
+fixcontext(ucontext_t* c)
+{
+	c-uc_mcontext.gregs[REG_FSBASE] = fs;
+}
+
+# else
+
+#  error unknown case for SETCONTEXT_CLOBBERS_TLS
+
+# endif
+
+#endif
+
 // We can not always refer to the TLS variables directly.  The
 // compiler will call tls_get_addr to get the address of the variable,
 // and it may hold it in a register across a call to schedule.  When
@@ -248,7 +296,9 @@
 #endif
 	g = newg;
 	newg-fromgogo = true;
+	fixcontext(newg-context);
 	setcontext(newg-context);
+	runtime_throw(gogo setcontext returned);
 }
 
 // Save context and call fn passing g as a parameter.  This is like
@@ -287,6 +337,7 @@
 		m-g0-entry = (byte*)pfn;
 		m-g0-param = g;
 		g 

Re: Go patch committed: Multiplex goroutines onto OS threads

2012-01-18 Thread Ian Lance Taylor
Rainer Orth r...@cebitec.uni-bielefeld.de writes:

   All tests hang with the default -test.timeout=240.

Thanks for providing access to a Solaris system.

Right now it looks like there is a bug, or at least an incompatibility,
in the 64-bit versions of getcontext and setcontext.  It looks like
calling setcontext on the 32-bit version does not change the value of
TLS variables, which is also the case on GNU/Linux.  In the 64-bit
version, calling setcontext does change the value of TLS variables.
That is, on the 64-bit version, getcontext preserves the value of TLS
variables and setcontext restores the old value.  (Of course it's really
the pointer, not the TLS variables themselves).  This incompatibility
has to be a bug, and of course I would prefer that the incompatibility
be resolved in favor of the implementation used on GNU/Linux.

Here is a program which shows the issue.  Compile with -pthread.  With
-m32 it prints go1: tls == 2.  With -m64 it prints go1: tls == 1.  The
program is too complex for the problem, but it does show the issue.

Ian

#include errno.h
#include stdio.h
#include stdlib.h
#include limits.h
#include pthread.h
#include ucontext.h

__thread int tls;

static void die (const char *) __attribute__ ((noreturn));
static void
die (const char *msg)
{
  perror (msg);
  exit (EXIT_FAILURE);
}

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]);

static void
swap (ucontext_t *fu, void *fs[10], ucontext_t *tu, void *ts[10])
{
  swapcontext (fu, tu);
}

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[1];

  printf (%s %d\n, msg, i);

  if (i  0)
{
  use_buffer (buf);
  swap (me, mes, other, others);
  down (i - 1, msg, me, mes, other, others);
}
  else
{
  printf (i == 0\n);
}
}

static void
go1 (void)
{
  printf (go1: tls == %d\n, tls);
  down (2, go1, c1, s1, c2, s2);
  pthread_exit (NULL);
}

static void
go2 (void)
{
  printf (go2: tls == %d\n, tls);
  down (2, go2, c2, s2, c1, s1);
  pthread_exit (NULL);
}

struct thread_context
{
  ucontext_t *u;
  void **s;
};

static void *
start_thread (void *context)
{
  struct thread_context *tc = (struct thread_context *) context;
  int block;

  printf (start_thread: tls == %d\n, tls);
  tls = 2;
  block = 0;
  setcontext (tc-u);
  die (setcontext);
  return NULL;
}

int
main (int argc __attribute__ ((unused)), char **argv __attribute__ ((unused)))
{
  pthread_t tid;
  int err;
  size_t size;
  struct thread_context tc;
  int block;

  tls = 1;

  if (getcontext (c1)  0)
die (getcontext);

  c2 = c1;

  c1.uc_stack.ss_sp = malloc (1024 * 1024 * 1024);
  if (c1.uc_stack.ss_sp == NULL)
die (malloc);
  c1.uc_stack.ss_flags = 0;
  c1.uc_stack.ss_size = 1024 * 1024 * 1024;
  c1.uc_link = NULL;
  block = 0;
  makecontext (c1, go1, 0);

  c2.uc_stack.ss_sp = malloc (1024 * 1024 * 1024);
  if (c2.uc_stack.ss_sp == NULL)
die (malloc);
  c2.uc_stack.ss_flags = 0;
  c2.uc_stack.ss_size = 1024 * 1024 * 1024;
  c2.uc_link = NULL;
  makecontext (c2, go2, 0);

  tc.u = c1;
  tc.s = s1[0];
  err = pthread_create (tid, NULL, start_thread, tc);
  if (err != 0)
{
  errno = err;
  die (pthread_create);
}

  err = pthread_join (tid, NULL);
  if (err != 0)
{
  errno = err;
  die (pthread_join);
}

  exit (EXIT_SUCCESS);
}


Re: Go patch committed: Multiplex goroutines onto OS threads

2012-01-18 Thread Rainer Orth
Ian Lance Taylor i...@google.com writes:

 Rainer Orth r...@cebitec.uni-bielefeld.de writes:

   All tests hang with the default -test.timeout=240.

 Thanks for providing access to a Solaris system.

 Right now it looks like there is a bug, or at least an incompatibility,
 in the 64-bit versions of getcontext and setcontext.  It looks like
 calling setcontext on the 32-bit version does not change the value of
 TLS variables, which is also the case on GNU/Linux.  In the 64-bit
 version, calling setcontext does change the value of TLS variables.
 That is, on the 64-bit version, getcontext preserves the value of TLS
 variables and setcontext restores the old value.  (Of course it's really
 the pointer, not the TLS variables themselves).  This incompatibility
 has to be a bug, and of course I would prefer that the incompatibility
 be resolved in favor of the implementation used on GNU/Linux.

 Here is a program which shows the issue.  Compile with -pthread.  With
 -m32 it prints go1: tls == 2.  With -m64 it prints go1: tls == 1.  The
 program is too complex for the problem, but it does show the issue.

Thanks for the detective work.  I'll try to find in the OpenSolaris
sources what's going on, at the same time contacting the Solaris
engineers about the issue.

There's more to the problem, though: on Solaris/SPARC (mayon is a
Solaris 11 machine you could use here), both 32 and 64-bit versions of
the test program print tls == 2, but many (not all) libgo tests still
fail.

I also tried the program on IRIX 6.5 (columba, dog slow unfortunately),
which doesn't have native TLS.  It doesn't go beyond the

go1: tls == 2

line, and I had to reduce the stack sizes to 32 MB to allow it to run at
all.  On Tru64 UNIX (haydn), also using emutls, it does run until the

i == 0

line, but doesn't finish.

Rainer

-- 
-
Rainer Orth, Center for Biotechnology, Bielefeld University


Re: Go patch committed: Multiplex goroutines onto OS threads

2011-12-14 Thread Uros Bizjak
On Wed, Dec 14, 2011 at 12:15 AM, Ian Lance Taylor i...@google.com wrote:

 This patch changes the Go library to multiplex goroutines onto operating
 system threads.  Previously, each new goroutine ran in a separate
 thread.  That is inefficient for programs with lots of goroutines.  This
 patch changes the library such that it runs a certain numbers of
 threads, and lets each thread switch between goroutines.  This is how
 the master Go library works, and this patch brings in code from the
 master Go library, adjusted for use by gccgo.

 For some reason I get this failure on alphaev68-pc-linux-gnu:

 --- FAIL: runtime_test.TestGcSys (4.64 seconds)
         using 64 MB
         using too much memory: 64 MB

 Raising the value in runtime/gc_test.go to 10e8 runs the test OK.

 Thanks for reporting this.  I just committed the appended patch to both
 the master Go library and to libgo.  I hope this will fix this problem.
 Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu.

Still no success, now I get:

--- FAIL: runtime_test.TestGcSys (4.21 seconds)
???:1: used 2554104 extra bytes
???:1: using too much memory: 2554104 bytes
FAIL
FAIL: runtime

Uros.


Re: Go patch committed: Multiplex goroutines onto OS threads

2011-12-14 Thread Paolo Bonzini

On 11/28/2011 06:46 AM, Ian Lance Taylor wrote:

This implementation relies on the functions getcontext, setcontext, and
makecontext.  If there are systems which don't have those, getcontext
and setcontext can be replaced by setjmp and longjmp, but there is no
obvious replacement for makecontext.  I think that will have to be
implemented using processor-specific code, as it needs to set the stack
pointer to point to a new stack, and I don't know how to do that in a
portable processor-independent manner without using makecontext.


ARM glibc does not implement these functions, so we have the same 
problem in QEMU.  (On top of this, there is no way that alternate stacks 
can work on OpenBSD, so we still have one coroutine per thread).


For QEMU, I tried replacing for makecontext using sigaltstack.  It works 
on Linux but it needs a dedicated signal, so it is likely inappropriate 
for libgo.  It would also need to be tested across many operating 
systems because it may trigger subtleties in other OSes.


Paolo


Re: Go patch committed: Multiplex goroutines onto OS threads

2011-12-14 Thread Ian Lance Taylor
Uros Bizjak ubiz...@gmail.com writes:

 Still no success, now I get:

 --- FAIL: runtime_test.TestGcSys (4.21 seconds)
 ???:1: used 2554104 extra bytes
 ???:1: using too much memory: 2554104 bytes
 FAIL
 FAIL: runtime

Yeah, I was too aggressive.  It had to be fixed in the master library
too.  This time for sure.  Bootstrapped and ran Go testsuite on
x86_64-unknown-linux-gnu.  Committed to mainline.

Ian

diff -r e97b850a6f33 libgo/go/runtime/gc_test.go
--- a/libgo/go/runtime/gc_test.go	Wed Dec 14 06:46:23 2011 -0800
+++ b/libgo/go/runtime/gc_test.go	Wed Dec 14 06:48:27 2011 -0800
@@ -22,7 +22,7 @@
 		sys = runtime.MemStats.Sys - sys
 	}
 	t.Logf(used %d extra bytes, sys)
-	if sys  220 {
+	if sys  420 {
 		t.Fatalf(using too much memory: %d bytes, sys)
 	}
 }


Re: Go patch committed: Multiplex goroutines onto OS threads

2011-12-14 Thread Ian Lance Taylor
Paolo Bonzini bonz...@gnu.org writes:

 On 11/28/2011 06:46 AM, Ian Lance Taylor wrote:
 This implementation relies on the functions getcontext, setcontext, and
 makecontext.  If there are systems which don't have those, getcontext
 and setcontext can be replaced by setjmp and longjmp, but there is no
 obvious replacement for makecontext.  I think that will have to be
 implemented using processor-specific code, as it needs to set the stack
 pointer to point to a new stack, and I don't know how to do that in a
 portable processor-independent manner without using makecontext.

 ARM glibc does not implement these functions, so we have the same
 problem in QEMU.  (On top of this, there is no way that alternate
 stacks can work on OpenBSD, so we still have one coroutine per
 thread).

The other Go compiler already supports OpenBSD, so it must be possible
in some sense.


 For QEMU, I tried replacing for makecontext using sigaltstack.  It
 works on Linux but it needs a dedicated signal, so it is likely
 inappropriate for libgo.  It would also need to be tested across many
 operating systems because it may trigger subtleties in other OSes.

I don't have any problem using a dedicated signal.  That's an
interesting approach.  I wonder what the relative performance would be.

Anyhow, makecontext is easy to write in a system specific manner.  It
doesn't even have to be written in assembler, though getcontext and
setcontext do have to be assembler.  Why not just implement them for
ARM?

Ian


Re: Go patch committed: Multiplex goroutines onto OS threads

2011-12-14 Thread Peter Maydell
On 14 December 2011 15:00, Ian Lance Taylor i...@google.com wrote:
 Anyhow, makecontext is easy to write in a system specific manner.  It
 doesn't even have to be written in assembler, though getcontext and
 setcontext do have to be assembler.  Why not just implement them for
 ARM?

We're looking at implementing them on ARM, yes. However, obviously
all the existing systems out there have versions that return ENOSYS,
so you might need some fallback code anyway.

-- PMM


Re: Go patch committed: Multiplex goroutines onto OS threads

2011-12-14 Thread Ian Lance Taylor
Peter Maydell peter.mayd...@linaro.org writes:

 On 14 December 2011 15:00, Ian Lance Taylor i...@google.com wrote:
 Anyhow, makecontext is easy to write in a system specific manner.  It
 doesn't even have to be written in assembler, though getcontext and
 setcontext do have to be assembler.  Why not just implement them for
 ARM?

 We're looking at implementing them on ARM, yes. However, obviously
 all the existing systems out there have versions that return ENOSYS,
 so you might need some fallback code anyway.

My fallback would be to simply include the implementations of
makecontext, et. al., with libgo.

Ian


Re: Go patch committed: Multiplex goroutines onto OS threads

2011-12-14 Thread Paolo Bonzini

On 12/14/2011 04:00 PM, Ian Lance Taylor wrote:

   This implementation relies on the functions getcontext, setcontext, and
   makecontext.  If there are systems which don't have those, getcontext
   and setcontext can be replaced by setjmp and longjmp, but there is no
   obvious replacement for makecontext.  I think that will have to be
   implemented using processor-specific code, as it needs to set the stack
   pointer to point to a new stack, and I don't know how to do that in a
   portable processor-independent manner without using makecontext.

  ARM glibc does not implement these functions, so we have the same
  problem in QEMU.  (On top of this, there is no way that alternate
  stacks can work on OpenBSD, so we still have one coroutine per
  thread).

The other Go compiler already supports OpenBSD, so it must be possible
in some sense.


Do they have specialised code for OpenBSD?  I said it cannot work in 
the sense that:


- *context functions are not there;

- sigaltstack always returns EINVAL when using threads;

- the threads are identified by the runtime from their stack pointer, so 
you risk confusing the runtime very much if you switch between coroutines.



I don't have any problem using a dedicated signal.  That's an
interesting approach.  I wonder what the relative performance would be.


You can look at the code at git://github.com/bonzini/qemu.git, branch 
coroutine-fix.


Paolo


Re: Go patch committed: Multiplex goroutines onto OS threads

2011-12-14 Thread Ian Lance Taylor
Paolo Bonzini bonz...@gnu.org writes:

 On 12/14/2011 04:00 PM, Ian Lance Taylor wrote:

 The other Go compiler already supports OpenBSD, so it must be possible
 in some sense.

 Do they have specialised code for OpenBSD?  I said it cannot work in
 the sense that:

 - *context functions are not there;

The other Go compiler does not use the *context functions--it doesn't
use libc at all.  It uses assembler code which has a similar effect.

 - sigaltstack always returns EINVAL when using threads;

That is odd.  sigaltstack is very useful when using threads.

 - the threads are identified by the runtime from their stack pointer,
 so you risk confusing the runtime very much if you switch between
 coroutines.

I'm not sure what this means--I'm not sure which runtime you're
referring to here.

Ian


Re: Go patch committed: Multiplex goroutines onto OS threads

2011-12-14 Thread Paolo Bonzini

On 12/14/2011 04:45 PM, Ian Lance Taylor wrote:

  - sigaltstack always returns EINVAL when using threads;

That is odd.  sigaltstack is very useful when using threads.


  - the threads are identified by the runtime from their stack pointer,
  so you risk confusing the runtime very much if you switch between
  coroutines.

I'm not sure what this means--I'm not sure which runtime you're
referring to here.


The OpenBSD thread runtime.  It's similar to old LinuxThreads, but with 
only 1 kernel thread per process IIUC.


Paolo


Re: Go patch committed: Multiplex goroutines onto OS threads

2011-12-14 Thread Ian Lance Taylor
Paolo Bonzini bonz...@gnu.org writes:

 On 12/14/2011 04:45 PM, Ian Lance Taylor wrote:
   - sigaltstack always returns EINVAL when using threads;
 That is odd.  sigaltstack is very useful when using threads.

   - the threads are identified by the runtime from their stack pointer,
   so you risk confusing the runtime very much if you switch between
   coroutines.
 I'm not sure what this means--I'm not sure which runtime you're
 referring to here.

 The OpenBSD thread runtime.  It's similar to old LinuxThreads, but
 with only 1 kernel thread per process IIUC.

Oh, hmmm, that might be a problem.

The other Go compiler seems to use the rfork system call to create new
threads, passing RFPROC | RFTHREAD | RFMEM | RFNOWAIT.

Ian


Re: Go patch committed: Multiplex goroutines onto OS threads

2011-12-14 Thread Paolo Bonzini

On 12/14/2011 05:04 PM, Ian Lance Taylor wrote:

  The OpenBSD thread runtime.  It's similar to old LinuxThreads, but
  with only 1 kernel thread per process IIUC.

Oh, hmmm, that might be a problem.

The other Go compiler seems to use the rfork system call to create new
threads, passing RFPROC | RFTHREAD | RFMEM | RFNOWAIT.


Yeah, found it now... it implements basically its own thread runtime. 
But it only has spinlocks right now.


Paolo



Re: Go patch committed: Multiplex goroutines onto OS threads

2011-12-13 Thread Ian Lance Taylor
Rainer Orth r...@cebitec.uni-bielefeld.de writes:

 Ian Lance Taylor i...@google.com writes:

 of any differences between Solaris and GNU/Linux when it comes to the
 getcontext, setcontext, and makecontext functions?

 I've just found something in Solaris 11 makecontext(3C) (NOTES section),
 but that doesn't explain why 32-bit Solaris/x86 works, while 64-bit
 doesn't:

   http://docs.oracle.com/cd/E23824_01/html/821-1465/makecontext-3c.html

Wow, that's annoying.  You're right, though, it seems that that ought to
affect both x86 and x86_64.

Ian


Re: Go patch committed: Multiplex goroutines onto OS threads

2011-12-13 Thread Rainer Orth
Ian Lance Taylor i...@google.com writes:

 Rainer Orth r...@cebitec.uni-bielefeld.de writes:

 Ian Lance Taylor i...@google.com writes:

 Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu.  Tested
 both with and without -fsplit-stack support.  Committed to mainline.

 Once Go bootstrap works again on Solaris, I notice that there are many
 64-bit testsuite failures, which have been introduced between 2025
 (r181724) and 2030 (r181837), so this patch is the obvious culprit.

 I just committed another libgo update, which will no doubt lead to
 further problems.

Only a few minor compilation problems, fixed with the following patch.

Rainer


diff --git a/libgo/go/net/fd_select.go b/libgo/go/net/fd_select.go
--- a/libgo/go/net/fd_select.go
+++ b/libgo/go/net/fd_select.go
@@ -85,7 +85,8 @@ func (p *pollster) WaitFD(s *pollServer,
 			timeout = tv
 		}
 
-		var n, e int
+		var n int
+		var e error
 		var tmpReadFds, tmpWriteFds syscall.FdSet
 		for {
 			// Temporary syscall.FdSet's into which the values are copied
@@ -101,7 +102,7 @@ func (p *pollster) WaitFD(s *pollServer,
 break
 			}
 		}
-		if e != 0 {
+		if e != nil {
 			return -1, 0, os.NewSyscallError(select, e)
 		}
 		if n == 0 {
diff --git a/libgo/go/os/sys_uname.go b/libgo/go/os/sys_uname.go
--- a/libgo/go/os/sys_uname.go
+++ b/libgo/go/os/sys_uname.go
@@ -10,7 +10,7 @@ import syscall
 
 func Hostname() (name string, err error) {
 	var u syscall.Utsname
-	if errno := syscall.Uname(u); errno != 0 {
+	if errno := syscall.Uname(u); errno != nil {
 		return , NewSyscallError(uname, errno)
 	}
 	b := make([]byte, len(u.Nodename))


-- 
-
Rainer Orth, Center for Biotechnology, Bielefeld University


Re: Go patch committed: Multiplex goroutines onto OS threads

2011-12-13 Thread Ian Lance Taylor
Rainer Orth r...@cebitec.uni-bielefeld.de writes:

 Only a few minor compilation problems, fixed with the following patch.

Thanks.  Committed.

Ian


Re: Go patch committed: Multiplex goroutines onto OS threads

2011-12-13 Thread Ian Lance Taylor
Uros Bizjak ubiz...@gmail.com writes:

 This patch changes the Go library to multiplex goroutines onto operating
 system threads.  Previously, each new goroutine ran in a separate
 thread.  That is inefficient for programs with lots of goroutines.  This
 patch changes the library such that it runs a certain numbers of
 threads, and lets each thread switch between goroutines.  This is how
 the master Go library works, and this patch brings in code from the
 master Go library, adjusted for use by gccgo.

 For some reason I get this failure on alphaev68-pc-linux-gnu:

 --- FAIL: runtime_test.TestGcSys (4.64 seconds)
 using 64 MB
 using too much memory: 64 MB

 Raising the value in runtime/gc_test.go to 10e8 runs the test OK.

Thanks for reporting this.  I just committed the appended patch to both
the master Go library and to libgo.  I hope this will fix this problem.
Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu.

Ian

diff -r 832d9ebdb3c6 libgo/go/runtime/gc_test.go
--- a/libgo/go/runtime/gc_test.go	Tue Dec 13 14:24:59 2011 -0800
+++ b/libgo/go/runtime/gc_test.go	Tue Dec 13 15:13:43 2011 -0800
@@ -6,16 +6,24 @@
 )
 
 func TestGcSys(t *testing.T) {
+	runtime.GC()
+	runtime.UpdateMemStats()
+	sys := runtime.MemStats.Sys
+
 	for i := 0; i  100; i++ {
 		workthegc()
 	}
 
 	// Should only be using a few MB.
 	runtime.UpdateMemStats()
-	sys := runtime.MemStats.Sys
-	t.Logf(using %d MB, sys20)
-	if sys  10e6 {
-		t.Fatalf(using too much memory: %d MB, sys20)
+	if sys  runtime.MemStats.Sys {
+		sys = 0
+	} else {
+		sys = runtime.MemStats.Sys - sys
+	}
+	t.Logf(used %d extra bytes, sys)
+	if sys  220 {
+		t.Fatalf(using too much memory: %d bytes, sys)
 	}
 }
 


Re: Go patch committed: Multiplex goroutines onto OS threads

2011-12-12 Thread Rainer Orth
Uros Bizjak ubiz...@gmail.com writes:

 For some reason I get this failure on alphaev68-pc-linux-gnu:

 --- FAIL: runtime_test.TestGcSys (4.64 seconds)
 using 64 MB
 using too much memory: 64 MB

I see the same on Solaris/x86:

--- FAIL: runtime_test.TestGcSys (2.76 seconds)
using 63 MB
using too much memory: 63 MB
FAIL
FAIL: runtime

Rainer

-- 
-
Rainer Orth, Center for Biotechnology, Bielefeld University


Re: Go patch committed: Multiplex goroutines onto OS threads

2011-12-12 Thread Rainer Orth
Ian Lance Taylor i...@google.com writes:

 Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu.  Tested
 both with and without -fsplit-stack support.  Committed to mainline.

Once Go bootstrap works again on Solaris, I notice that there are many
64-bit testsuite failures, which have been introduced between 2025
(r181724) and 2030 (r181837), so this patch is the obvious culprit.

The failures are as follows:

* In the go.* tests:

FAIL: ./select5-out.go compilation,  -O2 -g 
WARNING: program timed out.

  32-bit compilation on idle system (1.6 GHz Core i7 Q720, so a
  reasonably up-to-date system):

./select5-out.go: In function 'main.$init4':
./select5-out.go:19326:1: note: variable tracking size limit exceeded with 
-fvar-tracking-assignments, retrying without

real2:04.06
user2:03.43
sys0.35

  with -fno-var-tracking-assignments:

real1:09.87
user1:09.57
sys0.20

  With parallel make check, the runtime can easily exceed the default
  300s timeout.

* 64-bit failures:

FAIL: go.test/test/chan/doubleselect.go execution,  -O2 -g 

throw: malloc/free - deadlock
panic during panic

  The messages don't show up in go.log, they goes to stdout,
  cf. runtime/runtime.h where runtime_printf is just printf.

FAIL: go.test/test/chan/select2.go execution,  -O2 -g 

BUG: too much memory for 100,000 selects: 2098448

  This test used to fail intermittendly, now the failure seems constant.

FAIL: go.test/test/chan/select3.go execution,  -O2 -g 

throw: gosched of g0

FAIL: go.test/test/fixedbugs/bug147.go execution,  -O2 -g 

throw: gosched of g0

FAIL: go.test/test/goprint.go execution,  -O2 -g 

throw: gosched holding locks

  sometimes

throw: bad gp-status in sched

FAIL: go.test/test/mallocfin.go execution,  -O2 -g 

throw: gosched holding locks

FAIL: go.test/test/nil.go execution,  -O2 -g 

throw: gosched holding locks

FAIL: go.test/test/stack.go execution,  -O2 -g 

  SEGV from a stack overflow, this test seems to require split-stack
  support and doesn't even work with unlimited stack size.

* libgo testsuite failures:

  All tests hang with the default -test.timeout=240.  When I remove
  that, some (like bufio) simply pass, while others run into errors
  similar to the above:

goroutine 2 has status 1
throw: bad g-status in ready

I've tried to make some sense of it, but don't really know where to
start looking.

The situation on Solaris/SPARC is considerably worse (large number of
32-bit failures, too, all 32-bit libgo tests fail), but I think it's
preferable to get it working again on x86 before checking what remains
on SPARC.

Rainer

-- 
-
Rainer Orth, Center for Biotechnology, Bielefeld University


Re: Go patch committed: Multiplex goroutines onto OS threads

2011-12-12 Thread Ian Lance Taylor
Rainer Orth r...@cebitec.uni-bielefeld.de writes:

 Ian Lance Taylor i...@google.com writes:

 Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu.  Tested
 both with and without -fsplit-stack support.  Committed to mainline.

 Once Go bootstrap works again on Solaris, I notice that there are many
 64-bit testsuite failures, which have been introduced between 2025
 (r181724) and 2030 (r181837), so this patch is the obvious culprit.

I just committed another libgo update, which will no doubt lead to
further problems.

In order to debug these problems I think I will need access to an x86
Solaris system.  Otherwise I don't know what is happening.  Do you know
of any differences between Solaris and GNU/Linux when it comes to the
getcontext, setcontext, and makecontext functions?

Ian


Re: Go patch committed: Multiplex goroutines onto OS threads

2011-12-01 Thread Rainer Orth
Ian Lance Taylor i...@google.com writes:

 This patch changes the Go library to multiplex goroutines onto operating
 system threads.  Previously, each new goroutine ran in a separate
 thread.  That is inefficient for programs with lots of goroutines.  This
 patch changes the library such that it runs a certain numbers of
 threads, and lets each thread switch between goroutines.  This is how
 the master Go library works, and this patch brings in code from the
 master Go library, adjusted for use by gccgo.
[...]
 Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu.  Tested
 both with and without -fsplit-stack support.  Committed to mainline.

Unfortunately, this patch broke Solaris bootstrap (and would break IRIX
bootstrap if this ever started working again):

/vol/gcc/src/hg/trunk/local/libgo/runtime/go-signal.c:221:1: error: conflicting 
types for 'sigignore'
In file included from /vol/gcc/src/hg/trunk/local/libgo/runtime/go-signal.c:7:0:
/var/gcc/regression/trunk/8-gcc/build/./gcc/include-fixed/signal.h:100:12: note:
 previous declaration of 'sigignore' was here
make[4]: *** [go-signal.lo] Error 1

signal.h on all of Solaris, IRIX, and Tru64 UNIX has

extern int sigignore(int);

I've fixed this by using sig_ignore instead.

Rainer


diff --git a/libgo/runtime/go-signal.c b/libgo/runtime/go-signal.c
--- a/libgo/runtime/go-signal.c
+++ b/libgo/runtime/go-signal.c
@@ -218,7 +218,7 @@ sighandler (int sig)
 /* Ignore a signal.  */
 
 static void
-sigignore (int sig __attribute__ ((unused)))
+sig_ignore (int sig __attribute__ ((unused)))
 {
 }
 
@@ -247,7 +247,7 @@ runtime_initsig (int32 queue)
   if (signals[i].catch || signals[i].queue)
sa.sa_handler = sighandler;
   else
-   sa.sa_handler = sigignore;
+   sa.sa_handler = sig_ignore;
   sa.sa_flags = signals[i].restart ? SA_RESTART : 0;
   if (sigaction (signals[i].sig, sa, NULL) != 0)
__go_assert (0);


-- 
-
Rainer Orth, Center for Biotechnology, Bielefeld University


Re: Go patch committed: Multiplex goroutines onto OS threads

2011-12-01 Thread Ian Lance Taylor
Rainer Orth r...@cebitec.uni-bielefeld.de writes:

 Unfortunately, this patch broke Solaris bootstrap (and would break IRIX
 bootstrap if this ever started working again):

 /vol/gcc/src/hg/trunk/local/libgo/runtime/go-signal.c:221:1: error: 
 conflicting types for 'sigignore'
 In file included from 
 /vol/gcc/src/hg/trunk/local/libgo/runtime/go-signal.c:7:0:
 /var/gcc/regression/trunk/8-gcc/build/./gcc/include-fixed/signal.h:100:12: 
 note:
  previous declaration of 'sigignore' was here
 make[4]: *** [go-signal.lo] Error 1

 signal.h on all of Solaris, IRIX, and Tru64 UNIX has

 extern int sigignore(int);

 I've fixed this by using sig_ignore instead.

Thanks.  Patch committed.

Ian


Re: Go patch committed: Multiplex goroutines onto OS threads

2011-11-28 Thread Uros Bizjak
Hello!

 This patch changes the Go library to multiplex goroutines onto operating
 system threads.  Previously, each new goroutine ran in a separate
 thread.  That is inefficient for programs with lots of goroutines.  This
 patch changes the library such that it runs a certain numbers of
 threads, and lets each thread switch between goroutines.  This is how
 the master Go library works, and this patch brings in code from the
 master Go library, adjusted for use by gccgo.

For some reason I get this failure on alphaev68-pc-linux-gnu:

--- FAIL: runtime_test.TestGcSys (4.64 seconds)
using 64 MB
using too much memory: 64 MB

Raising the value in runtime/gc_test.go to 10e8 runs the test OK.

Uros.