summaryrefslogtreecommitdiff
path: root/libgo
diff options
context:
space:
mode:
Diffstat (limited to 'libgo')
-rw-r--r--libgo/Makefile.am16
-rw-r--r--libgo/Makefile.in182
-rw-r--r--libgo/runtime/chan.c1248
-rw-r--r--libgo/runtime/chan.goc57
-rw-r--r--libgo/runtime/channel.h152
-rw-r--r--libgo/runtime/go-chan-cap.c41
-rw-r--r--libgo/runtime/go-chan-len.c41
-rw-r--r--libgo/runtime/go-close.c42
-rw-r--r--libgo/runtime/go-new-channel.c70
-rw-r--r--libgo/runtime/go-rec-big.c43
-rw-r--r--libgo/runtime/go-rec-nb-big.c46
-rw-r--r--libgo/runtime/go-rec-nb-small.c123
-rw-r--r--libgo/runtime/go-rec-small.c304
-rw-r--r--libgo/runtime/go-reflect-chan.c200
-rw-r--r--libgo/runtime/go-select.c758
-rw-r--r--libgo/runtime/go-send-big.c34
-rw-r--r--libgo/runtime/go-send-nb-big.c33
-rw-r--r--libgo/runtime/go-send-nb-small.c107
-rw-r--r--libgo/runtime/go-send-small.c159
-rw-r--r--libgo/runtime/go-signal.c4
-rw-r--r--libgo/runtime/runtime.h11
-rw-r--r--libgo/runtime/thread.c24
22 files changed, 1282 insertions, 2413 deletions
diff --git a/libgo/Makefile.am b/libgo/Makefile.am
index 5ab10a61f3d..19ce7152cf1 100644
--- a/libgo/Makefile.am
+++ b/libgo/Makefile.am
@@ -409,10 +409,7 @@ runtime_files = \
runtime/go-caller.c \
runtime/go-can-convert-interface.c \
runtime/go-cgo.c \
- runtime/go-chan-cap.c \
- runtime/go-chan-len.c \
runtime/go-check-interface.c \
- runtime/go-close.c \
runtime/go-construct-map.c \
runtime/go-convert-interface.c \
runtime/go-copy.c \
@@ -432,27 +429,16 @@ runtime_files = \
runtime/go-map-len.c \
runtime/go-map-range.c \
runtime/go-nanotime.c \
- runtime/go-new-channel.c \
runtime/go-new-map.c \
runtime/go-new.c \
runtime/go-panic.c \
runtime/go-print.c \
- runtime/go-rec-big.c \
- runtime/go-rec-nb-big.c \
- runtime/go-rec-nb-small.c \
- runtime/go-rec-small.c \
runtime/go-recover.c \
runtime/go-reflect.c \
runtime/go-reflect-call.c \
- runtime/go-reflect-chan.c \
runtime/go-reflect-map.c \
runtime/go-rune.c \
runtime/go-runtime-error.c \
- runtime/go-select.c \
- runtime/go-send-big.c \
- runtime/go-send-nb-big.c \
- runtime/go-send-nb-small.c \
- runtime/go-send-small.c \
runtime/go-setenv.c \
runtime/go-signal.c \
runtime/go-strcmp.c \
@@ -473,6 +459,7 @@ runtime_files = \
runtime/go-unsafe-newarray.c \
runtime/go-unsafe-pointer.c \
runtime/go-unwind.c \
+ runtime/chan.c \
runtime/cpuprof.c \
$(runtime_lock_files) \
runtime/mcache.c \
@@ -488,7 +475,6 @@ runtime_files = \
runtime/thread.c \
runtime/yield.c \
$(rtems_task_variable_add_file) \
- chan.c \
iface.c \
malloc.c \
map.c \
diff --git a/libgo/Makefile.in b/libgo/Makefile.in
index f7c293a66cc..1a76f0b5a20 100644
--- a/libgo/Makefile.in
+++ b/libgo/Makefile.in
@@ -183,8 +183,7 @@ am__libgo_la_SOURCES_DIST = runtime/go-append.c runtime/go-assert.c \
runtime/go-assert-interface.c \
runtime/go-byte-array-to-string.c runtime/go-breakpoint.c \
runtime/go-caller.c runtime/go-can-convert-interface.c \
- runtime/go-cgo.c runtime/go-chan-cap.c runtime/go-chan-len.c \
- runtime/go-check-interface.c runtime/go-close.c \
+ runtime/go-cgo.c runtime/go-check-interface.c \
runtime/go-construct-map.c runtime/go-convert-interface.c \
runtime/go-copy.c runtime/go-defer.c \
runtime/go-deferred-recover.c runtime/go-eface-compare.c \
@@ -195,17 +194,11 @@ am__libgo_la_SOURCES_DIST = runtime/go-append.c runtime/go-assert.c \
runtime/go-interface-val-compare.c runtime/go-make-slice.c \
runtime/go-map-delete.c runtime/go-map-index.c \
runtime/go-map-len.c runtime/go-map-range.c \
- runtime/go-nanotime.c runtime/go-new-channel.c \
- runtime/go-new-map.c runtime/go-new.c runtime/go-panic.c \
- runtime/go-print.c runtime/go-rec-big.c \
- runtime/go-rec-nb-big.c runtime/go-rec-nb-small.c \
- runtime/go-rec-small.c runtime/go-recover.c \
+ runtime/go-nanotime.c runtime/go-new-map.c runtime/go-new.c \
+ runtime/go-panic.c runtime/go-print.c runtime/go-recover.c \
runtime/go-reflect.c runtime/go-reflect-call.c \
- runtime/go-reflect-chan.c runtime/go-reflect-map.c \
- runtime/go-rune.c runtime/go-runtime-error.c \
- runtime/go-select.c runtime/go-send-big.c \
- runtime/go-send-nb-big.c runtime/go-send-nb-small.c \
- runtime/go-send-small.c runtime/go-setenv.c \
+ runtime/go-reflect-map.c runtime/go-rune.c \
+ runtime/go-runtime-error.c runtime/go-setenv.c \
runtime/go-signal.c runtime/go-strcmp.c \
runtime/go-string-to-byte-array.c \
runtime/go-string-to-int-array.c runtime/go-strplus.c \
@@ -215,15 +208,15 @@ am__libgo_la_SOURCES_DIST = runtime/go-append.c runtime/go-assert.c \
runtime/go-type-string.c runtime/go-typedesc-equal.c \
runtime/go-typestring.c runtime/go-unreflect.c \
runtime/go-unsafe-new.c runtime/go-unsafe-newarray.c \
- runtime/go-unsafe-pointer.c runtime/go-unwind.c \
+ runtime/go-unsafe-pointer.c runtime/go-unwind.c runtime/chan.c \
runtime/cpuprof.c runtime/lock_sema.c runtime/thread-sema.c \
runtime/lock_futex.c runtime/thread-linux.c runtime/mcache.c \
runtime/mcentral.c runtime/mem_posix_memalign.c runtime/mem.c \
runtime/mfinal.c runtime/mfixalloc.c runtime/mgc0.c \
runtime/mheap.c runtime/msize.c runtime/proc.c \
runtime/runtime.c runtime/thread.c runtime/yield.c \
- runtime/rtems-task-variable-add.c chan.c iface.c malloc.c \
- map.c mprof.c reflect.c runtime1.c sema.c sigqueue.c string.c
+ runtime/rtems-task-variable-add.c iface.c malloc.c map.c \
+ mprof.c reflect.c runtime1.c sema.c sigqueue.c string.c
@LIBGO_IS_LINUX_FALSE@am__objects_1 = lock_sema.lo thread-sema.lo
@LIBGO_IS_LINUX_TRUE@am__objects_1 = lock_futex.lo thread-linux.lo
@HAVE_SYS_MMAN_H_FALSE@am__objects_2 = mem_posix_memalign.lo
@@ -231,8 +224,7 @@ am__libgo_la_SOURCES_DIST = runtime/go-append.c runtime/go-assert.c \
@LIBGO_IS_RTEMS_TRUE@am__objects_3 = rtems-task-variable-add.lo
am__objects_4 = go-append.lo go-assert.lo go-assert-interface.lo \
go-byte-array-to-string.lo go-breakpoint.lo go-caller.lo \
- go-can-convert-interface.lo go-cgo.lo go-chan-cap.lo \
- go-chan-len.lo go-check-interface.lo go-close.lo \
+ go-can-convert-interface.lo go-cgo.lo go-check-interface.lo \
go-construct-map.lo go-convert-interface.lo go-copy.lo \
go-defer.lo go-deferred-recover.lo go-eface-compare.lo \
go-eface-val-compare.lo go-getgoroot.lo \
@@ -240,23 +232,20 @@ am__objects_4 = go-append.lo go-assert.lo go-assert-interface.lo \
go-interface-compare.lo go-interface-eface-compare.lo \
go-interface-val-compare.lo go-make-slice.lo go-map-delete.lo \
go-map-index.lo go-map-len.lo go-map-range.lo go-nanotime.lo \
- go-new-channel.lo go-new-map.lo go-new.lo go-panic.lo \
- go-print.lo go-rec-big.lo go-rec-nb-big.lo go-rec-nb-small.lo \
- go-rec-small.lo go-recover.lo go-reflect.lo go-reflect-call.lo \
- go-reflect-chan.lo go-reflect-map.lo go-rune.lo \
- go-runtime-error.lo go-select.lo go-send-big.lo \
- go-send-nb-big.lo go-send-nb-small.lo go-send-small.lo \
- go-setenv.lo go-signal.lo go-strcmp.lo \
+ go-new-map.lo go-new.lo go-panic.lo go-print.lo go-recover.lo \
+ go-reflect.lo go-reflect-call.lo go-reflect-map.lo go-rune.lo \
+ go-runtime-error.lo go-setenv.lo go-signal.lo go-strcmp.lo \
go-string-to-byte-array.lo go-string-to-int-array.lo \
go-strplus.lo go-strslice.lo go-trampoline.lo go-type-eface.lo \
go-type-error.lo go-type-identity.lo go-type-interface.lo \
go-type-string.lo go-typedesc-equal.lo go-typestring.lo \
go-unreflect.lo go-unsafe-new.lo go-unsafe-newarray.lo \
- go-unsafe-pointer.lo go-unwind.lo cpuprof.lo $(am__objects_1) \
- mcache.lo mcentral.lo $(am__objects_2) mfinal.lo mfixalloc.lo \
- mgc0.lo mheap.lo msize.lo proc.lo runtime.lo thread.lo \
- yield.lo $(am__objects_3) chan.lo iface.lo malloc.lo map.lo \
- mprof.lo reflect.lo runtime1.lo sema.lo sigqueue.lo string.lo
+ go-unsafe-pointer.lo go-unwind.lo chan.lo cpuprof.lo \
+ $(am__objects_1) mcache.lo mcentral.lo $(am__objects_2) \
+ mfinal.lo mfixalloc.lo mgc0.lo mheap.lo msize.lo proc.lo \
+ runtime.lo thread.lo yield.lo $(am__objects_3) iface.lo \
+ malloc.lo map.lo mprof.lo reflect.lo runtime1.lo sema.lo \
+ sigqueue.lo string.lo
am_libgo_la_OBJECTS = $(am__objects_4)
libgo_la_OBJECTS = $(am_libgo_la_OBJECTS)
libgo_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
@@ -836,10 +825,7 @@ runtime_files = \
runtime/go-caller.c \
runtime/go-can-convert-interface.c \
runtime/go-cgo.c \
- runtime/go-chan-cap.c \
- runtime/go-chan-len.c \
runtime/go-check-interface.c \
- runtime/go-close.c \
runtime/go-construct-map.c \
runtime/go-convert-interface.c \
runtime/go-copy.c \
@@ -859,27 +845,16 @@ runtime_files = \
runtime/go-map-len.c \
runtime/go-map-range.c \
runtime/go-nanotime.c \
- runtime/go-new-channel.c \
runtime/go-new-map.c \
runtime/go-new.c \
runtime/go-panic.c \
runtime/go-print.c \
- runtime/go-rec-big.c \
- runtime/go-rec-nb-big.c \
- runtime/go-rec-nb-small.c \
- runtime/go-rec-small.c \
runtime/go-recover.c \
runtime/go-reflect.c \
runtime/go-reflect-call.c \
- runtime/go-reflect-chan.c \
runtime/go-reflect-map.c \
runtime/go-rune.c \
runtime/go-runtime-error.c \
- runtime/go-select.c \
- runtime/go-send-big.c \
- runtime/go-send-nb-big.c \
- runtime/go-send-nb-small.c \
- runtime/go-send-small.c \
runtime/go-setenv.c \
runtime/go-signal.c \
runtime/go-strcmp.c \
@@ -900,6 +875,7 @@ runtime_files = \
runtime/go-unsafe-newarray.c \
runtime/go-unsafe-pointer.c \
runtime/go-unwind.c \
+ runtime/chan.c \
runtime/cpuprof.c \
$(runtime_lock_files) \
runtime/mcache.c \
@@ -915,7 +891,6 @@ runtime_files = \
runtime/thread.c \
runtime/yield.c \
$(rtems_task_variable_add_file) \
- chan.c \
iface.c \
malloc.c \
map.c \
@@ -2461,10 +2436,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-caller.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-can-convert-interface.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-cgo.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-chan-cap.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-chan-len.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-check-interface.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-close.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-construct-map.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-convert-interface.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-copy.Plo@am__quote@
@@ -2485,27 +2457,16 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-map-len.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-map-range.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-nanotime.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-new-channel.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-new-map.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-new.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-panic.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-print.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-rec-big.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-rec-nb-big.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-rec-nb-small.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-rec-small.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-recover.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-reflect-call.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-reflect-chan.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-reflect-map.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-reflect.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-rune.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-runtime-error.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-select.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-send-big.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-send-nb-big.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-send-nb-small.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-send-small.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-setenv.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-signal.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-strcmp.Plo@am__quote@
@@ -2645,20 +2606,6 @@ go-cgo.lo: runtime/go-cgo.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-cgo.lo `test -f 'runtime/go-cgo.c' || echo '$(srcdir)/'`runtime/go-cgo.c
-go-chan-cap.lo: runtime/go-chan-cap.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-chan-cap.lo -MD -MP -MF $(DEPDIR)/go-chan-cap.Tpo -c -o go-chan-cap.lo `test -f 'runtime/go-chan-cap.c' || echo '$(srcdir)/'`runtime/go-chan-cap.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-chan-cap.Tpo $(DEPDIR)/go-chan-cap.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-chan-cap.c' object='go-chan-cap.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-chan-cap.lo `test -f 'runtime/go-chan-cap.c' || echo '$(srcdir)/'`runtime/go-chan-cap.c
-
-go-chan-len.lo: runtime/go-chan-len.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-chan-len.lo -MD -MP -MF $(DEPDIR)/go-chan-len.Tpo -c -o go-chan-len.lo `test -f 'runtime/go-chan-len.c' || echo '$(srcdir)/'`runtime/go-chan-len.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-chan-len.Tpo $(DEPDIR)/go-chan-len.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-chan-len.c' object='go-chan-len.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-chan-len.lo `test -f 'runtime/go-chan-len.c' || echo '$(srcdir)/'`runtime/go-chan-len.c
-
go-check-interface.lo: runtime/go-check-interface.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-check-interface.lo -MD -MP -MF $(DEPDIR)/go-check-interface.Tpo -c -o go-check-interface.lo `test -f 'runtime/go-check-interface.c' || echo '$(srcdir)/'`runtime/go-check-interface.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-check-interface.Tpo $(DEPDIR)/go-check-interface.Plo
@@ -2666,13 +2613,6 @@ go-check-interface.lo: runtime/go-check-interface.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-check-interface.lo `test -f 'runtime/go-check-interface.c' || echo '$(srcdir)/'`runtime/go-check-interface.c
-go-close.lo: runtime/go-close.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-close.lo -MD -MP -MF $(DEPDIR)/go-close.Tpo -c -o go-close.lo `test -f 'runtime/go-close.c' || echo '$(srcdir)/'`runtime/go-close.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-close.Tpo $(DEPDIR)/go-close.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-close.c' object='go-close.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-close.lo `test -f 'runtime/go-close.c' || echo '$(srcdir)/'`runtime/go-close.c
-
go-construct-map.lo: runtime/go-construct-map.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-construct-map.lo -MD -MP -MF $(DEPDIR)/go-construct-map.Tpo -c -o go-construct-map.lo `test -f 'runtime/go-construct-map.c' || echo '$(srcdir)/'`runtime/go-construct-map.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-construct-map.Tpo $(DEPDIR)/go-construct-map.Plo
@@ -2806,13 +2746,6 @@ go-nanotime.lo: runtime/go-nanotime.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-nanotime.lo `test -f 'runtime/go-nanotime.c' || echo '$(srcdir)/'`runtime/go-nanotime.c
-go-new-channel.lo: runtime/go-new-channel.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-new-channel.lo -MD -MP -MF $(DEPDIR)/go-new-channel.Tpo -c -o go-new-channel.lo `test -f 'runtime/go-new-channel.c' || echo '$(srcdir)/'`runtime/go-new-channel.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-new-channel.Tpo $(DEPDIR)/go-new-channel.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-new-channel.c' object='go-new-channel.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-new-channel.lo `test -f 'runtime/go-new-channel.c' || echo '$(srcdir)/'`runtime/go-new-channel.c
-
go-new-map.lo: runtime/go-new-map.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-new-map.lo -MD -MP -MF $(DEPDIR)/go-new-map.Tpo -c -o go-new-map.lo `test -f 'runtime/go-new-map.c' || echo '$(srcdir)/'`runtime/go-new-map.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-new-map.Tpo $(DEPDIR)/go-new-map.Plo
@@ -2841,34 +2774,6 @@ go-print.lo: runtime/go-print.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-print.lo `test -f 'runtime/go-print.c' || echo '$(srcdir)/'`runtime/go-print.c
-go-rec-big.lo: runtime/go-rec-big.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-rec-big.lo -MD -MP -MF $(DEPDIR)/go-rec-big.Tpo -c -o go-rec-big.lo `test -f 'runtime/go-rec-big.c' || echo '$(srcdir)/'`runtime/go-rec-big.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-rec-big.Tpo $(DEPDIR)/go-rec-big.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-rec-big.c' object='go-rec-big.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-rec-big.lo `test -f 'runtime/go-rec-big.c' || echo '$(srcdir)/'`runtime/go-rec-big.c
-
-go-rec-nb-big.lo: runtime/go-rec-nb-big.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-rec-nb-big.lo -MD -MP -MF $(DEPDIR)/go-rec-nb-big.Tpo -c -o go-rec-nb-big.lo `test -f 'runtime/go-rec-nb-big.c' || echo '$(srcdir)/'`runtime/go-rec-nb-big.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-rec-nb-big.Tpo $(DEPDIR)/go-rec-nb-big.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-rec-nb-big.c' object='go-rec-nb-big.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-rec-nb-big.lo `test -f 'runtime/go-rec-nb-big.c' || echo '$(srcdir)/'`runtime/go-rec-nb-big.c
-
-go-rec-nb-small.lo: runtime/go-rec-nb-small.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-rec-nb-small.lo -MD -MP -MF $(DEPDIR)/go-rec-nb-small.Tpo -c -o go-rec-nb-small.lo `test -f 'runtime/go-rec-nb-small.c' || echo '$(srcdir)/'`runtime/go-rec-nb-small.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-rec-nb-small.Tpo $(DEPDIR)/go-rec-nb-small.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-rec-nb-small.c' object='go-rec-nb-small.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-rec-nb-small.lo `test -f 'runtime/go-rec-nb-small.c' || echo '$(srcdir)/'`runtime/go-rec-nb-small.c
-
-go-rec-small.lo: runtime/go-rec-small.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-rec-small.lo -MD -MP -MF $(DEPDIR)/go-rec-small.Tpo -c -o go-rec-small.lo `test -f 'runtime/go-rec-small.c' || echo '$(srcdir)/'`runtime/go-rec-small.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-rec-small.Tpo $(DEPDIR)/go-rec-small.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-rec-small.c' object='go-rec-small.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-rec-small.lo `test -f 'runtime/go-rec-small.c' || echo '$(srcdir)/'`runtime/go-rec-small.c
-
go-recover.lo: runtime/go-recover.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-recover.lo -MD -MP -MF $(DEPDIR)/go-recover.Tpo -c -o go-recover.lo `test -f 'runtime/go-recover.c' || echo '$(srcdir)/'`runtime/go-recover.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-recover.Tpo $(DEPDIR)/go-recover.Plo
@@ -2890,13 +2795,6 @@ go-reflect-call.lo: runtime/go-reflect-call.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-reflect-call.lo `test -f 'runtime/go-reflect-call.c' || echo '$(srcdir)/'`runtime/go-reflect-call.c
-go-reflect-chan.lo: runtime/go-reflect-chan.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-reflect-chan.lo -MD -MP -MF $(DEPDIR)/go-reflect-chan.Tpo -c -o go-reflect-chan.lo `test -f 'runtime/go-reflect-chan.c' || echo '$(srcdir)/'`runtime/go-reflect-chan.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-reflect-chan.Tpo $(DEPDIR)/go-reflect-chan.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-reflect-chan.c' object='go-reflect-chan.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-reflect-chan.lo `test -f 'runtime/go-reflect-chan.c' || echo '$(srcdir)/'`runtime/go-reflect-chan.c
-
go-reflect-map.lo: runtime/go-reflect-map.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-reflect-map.lo -MD -MP -MF $(DEPDIR)/go-reflect-map.Tpo -c -o go-reflect-map.lo `test -f 'runtime/go-reflect-map.c' || echo '$(srcdir)/'`runtime/go-reflect-map.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-reflect-map.Tpo $(DEPDIR)/go-reflect-map.Plo
@@ -2918,41 +2816,6 @@ go-runtime-error.lo: runtime/go-runtime-error.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-runtime-error.lo `test -f 'runtime/go-runtime-error.c' || echo '$(srcdir)/'`runtime/go-runtime-error.c
-go-select.lo: runtime/go-select.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-select.lo -MD -MP -MF $(DEPDIR)/go-select.Tpo -c -o go-select.lo `test -f 'runtime/go-select.c' || echo '$(srcdir)/'`runtime/go-select.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-select.Tpo $(DEPDIR)/go-select.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-select.c' object='go-select.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-select.lo `test -f 'runtime/go-select.c' || echo '$(srcdir)/'`runtime/go-select.c
-
-go-send-big.lo: runtime/go-send-big.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-send-big.lo -MD -MP -MF $(DEPDIR)/go-send-big.Tpo -c -o go-send-big.lo `test -f 'runtime/go-send-big.c' || echo '$(srcdir)/'`runtime/go-send-big.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-send-big.Tpo $(DEPDIR)/go-send-big.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-send-big.c' object='go-send-big.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-send-big.lo `test -f 'runtime/go-send-big.c' || echo '$(srcdir)/'`runtime/go-send-big.c
-
-go-send-nb-big.lo: runtime/go-send-nb-big.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-send-nb-big.lo -MD -MP -MF $(DEPDIR)/go-send-nb-big.Tpo -c -o go-send-nb-big.lo `test -f 'runtime/go-send-nb-big.c' || echo '$(srcdir)/'`runtime/go-send-nb-big.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-send-nb-big.Tpo $(DEPDIR)/go-send-nb-big.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-send-nb-big.c' object='go-send-nb-big.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-send-nb-big.lo `test -f 'runtime/go-send-nb-big.c' || echo '$(srcdir)/'`runtime/go-send-nb-big.c
-
-go-send-nb-small.lo: runtime/go-send-nb-small.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-send-nb-small.lo -MD -MP -MF $(DEPDIR)/go-send-nb-small.Tpo -c -o go-send-nb-small.lo `test -f 'runtime/go-send-nb-small.c' || echo '$(srcdir)/'`runtime/go-send-nb-small.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-send-nb-small.Tpo $(DEPDIR)/go-send-nb-small.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-send-nb-small.c' object='go-send-nb-small.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-send-nb-small.lo `test -f 'runtime/go-send-nb-small.c' || echo '$(srcdir)/'`runtime/go-send-nb-small.c
-
-go-send-small.lo: runtime/go-send-small.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-send-small.lo -MD -MP -MF $(DEPDIR)/go-send-small.Tpo -c -o go-send-small.lo `test -f 'runtime/go-send-small.c' || echo '$(srcdir)/'`runtime/go-send-small.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-send-small.Tpo $(DEPDIR)/go-send-small.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-send-small.c' object='go-send-small.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-send-small.lo `test -f 'runtime/go-send-small.c' || echo '$(srcdir)/'`runtime/go-send-small.c
-
go-setenv.lo: runtime/go-setenv.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-setenv.lo -MD -MP -MF $(DEPDIR)/go-setenv.Tpo -c -o go-setenv.lo `test -f 'runtime/go-setenv.c' || echo '$(srcdir)/'`runtime/go-setenv.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-setenv.Tpo $(DEPDIR)/go-setenv.Plo
@@ -3093,6 +2956,13 @@ go-unwind.lo: runtime/go-unwind.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-unwind.lo `test -f 'runtime/go-unwind.c' || echo '$(srcdir)/'`runtime/go-unwind.c
+chan.lo: runtime/chan.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT chan.lo -MD -MP -MF $(DEPDIR)/chan.Tpo -c -o chan.lo `test -f 'runtime/chan.c' || echo '$(srcdir)/'`runtime/chan.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/chan.Tpo $(DEPDIR)/chan.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/chan.c' object='chan.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o chan.lo `test -f 'runtime/chan.c' || echo '$(srcdir)/'`runtime/chan.c
+
cpuprof.lo: runtime/cpuprof.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cpuprof.lo -MD -MP -MF $(DEPDIR)/cpuprof.Tpo -c -o cpuprof.lo `test -f 'runtime/cpuprof.c' || echo '$(srcdir)/'`runtime/cpuprof.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/cpuprof.Tpo $(DEPDIR)/cpuprof.Plo
diff --git a/libgo/runtime/chan.c b/libgo/runtime/chan.c
new file mode 100644
index 00000000000..a246992c60b
--- /dev/null
+++ b/libgo/runtime/chan.c
@@ -0,0 +1,1248 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "runtime.h"
+#include "go-type.h"
+
+#define NOSELGEN 1
+
+static int32 debug = 0;
+
+typedef struct WaitQ WaitQ;
+typedef struct SudoG SudoG;
+typedef struct Select Select;
+typedef struct Scase Scase;
+
+typedef struct __go_type_descriptor Type;
+typedef struct __go_channel_type ChanType;
+
+struct SudoG
+{
+ G* g; // g and selgen constitute
+ uint32 selgen; // a weak pointer to g
+ SudoG* link;
+ byte* elem; // data element
+};
+
+struct WaitQ
+{
+ SudoG* first;
+ SudoG* last;
+};
+
+struct Hchan
+{
+ uint32 qcount; // total data in the q
+ uint32 dataqsiz; // size of the circular q
+ uint16 elemsize;
+ bool closed;
+ uint8 elemalign;
+ uint32 sendx; // send index
+ uint32 recvx; // receive index
+ WaitQ recvq; // list of recv waiters
+ WaitQ sendq; // list of send waiters
+ Lock;
+};
+
+// Buffer follows Hchan immediately in memory.
+// chanbuf(c, i) is pointer to the i'th slot in the buffer.
+#define chanbuf(c, i) ((byte*)((c)+1)+(uintptr)(c)->elemsize*(i))
+
+enum
+{
+ // Scase.kind
+ CaseRecv,
+ CaseSend,
+ CaseDefault,
+};
+
+struct Scase
+{
+ SudoG sg; // must be first member (cast to Scase)
+ Hchan* chan; // chan
+ uint16 kind;
+ uint16 index; // index to return
+ bool* receivedp; // pointer to received bool (recv2)
+};
+
+struct Select
+{
+ uint16 tcase; // total count of scase[]
+ uint16 ncase; // currently filled scase[]
+ uint16* pollorder; // case poll order
+ Hchan** lockorder; // channel lock order
+ Scase scase[1]; // one per case (in order of appearance)
+};
+
+static void dequeueg(WaitQ*);
+static SudoG* dequeue(WaitQ*);
+static void enqueue(WaitQ*, SudoG*);
+
+Hchan*
+runtime_makechan_c(ChanType *t, int64 hint)
+{
+ Hchan *c;
+ int32 n;
+ const Type *elem;
+
+ elem = t->__element_type;
+
+ if(hint < 0 || (int32)hint != hint || (elem->__size > 0 && (uintptr)hint > ((uintptr)-1) / elem->__size))
+ runtime_panicstring("makechan: size out of range");
+
+ n = sizeof(*c);
+
+ // allocate memory in one call
+ c = (Hchan*)runtime_mal(n + hint*elem->__size);
+ c->elemsize = elem->__size;
+ c->elemalign = elem->__align;
+ c->dataqsiz = hint;
+
+ if(debug)
+ runtime_printf("makechan: chan=%p; elemsize=%lld; elemalign=%d; dataqsiz=%d\n",
+ c, (long long)elem->__size, elem->__align, c->dataqsiz);
+
+ return c;
+}
+
+// For reflect
+// func makechan(typ *ChanType, size uint32) (chan)
+uintptr reflect_makechan(ChanType *, uint32)
+ asm ("libgo_reflect.reflect.makechan");
+
+uintptr
+reflect_makechan(ChanType *t, uint32 size)
+{
+ void *ret;
+ Hchan *c;
+
+ c = runtime_makechan_c(t, size);
+ ret = runtime_mal(sizeof(void*));
+ __builtin_memcpy(ret, &c, sizeof(void*));
+ return (uintptr)ret;
+}
+
+// makechan(t *ChanType, hint int64) (hchan *chan any);
+Hchan*
+__go_new_channel(ChanType *t, uintptr hint)
+{
+ return runtime_makechan_c(t, hint);
+}
+
+/*
+ * generic single channel send/recv
+ * if the bool pointer is nil,
+ * then the full exchange will
+ * occur. if pres is not nil,
+ * then the protocol will not
+ * sleep but return if it could
+ * not complete.
+ *
+ * sleep can wake up with g->param == nil
+ * when a channel involved in the sleep has
+ * been closed. it is easiest to loop and re-run
+ * the operation; we'll see that it's now closed.
+ */
+void
+runtime_chansend(ChanType *t, Hchan *c, byte *ep, bool *pres)
+{
+ SudoG *sg;
+ SudoG mysg;
+ G* gp;
+ G* g;
+
+ g = runtime_g();
+
+ if(c == nil) {
+ USED(t);
+ if(pres != nil) {
+ *pres = false;
+ return;
+ }
+ g->status = Gwaiting;
+ g->waitreason = "chan send (nil chan)";
+ runtime_gosched();
+ return; // not reached
+ }
+
+ if(runtime_gcwaiting)
+ runtime_gosched();
+
+ if(debug) {
+ runtime_printf("chansend: chan=%p\n", c);
+ }
+
+ runtime_lock(c);
+ if(c->closed)
+ goto closed;
+
+ if(c->dataqsiz > 0)
+ goto asynch;
+
+ sg = dequeue(&c->recvq);
+ if(sg != nil) {
+ runtime_unlock(c);
+
+ gp = sg->g;
+ gp->param = sg;
+ if(sg->elem != nil)
+ runtime_memmove(sg->elem, ep, c->elemsize);
+ runtime_ready(gp);
+
+ if(pres != nil)
+ *pres = true;
+ return;
+ }
+
+ if(pres != nil) {
+ runtime_unlock(c);
+ *pres = false;
+ return;
+ }
+
+ mysg.elem = ep;
+ mysg.g = g;
+ mysg.selgen = NOSELGEN;
+ g->param = nil;
+ g->status = Gwaiting;
+ g->waitreason = "chan send";
+ enqueue(&c->sendq, &mysg);
+ runtime_unlock(c);
+ runtime_gosched();
+
+ if(g->param == nil) {
+ runtime_lock(c);
+ if(!c->closed)
+ runtime_throw("chansend: spurious wakeup");
+ goto closed;
+ }
+
+ return;
+
+asynch:
+ if(c->closed)
+ goto closed;
+
+ if(c->qcount >= c->dataqsiz) {
+ if(pres != nil) {
+ runtime_unlock(c);
+ *pres = false;
+ return;
+ }
+ mysg.g = g;
+ mysg.elem = nil;
+ mysg.selgen = NOSELGEN;
+ g->status = Gwaiting;
+ g->waitreason = "chan send";
+ enqueue(&c->sendq, &mysg);
+ runtime_unlock(c);
+ runtime_gosched();
+
+ runtime_lock(c);
+ goto asynch;
+ }
+ runtime_memmove(chanbuf(c, c->sendx), ep, c->elemsize);
+ if(++c->sendx == c->dataqsiz)
+ c->sendx = 0;
+ c->qcount++;
+
+ sg = dequeue(&c->recvq);
+ if(sg != nil) {
+ gp = sg->g;
+ runtime_unlock(c);
+ runtime_ready(gp);
+ } else
+ runtime_unlock(c);
+ if(pres != nil)
+ *pres = true;
+ return;
+
+closed:
+ runtime_unlock(c);
+ runtime_panicstring("send on closed channel");
+}
+
+
+void
+runtime_chanrecv(ChanType *t, Hchan* c, byte *ep, bool *selected, bool *received)
+{
+ SudoG *sg;
+ SudoG mysg;
+ G *gp;
+ G *g;
+
+ if(runtime_gcwaiting)
+ runtime_gosched();
+
+ if(debug)
+ runtime_printf("chanrecv: chan=%p\n", c);
+
+ g = runtime_g();
+
+ if(c == nil) {
+ USED(t);
+ if(selected != nil) {
+ *selected = false;
+ return;
+ }
+ g->status = Gwaiting;
+ g->waitreason = "chan receive (nil chan)";
+ runtime_gosched();
+ return; // not reached
+ }
+
+ runtime_lock(c);
+ if(c->dataqsiz > 0)
+ goto asynch;
+
+ if(c->closed)
+ goto closed;
+
+ sg = dequeue(&c->sendq);
+ if(sg != nil) {
+ runtime_unlock(c);
+
+ if(ep != nil)
+ runtime_memmove(ep, sg->elem, c->elemsize);
+ gp = sg->g;
+ gp->param = sg;
+ runtime_ready(gp);
+
+ if(selected != nil)
+ *selected = true;
+ if(received != nil)
+ *received = true;
+ return;
+ }
+
+ if(selected != nil) {
+ runtime_unlock(c);
+ *selected = false;
+ return;
+ }
+
+ mysg.elem = ep;
+ mysg.g = g;
+ mysg.selgen = NOSELGEN;
+ g->param = nil;
+ g->status = Gwaiting;
+ g->waitreason = "chan receive";
+ enqueue(&c->recvq, &mysg);
+ runtime_unlock(c);
+ runtime_gosched();
+
+ if(g->param == nil) {
+ runtime_lock(c);
+ if(!c->closed)
+ runtime_throw("chanrecv: spurious wakeup");
+ goto closed;
+ }
+
+ if(received != nil)
+ *received = true;
+ return;
+
+asynch:
+ if(c->qcount <= 0) {
+ if(c->closed)
+ goto closed;
+
+ if(selected != nil) {
+ runtime_unlock(c);
+ *selected = false;
+ if(received != nil)
+ *received = false;
+ return;
+ }
+ mysg.g = g;
+ mysg.elem = nil;
+ mysg.selgen = NOSELGEN;
+ g->status = Gwaiting;
+ g->waitreason = "chan receive";
+ enqueue(&c->recvq, &mysg);
+ runtime_unlock(c);
+ runtime_gosched();
+
+ runtime_lock(c);
+ goto asynch;
+ }
+ if(ep != nil)
+ runtime_memmove(ep, chanbuf(c, c->recvx), c->elemsize);
+ runtime_memclr(chanbuf(c, c->recvx), c->elemsize);
+ if(++c->recvx == c->dataqsiz)
+ c->recvx = 0;
+ c->qcount--;
+
+ sg = dequeue(&c->sendq);
+ if(sg != nil) {
+ gp = sg->g;
+ runtime_unlock(c);
+ runtime_ready(gp);
+ } else
+ runtime_unlock(c);
+
+ if(selected != nil)
+ *selected = true;
+ if(received != nil)
+ *received = true;
+ return;
+
+closed:
+ if(ep != nil)
+ runtime_memclr(ep, c->elemsize);
+ if(selected != nil)
+ *selected = true;
+ if(received != nil)
+ *received = false;
+ runtime_unlock(c);
+}
+
+// The compiler generates a call to __go_send_small to send a value 8
+// bytes or smaller.
+void
+__go_send_small(ChanType *t, Hchan* c, uint64 val)
+{
+ byte b[sizeof(uint64)];
+
+ runtime_memclr(b, sizeof(uint64));
+ __builtin_memcpy(b, &val, t->__element_type->__size);
+ runtime_chansend(t, c, b, nil);
+}
+
+// The compiler generates a call to __go_send_big to send a value
+// larger than 8 bytes or smaller.
+void
+__go_send_big(ChanType *t, Hchan* c, byte* p)
+{
+ runtime_chansend(t, c, p, nil);
+}
+
+// The compiler generates a call to __go_receive_small to receive a
+// value 8 bytes or smaller.
+uint64
+__go_receive_small(ChanType *t, Hchan* c)
+{
+ union {
+ byte b[sizeof(uint64)];
+ uint64 v;
+ } u;
+
+ u.v = 0;
+ runtime_chanrecv(t, c, u.b, nil, nil);
+ return u.v;
+}
+
+// The compiler generates a call to __go_receive_big to receive a
+// value larger than 8 bytes.
+void
+__go_receive_big(ChanType *t, Hchan* c, byte* p)
+{
+ runtime_chanrecv(t, c, p, nil, nil);
+}
+
+_Bool runtime_chanrecv2(ChanType *t, Hchan* c, byte* p)
+ __asm__("runtime.chanrecv2");
+
+_Bool
+runtime_chanrecv2(ChanType *t, Hchan* c, byte* p)
+{
+ bool received;
+
+ runtime_chanrecv(t, c, p, nil, &received);
+ return received;
+}
+
+// func selectnbsend(c chan any, elem any) bool
+//
+// compiler implements
+//
+// select {
+// case c <- v:
+// ... foo
+// default:
+// ... bar
+// }
+//
+// as
+//
+// if selectnbsend(c, v) {
+// ... foo
+// } else {
+// ... bar
+// }
+//
+_Bool
+runtime_selectnbsend(ChanType *t, Hchan *c, byte *p)
+{
+ bool res;
+
+ runtime_chansend(t, c, p, &res);
+ return res;
+}
+
+// func selectnbrecv(elem *any, c chan any) bool
+//
+// compiler implements
+//
+// select {
+// case v = <-c:
+// ... foo
+// default:
+// ... bar
+// }
+//
+// as
+//
+// if selectnbrecv(&v, c) {
+// ... foo
+// } else {
+// ... bar
+// }
+//
+_Bool
+runtime_selectnbrecv(ChanType *t, byte *v, Hchan *c)
+{
+ bool selected;
+
+ runtime_chanrecv(t, c, v, &selected, nil);
+ return selected;
+}
+
+// func selectnbrecv2(elem *any, ok *bool, c chan any) bool
+//
+// compiler implements
+//
+// select {
+// case v, ok = <-c:
+// ... foo
+// default:
+// ... bar
+// }
+//
+// as
+//
+// if c != nil && selectnbrecv2(&v, &ok, c) {
+// ... foo
+// } else {
+// ... bar
+// }
+//
+_Bool
+runtime_selectnbrecv2(ChanType *t, byte *v, _Bool *received, Hchan *c)
+{
+ bool selected;
+ bool r;
+
+ r = false;
+ runtime_chanrecv(t, c, v, &selected, received == nil ? nil : &r);
+ if(received != nil)
+ *received = r;
+ return selected;
+}
+
+// For reflect:
+// func chansend(c chan, val iword, nb bool) (selected bool)
+// where an iword is the same word an interface value would use:
+// the actual data if it fits, or else a pointer to the data.
+
+_Bool reflect_chansend(ChanType *, Hchan *, uintptr, _Bool)
+ __asm__("libgo_reflect.reflect.chansend");
+
+_Bool
+reflect_chansend(ChanType *t, Hchan *c, uintptr val, _Bool nb)
+{
+ bool selected;
+ bool *sp;
+ byte *vp;
+
+ if(nb) {
+ selected = false;
+ sp = (bool*)&selected;
+ } else {
+ selected = true;
+ sp = nil;
+ }
+ if(__go_is_pointer_type(t->__element_type))
+ vp = (byte*)&val;
+ else
+ vp = (byte*)val;
+ runtime_chansend(t, c, vp, sp);
+ return selected;
+}
+
+// For reflect:
+// func chanrecv(c chan, nb bool) (val iword, selected, received bool)
+// where an iword is the same word an interface value would use:
+// the actual data if it fits, or else a pointer to the data.
+
+struct chanrecv_ret
+{
+ uintptr val;
+ _Bool selected;
+ _Bool received;
+};
+
+struct chanrecv_ret reflect_chanrecv(ChanType *, Hchan *, _Bool)
+ __asm__("libgo_reflect.reflect.chanrecv");
+
+struct chanrecv_ret
+reflect_chanrecv(ChanType *t, Hchan *c, _Bool nb)
+{
+ struct chanrecv_ret ret;
+ byte *vp;
+ bool *sp;
+ bool selected;
+ bool received;
+
+ if(nb) {
+ selected = false;
+ sp = &selected;
+ } else {
+ ret.selected = true;
+ sp = nil;
+ }
+ received = false;
+ if(__go_is_pointer_type(t->__element_type)) {
+ vp = (byte*)&ret.val;
+ } else {
+ vp = runtime_mal(t->__element_type->__size);
+ ret.val = (uintptr)vp;
+ }
+ runtime_chanrecv(t, c, vp, sp, &received);
+ if(nb)
+ ret.selected = selected;
+ ret.received = received;
+ return ret;
+}
+
+static void newselect(int32, Select**);
+
+// newselect(size uint32) (sel *byte);
+
+void* runtime_newselect(int) __asm__("runtime.newselect");
+
+void*
+runtime_newselect(int size)
+{
+ Select *sel;
+
+ newselect(size, &sel);
+ return (void*)sel;
+}
+
+static void
+newselect(int32 size, Select **selp)
+{
+ int32 n;
+ Select *sel;
+
+ n = 0;
+ if(size > 1)
+ n = size-1;
+
+ sel = runtime_mal(sizeof(*sel) +
+ n*sizeof(sel->scase[0]) +
+ size*sizeof(sel->lockorder[0]) +
+ size*sizeof(sel->pollorder[0]));
+
+ sel->tcase = size;
+ sel->ncase = 0;
+ sel->pollorder = (void*)(sel->scase + size);
+ sel->lockorder = (void*)(sel->pollorder + size);
+ *selp = sel;
+
+ if(debug)
+ runtime_printf("newselect s=%p size=%d\n", sel, size);
+}
+
+// cut in half to give stack a chance to split
+static void selectsend(Select *sel, Hchan *c, int index, void *elem);
+
+// selectsend(sel *byte, hchan *chan any, elem *any) (selected bool);
+
+void runtime_selectsend(Select *, Hchan *, void *, int)
+ __asm__("runtime.selectsend");
+
+void
+runtime_selectsend(Select *sel, Hchan *c, void *elem, int index)
+{
+ // nil cases do not compete
+ if(c == nil)
+ return;
+
+ selectsend(sel, c, index, elem);
+}
+
+static void
+selectsend(Select *sel, Hchan *c, int index, void *elem)
+{
+ int32 i;
+ Scase *cas;
+
+ i = sel->ncase;
+ if(i >= sel->tcase)
+ runtime_throw("selectsend: too many cases");
+ sel->ncase = i+1;
+ cas = &sel->scase[i];
+
+ cas->index = index;
+ cas->chan = c;
+ cas->kind = CaseSend;
+ cas->sg.elem = elem;
+
+ if(debug)
+ runtime_printf("selectsend s=%p index=%d chan=%p\n",
+ sel, cas->index, cas->chan);
+}
+
+// cut in half to give stack a chance to split
+static void selectrecv(Select *sel, Hchan *c, int index, void *elem, bool*);
+
+// selectrecv(sel *byte, hchan *chan any, elem *any) (selected bool);
+
+void runtime_selectrecv(Select *, Hchan *, void *, int)
+ __asm__("runtime.selectrecv");
+
+void
+runtime_selectrecv(Select *sel, Hchan *c, void *elem, int index)
+{
+ // nil cases do not compete
+ if(c == nil)
+ return;
+
+ selectrecv(sel, c, index, elem, nil);
+}
+
+// selectrecv2(sel *byte, hchan *chan any, elem *any, received *bool) (selected bool);
+
+void runtime_selectrecv2(Select *, Hchan *, void *, bool *, int)
+ __asm__("runtime.selectrecv2");
+
+void
+runtime_selectrecv2(Select *sel, Hchan *c, void *elem, bool *received, int index)
+{
+ // nil cases do not compete
+ if(c == nil)
+ return;
+
+ selectrecv(sel, c, index, elem, received);
+}
+
+static void
+selectrecv(Select *sel, Hchan *c, int index, void *elem, bool *received)
+{
+ int32 i;
+ Scase *cas;
+
+ i = sel->ncase;
+ if(i >= sel->tcase)
+ runtime_throw("selectrecv: too many cases");
+ sel->ncase = i+1;
+ cas = &sel->scase[i];
+ cas->index = index;
+ cas->chan = c;
+
+ cas->kind = CaseRecv;
+ cas->sg.elem = elem;
+ cas->receivedp = received;
+
+ if(debug)
+ runtime_printf("selectrecv s=%p index=%d chan=%p\n",
+ sel, cas->index, cas->chan);
+}
+
+// cut in half to give stack a chance to split
+static void selectdefault(Select*, int);
+
+// selectdefault(sel *byte) (selected bool);
+
+void runtime_selectdefault(Select *, int) __asm__("runtime.selectdefault");
+
+void
+runtime_selectdefault(Select *sel, int index)
+{
+ selectdefault(sel, index);
+}
+
+static void
+selectdefault(Select *sel, int index)
+{
+ int32 i;
+ Scase *cas;
+
+ i = sel->ncase;
+ if(i >= sel->tcase)
+ runtime_throw("selectdefault: too many cases");
+ sel->ncase = i+1;
+ cas = &sel->scase[i];
+ cas->index = index;
+ cas->chan = nil;
+
+ cas->kind = CaseDefault;
+
+ if(debug)
+ runtime_printf("selectdefault s=%p index=%d\n",
+ sel, cas->index);
+}
+
+static void
+sellock(Select *sel)
+{
+ uint32 i;
+ Hchan *c, *c0;
+
+ c = nil;
+ for(i=0; i<sel->ncase; i++) {
+ c0 = sel->lockorder[i];
+ if(c0 && c0 != c) {
+ c = sel->lockorder[i];
+ runtime_lock(c);
+ }
+ }
+}
+
+static void
+selunlock(Select *sel)
+{
+ uint32 i;
+ Hchan *c, *c0;
+
+ c = nil;
+ for(i=sel->ncase; i-->0;) {
+ c0 = sel->lockorder[i];
+ if(c0 && c0 != c) {
+ c = c0;
+ runtime_unlock(c);
+ }
+ }
+}
+
+void
+runtime_block(void)
+{
+ G *g;
+
+ g = runtime_g();
+ g->status = Gwaiting; // forever
+ g->waitreason = "select (no cases)";
+ runtime_gosched();
+}
+
+static int selectgo(Select**);
+
+// selectgo(sel *byte);
+
+int runtime_selectgo(Select *) __asm__("runtime.selectgo");
+
+int
+runtime_selectgo(Select *sel)
+{
+ return selectgo(&sel);
+}
+
+static int
+selectgo(Select **selp)
+{
+ Select *sel;
+ uint32 o, i, j;
+ Scase *cas, *dfl;
+ Hchan *c;
+ SudoG *sg;
+ G *gp;
+ int index;
+ G *g;
+
+ sel = *selp;
+ if(runtime_gcwaiting)
+ runtime_gosched();
+
+ if(debug)
+ runtime_printf("select: sel=%p\n", sel);
+
+ g = runtime_g();
+
+ // The compiler rewrites selects that statically have
+ // only 0 or 1 cases plus default into simpler constructs.
+ // The only way we can end up with such small sel->ncase
+ // values here is for a larger select in which most channels
+ // have been nilled out. The general code handles those
+ // cases correctly, and they are rare enough not to bother
+ // optimizing (and needing to test).
+
+ // generate permuted order
+ for(i=0; i<sel->ncase; i++)
+ sel->pollorder[i] = i;
+ for(i=1; i<sel->ncase; i++) {
+ o = sel->pollorder[i];
+ j = runtime_fastrand1()%(i+1);
+ sel->pollorder[i] = sel->pollorder[j];
+ sel->pollorder[j] = o;
+ }
+
+ // sort the cases by Hchan address to get the locking order.
+ for(i=0; i<sel->ncase; i++) {
+ c = sel->scase[i].chan;
+ for(j=i; j>0 && sel->lockorder[j-1] >= c; j--)
+ sel->lockorder[j] = sel->lockorder[j-1];
+ sel->lockorder[j] = c;
+ }
+ sellock(sel);
+
+loop:
+ // pass 1 - look for something already waiting
+ dfl = nil;
+ for(i=0; i<sel->ncase; i++) {
+ o = sel->pollorder[i];
+ cas = &sel->scase[o];
+ c = cas->chan;
+
+ switch(cas->kind) {
+ case CaseRecv:
+ if(c->dataqsiz > 0) {
+ if(c->qcount > 0)
+ goto asyncrecv;
+ } else {
+ sg = dequeue(&c->sendq);
+ if(sg != nil)
+ goto syncrecv;
+ }
+ if(c->closed)
+ goto rclose;
+ break;
+
+ case CaseSend:
+ if(c->closed)
+ goto sclose;
+ if(c->dataqsiz > 0) {
+ if(c->qcount < c->dataqsiz)
+ goto asyncsend;
+ } else {
+ sg = dequeue(&c->recvq);
+ if(sg != nil)
+ goto syncsend;
+ }
+ break;
+
+ case CaseDefault:
+ dfl = cas;
+ break;
+ }
+ }
+
+ if(dfl != nil) {
+ selunlock(sel);
+ cas = dfl;
+ goto retc;
+ }
+
+
+ // pass 2 - enqueue on all chans
+ for(i=0; i<sel->ncase; i++) {
+ o = sel->pollorder[i];
+ cas = &sel->scase[o];
+ c = cas->chan;
+ sg = &cas->sg;
+ sg->g = g;
+ sg->selgen = g->selgen;
+
+ switch(cas->kind) {
+ case CaseRecv:
+ enqueue(&c->recvq, sg);
+ break;
+
+ case CaseSend:
+ enqueue(&c->sendq, sg);
+ break;
+ }
+ }
+
+ g->param = nil;
+ g->status = Gwaiting;
+ g->waitreason = "select";
+ selunlock(sel);
+ runtime_gosched();
+
+ sellock(sel);
+ sg = g->param;
+
+ // pass 3 - dequeue from unsuccessful chans
+ // otherwise they stack up on quiet channels
+ for(i=0; i<sel->ncase; i++) {
+ cas = &sel->scase[i];
+ if(cas != (Scase*)sg) {
+ c = cas->chan;
+ if(cas->kind == CaseSend)
+ dequeueg(&c->sendq);
+ else
+ dequeueg(&c->recvq);
+ }
+ }
+
+ if(sg == nil)
+ goto loop;
+
+ cas = (Scase*)sg;
+ c = cas->chan;
+
+ if(c->dataqsiz > 0)
+ runtime_throw("selectgo: shouldnt happen");
+
+ if(debug)
+ runtime_printf("wait-return: sel=%p c=%p cas=%p kind=%d\n",
+ sel, c, cas, cas->kind);
+
+ if(cas->kind == CaseRecv) {
+ if(cas->receivedp != nil)
+ *cas->receivedp = true;
+ }
+
+ selunlock(sel);
+ goto retc;
+
+asyncrecv:
+ // can receive from buffer
+ if(cas->receivedp != nil)
+ *cas->receivedp = true;
+ if(cas->sg.elem != nil)
+ runtime_memmove(cas->sg.elem, chanbuf(c, c->recvx), c->elemsize);
+ runtime_memclr(chanbuf(c, c->recvx), c->elemsize);
+ if(++c->recvx == c->dataqsiz)
+ c->recvx = 0;
+ c->qcount--;
+ sg = dequeue(&c->sendq);
+ if(sg != nil) {
+ gp = sg->g;
+ selunlock(sel);
+ runtime_ready(gp);
+ } else {
+ selunlock(sel);
+ }
+ goto retc;
+
+asyncsend:
+ // can send to buffer
+ runtime_memmove(chanbuf(c, c->sendx), cas->sg.elem, c->elemsize);
+ if(++c->sendx == c->dataqsiz)
+ c->sendx = 0;
+ c->qcount++;
+ sg = dequeue(&c->recvq);
+ if(sg != nil) {
+ gp = sg->g;
+ selunlock(sel);
+ runtime_ready(gp);
+ } else {
+ selunlock(sel);
+ }
+ goto retc;
+
+syncrecv:
+ // can receive from sleeping sender (sg)
+ selunlock(sel);
+ if(debug)
+ runtime_printf("syncrecv: sel=%p c=%p o=%d\n", sel, c, o);
+ if(cas->receivedp != nil)
+ *cas->receivedp = true;
+ if(cas->sg.elem != nil)
+ runtime_memmove(cas->sg.elem, sg->elem, c->elemsize);
+ gp = sg->g;
+ gp->param = sg;
+ runtime_ready(gp);
+ goto retc;
+
+rclose:
+ // read at end of closed channel
+ selunlock(sel);
+ if(cas->receivedp != nil)
+ *cas->receivedp = false;
+ if(cas->sg.elem != nil)
+ runtime_memclr(cas->sg.elem, c->elemsize);
+ goto retc;
+
+syncsend:
+ // can send to sleeping receiver (sg)
+ selunlock(sel);
+ if(debug)
+ runtime_printf("syncsend: sel=%p c=%p o=%d\n", sel, c, o);
+ if(sg->elem != nil)
+ runtime_memmove(sg->elem, cas->sg.elem, c->elemsize);
+ gp = sg->g;
+ gp->param = sg;
+ runtime_ready(gp);
+
+retc:
+ // return index corresponding to chosen case
+ index = cas->index;
+ runtime_free(sel);
+ return index;
+
+sclose:
+ // send on closed channel
+ selunlock(sel);
+ runtime_panicstring("send on closed channel");
+ return 0; // not reached
+}
+
+// closechan(sel *byte);
+void
+runtime_closechan(Hchan *c)
+{
+ SudoG *sg;
+ G* gp;
+
+ if(c == nil)
+ runtime_panicstring("close of nil channel");
+
+ if(runtime_gcwaiting)
+ runtime_gosched();
+
+ runtime_lock(c);
+ if(c->closed) {
+ runtime_unlock(c);
+ runtime_panicstring("close of closed channel");
+ }
+
+ c->closed = true;
+
+ // release all readers
+ for(;;) {
+ sg = dequeue(&c->recvq);
+ if(sg == nil)
+ break;
+ gp = sg->g;
+ gp->param = nil;
+ runtime_ready(gp);
+ }
+
+ // release all writers
+ for(;;) {
+ sg = dequeue(&c->sendq);
+ if(sg == nil)
+ break;
+ gp = sg->g;
+ gp->param = nil;
+ runtime_ready(gp);
+ }
+
+ runtime_unlock(c);
+}
+
+void
+__go_builtin_close(Hchan *c)
+{
+ runtime_closechan(c);
+}
+
+// For reflect
+// func chanclose(c chan)
+
+void reflect_chanclose(uintptr) __asm__("libgo_reflect.reflect.chanclose");
+
+void
+reflect_chanclose(uintptr c)
+{
+ runtime_closechan((Hchan*)c);
+}
+
+// For reflect
+// func chanlen(c chan) (len int32)
+
+int32 reflect_chanlen(uintptr) __asm__("libgo_reflect.reflect.chanlen");
+
+int32
+reflect_chanlen(uintptr ca)
+{
+ Hchan *c;
+ int32 len;
+
+ c = (Hchan*)ca;
+ if(c == nil)
+ len = 0;
+ else
+ len = c->qcount;
+ return len;
+}
+
+int
+__go_chan_len(Hchan *c)
+{
+ return reflect_chanlen((uintptr)c);
+}
+
+// For reflect
+// func chancap(c chan) (cap int32)
+
+int32 reflect_chancap(uintptr) __asm__("libgo_reflect.reflect.chancap");
+
+int32
+reflect_chancap(uintptr ca)
+{
+ Hchan *c;
+ int32 cap;
+
+ c = (Hchan*)ca;
+ if(c == nil)
+ cap = 0;
+ else
+ cap = c->dataqsiz;
+ return cap;
+}
+
+int
+__go_chan_cap(Hchan *c)
+{
+ return reflect_chancap((uintptr)c);
+}
+
+static SudoG*
+dequeue(WaitQ *q)
+{
+ SudoG *sgp;
+
+loop:
+ sgp = q->first;
+ if(sgp == nil)
+ return nil;
+ q->first = sgp->link;
+
+ // if sgp is stale, ignore it
+ if(sgp->selgen != NOSELGEN &&
+ (sgp->selgen != sgp->g->selgen ||
+ !runtime_cas(&sgp->g->selgen, sgp->selgen, sgp->selgen + 2))) {
+ //prints("INVALID PSEUDOG POINTER\n");
+ goto loop;
+ }
+
+ return sgp;
+}
+
+static void
+dequeueg(WaitQ *q)
+{
+ SudoG **l, *sgp, *prevsgp;
+ G *g;
+
+ g = runtime_g();
+ prevsgp = nil;
+ for(l=&q->first; (sgp=*l) != nil; l=&sgp->link, prevsgp=sgp) {
+ if(sgp->g == g) {
+ *l = sgp->link;
+ if(q->last == sgp)
+ q->last = prevsgp;
+ break;
+ }
+ }
+}
+
+static void
+enqueue(WaitQ *q, SudoG *sgp)
+{
+ sgp->link = nil;
+ if(q->first == nil) {
+ q->first = sgp;
+ q->last = sgp;
+ return;
+ }
+ q->last->link = sgp;
+ q->last = sgp;
+}
diff --git a/libgo/runtime/chan.goc b/libgo/runtime/chan.goc
deleted file mode 100644
index c3cc3e39879..00000000000
--- a/libgo/runtime/chan.goc
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package runtime
-#include "config.h"
-#include "channel.h"
-
-#define nil NULL
-
-typedef _Bool bool;
-typedef unsigned char byte;
-typedef struct __go_channel chan;
-
-/* Do a channel receive with closed status. */
-
-func chanrecv2(c *chan, val *byte) (received bool) {
- uintptr_t element_size = c == nil ? 0 : c->element_type->__size;
- if (element_size > 8) {
- return __go_receive_big(c, val, 0);
- } else {
- union {
- char b[8];
- uint64_t v;
- } u;
-
- u.v = __go_receive_small_closed(c, 0, &received);
-#ifndef WORDS_BIGENDIAN
- __builtin_memcpy(val, u.b, element_size);
-#else
- __builtin_memcpy(val, u.b + 8 - element_size, element_size);
-#endif
- return received;
- }
-}
-
-/* Do a channel receive with closed status for a select statement. */
-
-func chanrecv3(c *chan, val *byte) (received bool) {
- uintptr_t element_size = c->element_type->__size;
- if (element_size > 8) {
- return __go_receive_big(c, val, 1);
- } else {
- union {
- char b[8];
- uint64_t v;
- } u;
-
- u.v = __go_receive_small_closed(c, 1, &received);
-#ifndef WORDS_BIGENDIAN
- __builtin_memcpy(val, u.b, element_size);
-#else
- __builtin_memcpy(val, u.b + 8 - element_size, element_size);
-#endif
- return received;
- }
-}
diff --git a/libgo/runtime/channel.h b/libgo/runtime/channel.h
deleted file mode 100644
index 9176c68f692..00000000000
--- a/libgo/runtime/channel.h
+++ /dev/null
@@ -1,152 +0,0 @@
-/* channel.h -- the channel type for Go.
-
- Copyright 2009 The Go Authors. All rights reserved.
- Use of this source code is governed by a BSD-style
- license that can be found in the LICENSE file. */
-
-#include <stdint.h>
-#include <pthread.h>
-
-#include "go-type.h"
-
-/* This structure is used when a select is waiting for a synchronous
- channel. */
-
-struct __go_channel_select
-{
- /* A pointer to the next select waiting for this channel. */
- struct __go_channel_select *next;
- /* A pointer to the channel which this select will use. This starts
- out as NULL and is set to the first channel which synchs up with
- this one. This variable to which this points may only be
- accessed when __go_select_data_mutex is held. */
- struct __go_channel **selected;
- /* A pointer to a variable which must be set to true if the
- goroutine which sets *SELECTED wants to read from the channel,
- false if it wants to write to it. */
- _Bool *is_read;
-};
-
-/* A channel is a pointer to this structure. */
-
-struct __go_channel
-{
- /* A mutex to control access to the channel. */
- pthread_mutex_t lock;
- /* A condition variable. This is signalled when data is added to
- the channel and when data is removed from the channel. */
- pthread_cond_t cond;
- /* The type of elements on this channel. */
- const struct __go_type_descriptor *element_type;
- /* True if a goroutine is waiting to send on a synchronous
- channel. */
- _Bool waiting_to_send;
- /* True if a goroutine is waiting to receive on a synchronous
- channel. */
- _Bool waiting_to_receive;
- /* True if this channel was selected for send in a select statement.
- This looks out all other sends. */
- _Bool selected_for_send;
- /* True if this channel was selected for receive in a select
- statement. This locks out all other receives. */
- _Bool selected_for_receive;
- /* True if this channel has been closed. */
- _Bool is_closed;
- /* The list of select statements waiting to send on a synchronous
- channel. */
- struct __go_channel_select *select_send_queue;
- /* The list of select statements waiting to receive on a synchronous
- channel. */
- struct __go_channel_select *select_receive_queue;
- /* If a select statement is waiting for this channel, it sets these
- pointers. When something happens on the channel, the channel
- locks the mutex, signals the condition, and unlocks the
- mutex. */
- pthread_mutex_t *select_mutex;
- pthread_cond_t *select_cond;
- /* The number of entries in the circular buffer. */
- unsigned int num_entries;
- /* Where to store the next value. */
- unsigned int next_store;
- /* Where to fetch the next value. If next_fetch == next_store, the
- buffer is empty. If next_store + 1 == next_fetch, the buffer is
- full. */
- unsigned int next_fetch;
- /* The circular buffer. */
- uint64_t data[];
-};
-
-/* Try to link up with the structure generated by the frontend. */
-typedef struct __go_channel __go_channel;
-
-/* The mutex used to control access to the value pointed to by the
- __go_channel_select selected field. No additional mutexes may be
- acquired while this mutex is held. */
-extern pthread_mutex_t __go_select_data_mutex;
-
-extern struct __go_channel *
-__go_new_channel (const struct __go_type_descriptor *, uintptr_t);
-
-extern _Bool __go_synch_with_select (struct __go_channel *, _Bool);
-
-extern void __go_broadcast_to_select (struct __go_channel *);
-
-extern void __go_send_acquire (struct __go_channel *, _Bool);
-
-extern _Bool __go_send_nonblocking_acquire (struct __go_channel *);
-
-extern void __go_send_release (struct __go_channel *);
-
-extern void __go_send_small (struct __go_channel *, uint64_t, _Bool);
-
-extern _Bool __go_send_nonblocking_small (struct __go_channel *, uint64_t);
-
-extern void __go_send_big (struct __go_channel *, const void *, _Bool);
-
-extern _Bool __go_send_nonblocking_big (struct __go_channel *, const void *);
-
-extern _Bool __go_receive_acquire (struct __go_channel *, _Bool);
-
-#define RECEIVE_NONBLOCKING_ACQUIRE_DATA 0
-#define RECEIVE_NONBLOCKING_ACQUIRE_NODATA 1
-#define RECEIVE_NONBLOCKING_ACQUIRE_CLOSED 2
-
-extern int __go_receive_nonblocking_acquire (struct __go_channel *);
-
-extern uint64_t __go_receive_small (struct __go_channel *, _Bool);
-
-extern uint64_t __go_receive_small_closed (struct __go_channel *, _Bool,
- _Bool *);
-
-extern void __go_receive_release (struct __go_channel *);
-
-struct __go_receive_nonblocking_small
-{
- /* Value read from channel, or 0. */
- uint64_t __val;
- /* True if value was read from channel. */
- _Bool __success;
- /* True if channel is closed. */
- _Bool __closed;
-};
-
-extern struct __go_receive_nonblocking_small
-__go_receive_nonblocking_small (struct __go_channel *);
-
-extern _Bool __go_receive_big (struct __go_channel *, void *, _Bool);
-
-extern _Bool __go_receive_nonblocking_big (struct __go_channel *, void *,
- _Bool *);
-
-extern void __go_unlock_and_notify_selects (struct __go_channel *);
-
-extern _Bool __go_builtin_closed (struct __go_channel *);
-
-extern void __go_builtin_close (struct __go_channel *);
-
-extern int __go_chan_len (struct __go_channel *);
-
-extern int __go_chan_cap (struct __go_channel *);
-
-extern uintptr_t __go_select (uintptr_t, _Bool, struct __go_channel **,
- _Bool *);
diff --git a/libgo/runtime/go-chan-cap.c b/libgo/runtime/go-chan-cap.c
deleted file mode 100644
index 2c7958dd9fc..00000000000
--- a/libgo/runtime/go-chan-cap.c
+++ /dev/null
@@ -1,41 +0,0 @@
-/* go-chan-cap.c -- the cap function applied to a channel.
-
- Copyright 2009 The Go Authors. All rights reserved.
- Use of this source code is governed by a BSD-style
- license that can be found in the LICENSE file. */
-
-#include <stddef.h>
-
-#include "go-assert.h"
-#include "channel.h"
-
-/* Return the cap function applied to a channel--the size of the
- buffer. This could be done inline but I'm doing it as a function
- for now to make it easy to change the channel structure. */
-
-int
-__go_chan_cap (struct __go_channel *channel)
-{
- int i;
- int ret;
-
- if (channel == NULL)
- return 0;
-
- i = pthread_mutex_lock (&channel->lock);
- __go_assert (i == 0);
-
- if (channel->num_entries == 0)
- ret = 0;
- else
- {
- /* One slot is always unused. We added 1 when we created the
- channel. */
- ret = channel->num_entries - 1;
- }
-
- i = pthread_mutex_unlock (&channel->lock);
- __go_assert (i == 0);
-
- return ret;
-}
diff --git a/libgo/runtime/go-chan-len.c b/libgo/runtime/go-chan-len.c
deleted file mode 100644
index b3ced98aa05..00000000000
--- a/libgo/runtime/go-chan-len.c
+++ /dev/null
@@ -1,41 +0,0 @@
-/* go-chan-len.c -- the len function applied to a channel.
-
- Copyright 2009 The Go Authors. All rights reserved.
- Use of this source code is governed by a BSD-style
- license that can be found in the LICENSE file. */
-
-#include <stddef.h>
-
-#include "go-assert.h"
-#include "channel.h"
-
-/* Return the len function applied to a channel--the number of
- elements in the buffer. This could be done inline but I'm doing it
- as a function for now to make it easy to change the channel
- structure. */
-
-int
-__go_chan_len (struct __go_channel *channel)
-{
- int i;
- int ret;
-
- if (channel == NULL)
- return 0;
-
- i = pthread_mutex_lock (&channel->lock);
- __go_assert (i == 0);
-
- if (channel->num_entries == 0)
- ret = 0;
- else if (channel->next_fetch == channel->next_store)
- ret = 0;
- else
- ret = ((channel->next_store + channel->num_entries - channel->next_fetch)
- % channel->num_entries);
-
- i = pthread_mutex_unlock (&channel->lock);
- __go_assert (i == 0);
-
- return ret;
-}
diff --git a/libgo/runtime/go-close.c b/libgo/runtime/go-close.c
deleted file mode 100644
index 7e32286dae0..00000000000
--- a/libgo/runtime/go-close.c
+++ /dev/null
@@ -1,42 +0,0 @@
-/* go-close.c -- the builtin close function.
-
- Copyright 2009 The Go Authors. All rights reserved.
- Use of this source code is governed by a BSD-style
- license that can be found in the LICENSE file. */
-
-#include "runtime.h"
-#include "go-assert.h"
-#include "go-panic.h"
-#include "channel.h"
-
-/* Close a channel. After a channel is closed, sends are no longer
- permitted. Receives always return zero. */
-
-void
-__go_builtin_close (struct __go_channel *channel)
-{
- int i;
-
- if (channel == NULL)
- runtime_panicstring ("close of nil channel");
-
- i = pthread_mutex_lock (&channel->lock);
- __go_assert (i == 0);
-
- while (channel->selected_for_send)
- runtime_cond_wait (&channel->cond, &channel->lock);
-
- if (channel->is_closed)
- {
- i = pthread_mutex_unlock (&channel->lock);
- __go_assert (i == 0);
- runtime_panicstring ("close of closed channel");
- }
-
- channel->is_closed = 1;
-
- i = pthread_cond_broadcast (&channel->cond);
- __go_assert (i == 0);
-
- __go_unlock_and_notify_selects (channel);
-}
diff --git a/libgo/runtime/go-new-channel.c b/libgo/runtime/go-new-channel.c
deleted file mode 100644
index fe13c5efab6..00000000000
--- a/libgo/runtime/go-new-channel.c
+++ /dev/null
@@ -1,70 +0,0 @@
-/* go-new-channel.c -- allocate a new channel.
-
- Copyright 2009 The Go Authors. All rights reserved.
- Use of this source code is governed by a BSD-style
- license that can be found in the LICENSE file. */
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include "runtime.h"
-#include "go-alloc.h"
-#include "go-assert.h"
-#include "channel.h"
-
-struct __go_channel*
-__go_new_channel (const struct __go_type_descriptor *channel_type,
- uintptr_t entries)
-{
- const struct __go_channel_type *ctd;
- const struct __go_type_descriptor *element_type;
- uintptr_t element_size;
- int ientries;
- struct __go_channel* ret;
- size_t alloc_size;
- int i;
-
- __go_assert (channel_type->__code == GO_CHAN);
- ctd = (const struct __go_channel_type *) channel_type;
- element_type = ctd->__element_type;
-
- element_size = element_type->__size;
-
- ientries = (int) entries;
- if (ientries < 0
- || (uintptr_t) ientries != entries
- || (element_size > 0 && entries > (uintptr_t) -1 / element_size))
- runtime_panicstring ("chan size out of range");
-
- alloc_size = (element_size + sizeof (uint64_t) - 1) / sizeof (uint64_t);
-
- /* We use a circular buffer which means that when next_fetch ==
- next_store we don't know whether the buffer is empty or full. So
- we allocate an extra space, and always leave a space open.
- FIXME. */
- if (entries != 0)
- ++entries;
-
- ret = (struct __go_channel*) __go_alloc (sizeof (struct __go_channel)
- + ((entries == 0 ? 1 : entries)
- * alloc_size
- * sizeof (uint64_t)));
- i = pthread_mutex_init (&ret->lock, NULL);
- __go_assert (i == 0);
- i = pthread_cond_init (&ret->cond, NULL);
- __go_assert (i == 0);
- ret->element_type = element_type;
- ret->waiting_to_send = 0;
- ret->waiting_to_receive = 0;
- ret->selected_for_send = 0;
- ret->selected_for_receive = 0;
- ret->is_closed = 0;
- ret->select_send_queue = NULL;
- ret->select_receive_queue = NULL;
- ret->select_mutex = NULL;
- ret->select_cond = NULL;
- ret->num_entries = entries;
- ret->next_store = 0;
- ret->next_fetch = 0;
- return ret;
-}
diff --git a/libgo/runtime/go-rec-big.c b/libgo/runtime/go-rec-big.c
deleted file mode 100644
index d45e90af476..00000000000
--- a/libgo/runtime/go-rec-big.c
+++ /dev/null
@@ -1,43 +0,0 @@
-/* go-rec-big.c -- receive something larger than 64 bits on a channel.
-
- Copyright 2009 The Go Authors. All rights reserved.
- Use of this source code is governed by a BSD-style
- license that can be found in the LICENSE file. */
-
-#include <stdint.h>
-
-#include "go-panic.h"
-#include "channel.h"
-
-/* Returns true if a value was received, false if the channel is
- closed. */
-
-_Bool
-__go_receive_big (struct __go_channel *channel, void *val, _Bool for_select)
-{
- uintptr_t element_size;
- size_t alloc_size;
- size_t offset;
-
- if (channel == NULL)
- {
- /* Block forever. */
- __go_select (0, 0, NULL, NULL);
- }
-
- element_size = channel->element_type->__size;
- alloc_size = (element_size + sizeof (uint64_t) - 1) / sizeof (uint64_t);
-
- if (!__go_receive_acquire (channel, for_select))
- {
- __builtin_memset (val, 0, element_size);
- return 0;
- }
-
- offset = channel->next_fetch * alloc_size;
- __builtin_memcpy (val, &channel->data[offset], element_size);
-
- __go_receive_release (channel);
-
- return 1;
-}
diff --git a/libgo/runtime/go-rec-nb-big.c b/libgo/runtime/go-rec-nb-big.c
deleted file mode 100644
index 659ea1dc33d..00000000000
--- a/libgo/runtime/go-rec-nb-big.c
+++ /dev/null
@@ -1,46 +0,0 @@
-/* go-rec-nb-big.c -- nonblocking receive of something big on a channel.
-
- Copyright 2009 The Go Authors. All rights reserved.
- Use of this source code is governed by a BSD-style
- license that can be found in the LICENSE file. */
-
-#include <stdint.h>
-
-#include "channel.h"
-
-/* Return true if a value was received, false if not. */
-
-_Bool
-__go_receive_nonblocking_big (struct __go_channel* channel, void *val,
- _Bool *closed)
-{
- uintptr_t element_size;
- size_t alloc_size;
- size_t offset;
-
- if (channel == NULL)
- {
- if (closed != NULL)
- *closed = 0;
- return 0;
- }
-
- element_size = channel->element_type->__size;
- alloc_size = (element_size + sizeof (uint64_t) - 1) / sizeof (uint64_t);
-
- int data = __go_receive_nonblocking_acquire (channel);
- if (data != RECEIVE_NONBLOCKING_ACQUIRE_DATA)
- {
- __builtin_memset (val, 0, element_size);
- if (closed != NULL)
- *closed = data == RECEIVE_NONBLOCKING_ACQUIRE_CLOSED;
- return 0;
- }
-
- offset = channel->next_fetch * alloc_size;
- __builtin_memcpy (val, &channel->data[offset], element_size);
-
- __go_receive_release (channel);
-
- return 1;
-}
diff --git a/libgo/runtime/go-rec-nb-small.c b/libgo/runtime/go-rec-nb-small.c
deleted file mode 100644
index c21878ce131..00000000000
--- a/libgo/runtime/go-rec-nb-small.c
+++ /dev/null
@@ -1,123 +0,0 @@
-/* go-rec-nb-small.c -- nonblocking receive of something smal on a channel.
-
- Copyright 2009 The Go Authors. All rights reserved.
- Use of this source code is governed by a BSD-style
- license that can be found in the LICENSE file. */
-
-#include <stdint.h>
-
-#include "runtime.h"
-#include "go-assert.h"
-#include "go-panic.h"
-#include "channel.h"
-
-/* Prepare to receive something on a nonblocking channel. */
-
-int
-__go_receive_nonblocking_acquire (struct __go_channel *channel)
-{
- int i;
- _Bool has_data;
-
- i = pthread_mutex_lock (&channel->lock);
- __go_assert (i == 0);
-
- while (channel->selected_for_receive)
- runtime_cond_wait (&channel->cond, &channel->lock);
-
- if (channel->is_closed
- && (channel->num_entries == 0
- ? channel->next_store == 0
- : channel->next_fetch == channel->next_store))
- {
- __go_unlock_and_notify_selects (channel);
- return RECEIVE_NONBLOCKING_ACQUIRE_CLOSED;
- }
-
- if (channel->num_entries > 0)
- has_data = channel->next_fetch != channel->next_store;
- else
- {
- if (channel->waiting_to_receive)
- {
- /* Some other goroutine is already waiting for data on this
- channel, so we can't pick it up. */
- has_data = 0;
- }
- else if (channel->next_store > 0)
- {
- /* There is data on the channel. */
- has_data = 1;
- }
- else if (__go_synch_with_select (channel, 0))
- {
- /* We synched up with a select sending data, so there will
- be data for us shortly. Tell the select to go, and then
- wait for the data. */
- __go_broadcast_to_select (channel);
-
- while (channel->next_store == 0)
- runtime_cond_wait (&channel->cond, &channel->lock);
-
- has_data = 1;
- }
- else
- {
- /* Otherwise there is no data. */
- has_data = 0;
- }
-
- if (has_data)
- {
- channel->waiting_to_receive = 1;
- __go_assert (channel->next_store == 1);
- }
- }
-
- if (!has_data)
- {
- i = pthread_mutex_unlock (&channel->lock);
- __go_assert (i == 0);
- return RECEIVE_NONBLOCKING_ACQUIRE_NODATA;
- }
-
- return RECEIVE_NONBLOCKING_ACQUIRE_DATA;
-}
-
-/* Receive something 64 bits or smaller on a nonblocking channel. */
-
-struct __go_receive_nonblocking_small
-__go_receive_nonblocking_small (struct __go_channel *channel)
-{
- uintptr_t element_size;
- struct __go_receive_nonblocking_small ret;
-
- if (channel == NULL)
- {
- ret.__val = 0;
- ret.__success = 0;
- ret.__closed = 0;
- return ret;
- }
-
- element_size = channel->element_type->__size;
- __go_assert (element_size <= sizeof (uint64_t));
-
- int data = __go_receive_nonblocking_acquire (channel);
- if (data != RECEIVE_NONBLOCKING_ACQUIRE_DATA)
- {
- ret.__val = 0;
- ret.__success = 0;
- ret.__closed = data == RECEIVE_NONBLOCKING_ACQUIRE_CLOSED;
- return ret;
- }
-
- ret.__val = channel->data[channel->next_fetch];
-
- __go_receive_release (channel);
-
- ret.__success = 1;
- ret.__closed = 0;
-
- return ret;
-}
diff --git a/libgo/runtime/go-rec-small.c b/libgo/runtime/go-rec-small.c
deleted file mode 100644
index f26dbcdd993..00000000000
--- a/libgo/runtime/go-rec-small.c
+++ /dev/null
@@ -1,304 +0,0 @@
-/* go-rec-small.c -- receive something smaller than 64 bits on a channel.
-
- Copyright 2009 The Go Authors. All rights reserved.
- Use of this source code is governed by a BSD-style
- license that can be found in the LICENSE file. */
-
-#include <stdint.h>
-
-#include "runtime.h"
-#include "go-assert.h"
-#include "go-panic.h"
-#include "channel.h"
-
-/* This mutex controls access to the selected field of struct
- __go_channel_select. While this mutex is held, no other mutexes
- may be acquired. */
-
-pthread_mutex_t __go_select_data_mutex = PTHREAD_MUTEX_INITIALIZER;
-
-/* Try to synchronize with a select waiting on a sychronized channel.
- This is used by a send or receive. The channel is locked. This
- returns true if it was able to synch. */
-
-_Bool
-__go_synch_with_select (struct __go_channel *channel, _Bool is_send)
-{
- struct __go_channel_select *p;
- int i;
-
- __go_assert (channel->num_entries == 0);
-
- i = pthread_mutex_lock (&__go_select_data_mutex);
- __go_assert (i == 0);
-
- for (p = (is_send
- ? channel->select_receive_queue
- : channel->select_send_queue);
- p != NULL;
- p = p->next)
- {
- if (*p->selected == NULL)
- {
- *p->selected = channel;
- *p->is_read = !is_send;
- if (is_send)
- channel->selected_for_receive = 1;
- else
- channel->selected_for_send = 1;
- break;
- }
- }
-
- i = pthread_mutex_unlock (&__go_select_data_mutex);
- __go_assert (i == 0);
-
- /* The caller is responsible for signalling the select condition
- variable so that the other select knows that something has
- changed. We can't signal it here because we can't acquire the
- select mutex while we hold a channel lock. */
-
- return p != NULL;
-}
-
-/* If we synch with a select, then we need to signal the select that
- something has changed. This requires grabbing the select mutex,
- which can only be done when the channel is unlocked. This routine
- does the signalling. It is called with the channel locked. It
- unlocks the channel, broadcasts the signal and relocks the
- channel. */
-
-void
-__go_broadcast_to_select (struct __go_channel *channel)
-{
- pthread_mutex_t *select_mutex;
- pthread_cond_t *select_cond;
- int i;
-
- select_mutex = channel->select_mutex;
- select_cond = channel->select_cond;
-
- i = pthread_mutex_unlock (&channel->lock);
- __go_assert (i == 0);
-
- __go_assert (select_mutex != NULL && select_cond != NULL);
-
- i = pthread_mutex_lock (select_mutex);
- __go_assert (i == 0);
-
- i = pthread_cond_broadcast (select_cond);
- __go_assert (i == 0);
-
- i = pthread_mutex_unlock (select_mutex);
- __go_assert (i == 0);
-
- i = pthread_mutex_lock (&channel->lock);
- __go_assert (i == 0);
-}
-
-/* Prepare to receive something on a channel. Return true if the
- channel is acquired (which implies that there is data available),
- false if it is closed. */
-
-_Bool
-__go_receive_acquire (struct __go_channel *channel, _Bool for_select)
-{
- int i;
- _Bool my_wait_lock;
- _Bool synched_with_select;
-
- my_wait_lock = 0;
- synched_with_select = 0;
-
- i = pthread_mutex_lock (&channel->lock);
- __go_assert (i == 0);
-
- while (1)
- {
- _Bool need_broadcast;
-
- need_broadcast = 0;
-
- /* Check whether the channel is closed. */
- if (channel->is_closed
- && (channel->num_entries == 0
- ? channel->next_store == 0
- : channel->next_fetch == channel->next_store))
- {
- channel->selected_for_receive = 0;
- __go_unlock_and_notify_selects (channel);
- return 0;
- }
-
- /* If somebody else has the channel locked for receiving, we
- have to wait. If FOR_SELECT is true, then we are the one
- with the lock. */
- if (!channel->selected_for_receive || for_select)
- {
- if (channel->num_entries == 0)
- {
- /* If somebody else is waiting to receive, we have to
- wait. */
- if (!channel->waiting_to_receive || my_wait_lock)
- {
- _Bool was_marked;
-
- /* Lock the channel so that we get to receive
- next. */
- was_marked = channel->waiting_to_receive;
- channel->waiting_to_receive = 1;
- my_wait_lock = 1;
-
- /* See if there is a value to receive. */
- if (channel->next_store > 0)
- return 1;
-
- /* If we haven't already done so, try to synch with
- a select waiting to send on this channel. If we
- have already synched with a select, we are just
- looping until the select eventually causes
- something to be sent. */
- if (!synched_with_select && !for_select)
- {
- if (__go_synch_with_select (channel, 0))
- {
- synched_with_select = 1;
- need_broadcast = 1;
- }
- }
-
- /* If we marked the channel as waiting, we need to
- signal, because something changed. It needs to
- be a broadcast since there might be other
- receivers waiting. */
- if (!was_marked)
- {
- i = pthread_cond_broadcast (&channel->cond);
- __go_assert (i == 0);
- }
- }
- }
- else
- {
- /* If there is a value on the channel, we are OK. */
- if (channel->next_fetch != channel->next_store)
- return 1;
- }
- }
-
- /* If we just synched with a select, then we need to signal the
- select condition variable. We can only do that if we unlock
- the channel. So we need to unlock, signal, lock, and go
- around the loop again without waiting. */
- if (need_broadcast)
- {
- __go_broadcast_to_select (channel);
- continue;
- }
-
- /* Wait for something to change, then loop around and try
- again. */
-
- runtime_cond_wait (&channel->cond, &channel->lock);
- }
-}
-
-/* Finished receiving something on a channel. */
-
-void
-__go_receive_release (struct __go_channel *channel)
-{
- int i;
-
- if (channel->num_entries != 0)
- channel->next_fetch = (channel->next_fetch + 1) % channel->num_entries;
- else
- {
- /* For a synchronous receiver, we tell the sender that we picked
- up the value by setting the next_store field back to 0.
- Using the mutexes should implement a memory barrier. */
- __go_assert (channel->next_store == 1);
- channel->next_store = 0;
-
- channel->waiting_to_receive = 0;
- }
-
- channel->selected_for_receive = 0;
-
- /* This is a broadcast to make sure that a synchronous sender sees
- it. */
- i = pthread_cond_broadcast (&channel->cond);
- __go_assert (i == 0);
-
- __go_unlock_and_notify_selects (channel);
-}
-
-/* Unlock a channel and notify any waiting selects that something
- happened. */
-
-void
-__go_unlock_and_notify_selects (struct __go_channel *channel)
-{
- pthread_mutex_t* select_mutex;
- pthread_cond_t* select_cond;
- int i;
-
- select_mutex = channel->select_mutex;
- select_cond = channel->select_cond;
-
- i = pthread_mutex_unlock (&channel->lock);
- __go_assert (i == 0);
-
- if (select_mutex != NULL)
- {
- i = pthread_mutex_lock (select_mutex);
- __go_assert (i == 0);
- i = pthread_cond_broadcast (select_cond);
- __go_assert (i == 0);
- i = pthread_mutex_unlock (select_mutex);
- __go_assert (i == 0);
- }
-}
-
-/* Receive something 64 bits or smaller on a channel. */
-
-uint64_t
-__go_receive_small_closed (struct __go_channel *channel, _Bool for_select,
- _Bool *received)
-{
- uintptr_t element_size;
- uint64_t ret;
-
- if (channel == NULL)
- {
- /* Block forever. */
- __go_select (0, 0, NULL, NULL);
- }
-
- element_size = channel->element_type->__size;
- __go_assert (element_size <= sizeof (uint64_t));
-
- if (!__go_receive_acquire (channel, for_select))
- {
- if (received != NULL)
- *received = 0;
- return 0;
- }
-
- ret = channel->data[channel->next_fetch];
-
- __go_receive_release (channel);
-
- if (received != NULL)
- *received = 1;
-
- return ret;
-}
-
-/* Called by the compiler. */
-
-uint64_t
-__go_receive_small (struct __go_channel *channel, _Bool for_select)
-{
- return __go_receive_small_closed (channel, for_select, NULL);
-}
diff --git a/libgo/runtime/go-reflect-chan.c b/libgo/runtime/go-reflect-chan.c
deleted file mode 100644
index 6f6693b6b54..00000000000
--- a/libgo/runtime/go-reflect-chan.c
+++ /dev/null
@@ -1,200 +0,0 @@
-/* go-reflect-chan.c -- channel reflection support for Go.
-
- Copyright 2009 The Go Authors. All rights reserved.
- Use of this source code is governed by a BSD-style
- license that can be found in the LICENSE file. */
-
-#include <stdlib.h>
-#include <stdint.h>
-
-#include "config.h"
-#include "go-alloc.h"
-#include "go-assert.h"
-#include "go-panic.h"
-#include "go-type.h"
-#include "channel.h"
-
-/* This file implements support for reflection on channels. These
- functions are called from reflect/value.go. */
-
-extern uintptr_t makechan (const struct __go_type_descriptor *, uint32_t)
- asm ("libgo_reflect.reflect.makechan");
-
-uintptr_t
-makechan (const struct __go_type_descriptor *typ, uint32_t size)
-{
- struct __go_channel *channel;
- void *ret;
-
- channel = __go_new_channel (typ, size);
-
- ret = __go_alloc (sizeof (void *));
- __builtin_memcpy (ret, &channel, sizeof (void *));
- return (uintptr_t) ret;
-}
-
-extern _Bool chansend (struct __go_channel_type *, uintptr_t, uintptr_t, _Bool)
- asm ("libgo_reflect.reflect.chansend");
-
-_Bool
-chansend (struct __go_channel_type *ct, uintptr_t ch, uintptr_t val_i,
- _Bool nb)
-{
- struct __go_channel *channel = (struct __go_channel *) ch;
- uintptr_t element_size;
- void *pv;
-
- __go_assert (ct->__common.__code == GO_CHAN);
-
- if (__go_is_pointer_type (ct->__element_type))
- pv = &val_i;
- else
- pv = (void *) val_i;
-
- element_size = ct->__element_type->__size;
- if (element_size <= sizeof (uint64_t))
- {
- union
- {
- char b[sizeof (uint64_t)];
- uint64_t v;
- } u;
-
- __builtin_memset (u.b, 0, sizeof (uint64_t));
-#ifndef WORDS_BIGENDIAN
- __builtin_memcpy (u.b, pv, element_size);
-#else
- __builtin_memcpy (u.b + sizeof (uint64_t) - element_size, pv,
- element_size);
-#endif
- if (nb)
- return __go_send_nonblocking_small (channel, u.v);
- else
- {
- __go_send_small (channel, u.v, 0);
- return 1;
- }
- }
- else
- {
- if (nb)
- return __go_send_nonblocking_big (channel, pv);
- else
- {
- __go_send_big (channel, pv, 0);
- return 1;
- }
- }
-}
-
-struct chanrecv_ret
-{
- uintptr_t val;
- _Bool selected;
- _Bool received;
-};
-
-extern struct chanrecv_ret chanrecv (struct __go_channel_type *, uintptr_t,
- _Bool)
- asm ("libgo_reflect.reflect.chanrecv");
-
-struct chanrecv_ret
-chanrecv (struct __go_channel_type *ct, uintptr_t ch, _Bool nb)
-{
- struct __go_channel *channel = (struct __go_channel *) ch;
- void *pv;
- uintptr_t element_size;
- struct chanrecv_ret ret;
-
- __go_assert (ct->__common.__code == GO_CHAN);
-
- element_size = ct->__element_type->__size;
-
- if (__go_is_pointer_type (ct->__element_type))
- pv = &ret.val;
- else
- {
- pv = __go_alloc (element_size);
- ret.val = (uintptr_t) pv;
- }
-
- if (element_size <= sizeof (uint64_t))
- {
- union
- {
- char b[sizeof (uint64_t)];
- uint64_t v;
- } u;
-
- if (!nb)
- {
- u.v = __go_receive_small_closed (channel, 0, &ret.received);
- ret.selected = 1;
- }
- else
- {
- struct __go_receive_nonblocking_small s;
-
- s = __go_receive_nonblocking_small (channel);
- ret.selected = s.__success || s.__closed;
- ret.received = s.__success;
- u.v = s.__val;
- }
-
-#ifndef WORDS_BIGENDIAN
- __builtin_memcpy (pv, u.b, element_size);
-#else
- __builtin_memcpy (pv, u.b + sizeof (uint64_t) - element_size,
- element_size);
-#endif
- }
- else
- {
- if (!nb)
- {
- ret.received = __go_receive_big (channel, pv, 0);
- ret.selected = 1;
- }
- else
- {
- _Bool got;
- _Bool closed;
-
- got = __go_receive_nonblocking_big (channel, pv, &closed);
- ret.selected = got || closed;
- ret.received = got;
- }
- }
-
- return ret;
-}
-
-extern void chanclose (uintptr_t) asm ("libgo_reflect.reflect.chanclose");
-
-void
-chanclose (uintptr_t ch)
-{
- struct __go_channel *channel = (struct __go_channel *) ch;
-
- __go_builtin_close (channel);
-}
-
-extern int32_t chanlen (uintptr_t) asm ("libgo_reflect.reflect.chanlen");
-
-int32_t
-chanlen (uintptr_t ch)
-{
- struct __go_channel *channel = (struct __go_channel *) ch;
-
- return (int32_t) __go_chan_len (channel);
-}
-
-extern int32_t chancap (uintptr_t) asm ("libgo_reflect.reflect.chancap");
-
-int32_t
-chancap (uintptr_t ch)
-{
- struct __go_channel *channel = (struct __go_channel *) ch;
-
- return (int32_t) __go_chan_cap (channel);
-}
diff --git a/libgo/runtime/go-select.c b/libgo/runtime/go-select.c
deleted file mode 100644
index 677c699b52c..00000000000
--- a/libgo/runtime/go-select.c
+++ /dev/null
@@ -1,758 +0,0 @@
-/* go-select.c -- implement select.
-
- Copyright 2009 The Go Authors. All rights reserved.
- Use of this source code is governed by a BSD-style
- license that can be found in the LICENSE file. */
-
-#include <pthread.h>
-#include <stdarg.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include "runtime.h"
-#include "config.h"
-#include "go-assert.h"
-#include "channel.h"
-
-/* __go_select builds an array of these structures. */
-
-struct select_channel
-{
- /* The channel being selected. */
- struct __go_channel* channel;
- /* If this channel is selected, the value to return. */
- uintptr_t retval;
- /* If this channel is a duplicate of one which appears earlier in
- the array, this is the array index of the earlier channel. This
- is -1UL if this is not a dup. */
- uintptr_t dup_index;
- /* An entry to put on the send or receive queue. */
- struct __go_channel_select queue_entry;
- /* True if selected for send. */
- _Bool is_send;
- /* True if channel is ready--it has data to receive or space to
- send. */
- _Bool is_ready;
-};
-
-/* This mutex controls access to __go_select_cond. This mutex may not
- be acquired if any channel locks are held. */
-
-static pthread_mutex_t __go_select_mutex = PTHREAD_MUTEX_INITIALIZER;
-
-/* When we have to wait for channels, we tell them to trigger this
- condition variable when they send or receive something. */
-
-static pthread_cond_t __go_select_cond = PTHREAD_COND_INITIALIZER;
-
-/* Sort the channels by address. This avoids deadlock when multiple
- selects are running on overlapping sets of channels. */
-
-static int
-channel_sort (const void *p1, const void *p2)
-{
- const struct select_channel *c1 = (const struct select_channel *) p1;
- const struct select_channel *c2 = (const struct select_channel *) p2;
-
- if ((uintptr_t) c1->channel < (uintptr_t) c2->channel)
- return -1;
- else if ((uintptr_t) c1->channel > (uintptr_t) c2->channel)
- return 1;
- else
- return 0;
-}
-
-/* Return whether there is an entry on QUEUE which can be used for a
- synchronous send or receive. */
-
-static _Bool
-is_queue_ready (struct __go_channel_select *queue)
-{
- int x;
-
- if (queue == NULL)
- return 0;
-
- x = pthread_mutex_lock (&__go_select_data_mutex);
- __go_assert (x == 0);
-
- while (queue != NULL)
- {
- if (*queue->selected == NULL)
- break;
- queue = queue->next;
- }
-
- x = pthread_mutex_unlock (&__go_select_data_mutex);
- __go_assert (x == 0);
-
- return queue != NULL;
-}
-
-/* Return whether CHAN is ready. If IS_SEND is true check whether it
- has space to send, otherwise check whether it has a value to
- receive. */
-
-static _Bool
-is_channel_ready (struct __go_channel* channel, _Bool is_send)
-{
- if (is_send)
- {
- if (channel->selected_for_send)
- return 0;
- if (channel->is_closed)
- return 1;
- if (channel->num_entries > 0)
- {
- /* An asynchronous channel is ready for sending if there is
- room in the buffer. */
- return ((channel->next_store + 1) % channel->num_entries
- != channel->next_fetch);
- }
- else
- {
- if (channel->waiting_to_send)
- {
- /* Some other goroutine is waiting to send on this
- channel, so we can't. */
- return 0;
- }
- if (channel->waiting_to_receive)
- {
- /* Some other goroutine is waiting to receive a value,
- so we can send one. */
- return 1;
- }
- if (is_queue_ready (channel->select_receive_queue))
- {
- /* There is a select statement waiting to synchronize
- with this one. */
- return 1;
- }
- return 0;
- }
- }
- else
- {
- if (channel->selected_for_receive)
- return 0;
- if (channel->is_closed)
- return 1;
- if (channel->num_entries > 0)
- {
- /* An asynchronous channel is ready for receiving if there
- is a value in the buffer. */
- return channel->next_fetch != channel->next_store;
- }
- else
- {
- if (channel->waiting_to_receive)
- {
- /* Some other goroutine is waiting to receive from this
- channel, so it is not ready for us to receive. */
- return 0;
- }
- if (channel->next_store > 0)
- {
- /* There is data on the channel. */
- return 1;
- }
- if (is_queue_ready (channel->select_send_queue))
- {
- /* There is a select statement waiting to synchronize
- with this one. */
- return 1;
- }
- return 0;
- }
- }
-}
-
-/* Mark a channel as selected. The channel is locked. IS_SELECTED is
- true if the channel was selected for us by another goroutine. We
- set *NEEDS_BROADCAST if we need to broadcast on the select
- condition variable. Return true if we got it. */
-
-static _Bool
-mark_channel_selected (struct __go_channel *channel, _Bool is_send,
- _Bool is_selected, _Bool *needs_broadcast)
-{
- if (channel->num_entries == 0)
- {
- /* This is a synchronous channel. If there is no goroutine
- currently waiting, but there is another select waiting, then
- we need to tell that select to use this channel. That may
- fail--there may be no other goroutines currently waiting--as
- a third goroutine may already have claimed the select. */
- if (!is_selected
- && !channel->is_closed
- && (is_send
- ? !channel->waiting_to_receive
- : channel->next_store == 0))
- {
- int x;
- struct __go_channel_select *queue;
-
- x = pthread_mutex_lock (&__go_select_data_mutex);
- __go_assert (x == 0);
-
- queue = (is_send
- ? channel->select_receive_queue
- : channel->select_send_queue);
- __go_assert (queue != NULL);
-
- while (queue != NULL)
- {
- if (*queue->selected == NULL)
- {
- *queue->selected = channel;
- *queue->is_read = !is_send;
- break;
- }
- queue = queue->next;
- }
-
- x = pthread_mutex_unlock (&__go_select_data_mutex);
- __go_assert (x == 0);
-
- if (queue == NULL)
- return 0;
-
- if (is_send)
- channel->selected_for_receive = 1;
- else
- channel->selected_for_send = 1;
-
- /* We are going to have to tell the other select that there
- is something to do. */
- *needs_broadcast = 1;
- }
- }
-
- if (is_send)
- channel->selected_for_send = 1;
- else
- channel->selected_for_receive = 1;
-
- return 1;
-}
-
-/* Mark a channel to indicate that a select is waiting. The channel
- is locked. */
-
-static void
-mark_select_waiting (struct select_channel *sc,
- struct __go_channel **selected_pointer,
- _Bool *selected_for_read_pointer)
-{
- struct __go_channel *channel = sc->channel;
- _Bool is_send = sc->is_send;
-
- if (channel->num_entries == 0)
- {
- struct __go_channel_select **pp;
-
- pp = (is_send
- ? &channel->select_send_queue
- : &channel->select_receive_queue);
-
- /* Add an entry to the queue of selects on this channel. */
- sc->queue_entry.next = *pp;
- sc->queue_entry.selected = selected_pointer;
- sc->queue_entry.is_read = selected_for_read_pointer;
-
- *pp = &sc->queue_entry;
- }
-
- channel->select_mutex = &__go_select_mutex;
- channel->select_cond = &__go_select_cond;
-
- /* We never actually clear the select_mutex and select_cond fields.
- In order to clear them safely, we would need to have some way of
- knowing when no select is waiting for the channel. Thus we
- introduce a bit of inefficiency for every channel that select
- needs to wait for. This is harmless other than the performance
- cost. */
-}
-
-/* Remove the entry for this select waiting on this channel. The
- channel is locked. We check both queues, because the channel may
- be selected for both reading and writing. */
-
-static void
-clear_select_waiting (struct select_channel *sc,
- struct __go_channel **selected_pointer)
-{
- struct __go_channel *channel = sc->channel;
-
- if (channel->num_entries == 0)
- {
- _Bool found;
- struct __go_channel_select **pp;
-
- found = 0;
-
- for (pp = &channel->select_send_queue; *pp != NULL; pp = &(*pp)->next)
- {
- if ((*pp)->selected == selected_pointer)
- {
- *pp = (*pp)->next;
- found = 1;
- break;
- }
- }
-
- for (pp = &channel->select_receive_queue; *pp != NULL; pp = &(*pp)->next)
- {
- if ((*pp)->selected == selected_pointer)
- {
- *pp = (*pp)->next;
- found = 1;
- break;
- }
- }
-
- __go_assert (found);
- }
-}
-
-/* Look through the list of channels to see which ones are ready.
- Lock each channels, and set the is_ready flag. Return the number
- of ready channels. */
-
-static uintptr_t
-lock_channels_find_ready (struct select_channel *channels, uintptr_t count)
-{
- uintptr_t ready_count;
- uintptr_t i;
-
- ready_count = 0;
- for (i = 0; i < count; ++i)
- {
- struct __go_channel *channel = channels[i].channel;
- _Bool is_send = channels[i].is_send;
- uintptr_t dup_index = channels[i].dup_index;
- int x;
-
- if (channel == NULL)
- continue;
-
- if (dup_index != (uintptr_t) -1UL)
- {
- if (channels[dup_index].is_ready)
- {
- channels[i].is_ready = 1;
- ++ready_count;
- }
- continue;
- }
-
- x = pthread_mutex_lock (&channel->lock);
- __go_assert (x == 0);
-
- if (is_channel_ready (channel, is_send))
- {
- channels[i].is_ready = 1;
- ++ready_count;
- }
- }
-
- return ready_count;
-}
-
-/* The channel we are going to select has been forced by some other
- goroutine. SELECTED_CHANNEL is the channel we will use,
- SELECTED_FOR_READ is whether the other goroutine wants to read from
- the channel. Note that the channel could be specified multiple
- times in this select, so we must mark each appropriate entry for
- this channel as ready. Every other channel is marked as not ready.
- All the channels are locked before this routine is called. This
- returns the number of ready channels. */
-
-uintptr_t
-force_selected_channel_ready (struct select_channel *channels, uintptr_t count,
- struct __go_channel *selected_channel,
- _Bool selected_for_read)
-{
- uintptr_t ready_count;
- uintptr_t i;
-
- ready_count = 0;
- for (i = 0; i < count; ++i)
- {
- struct __go_channel *channel = channels[i].channel;
- _Bool is_send = channels[i].is_send;
-
- if (channel == NULL)
- continue;
-
- if (channel != selected_channel
- || (is_send ? !selected_for_read : selected_for_read))
- channels[i].is_ready = 0;
- else
- {
- channels[i].is_ready = 1;
- ++ready_count;
- }
- }
- __go_assert (ready_count > 0);
- return ready_count;
-}
-
-/* Unlock all the channels. */
-
-static void
-unlock_channels (struct select_channel *channels, uintptr_t count)
-{
- uintptr_t i;
- int x;
-
- for (i = 0; i < count; ++i)
- {
- struct __go_channel *channel = channels[i].channel;
-
- if (channel == NULL)
- continue;
-
- if (channels[i].dup_index != (uintptr_t) -1UL)
- continue;
-
- x = pthread_mutex_unlock (&channel->lock);
- __go_assert (x == 0);
- }
-}
-
-/* At least one channel is ready. Randomly pick a channel to return.
- Unlock all the channels. IS_SELECTED is true if the channel was
- picked for us by some other goroutine. If SELECTED_POINTER is not
- NULL, remove it from the queue for all the channels. Return the
- retval field of the selected channel. This will return 0 if we
- can't use the selected channel, because it relied on synchronizing
- with some other select, and that select already synchronized with a
- different channel. */
-
-static uintptr_t
-unlock_channels_and_select (struct select_channel *channels,
- uintptr_t count, uintptr_t ready_count,
- _Bool is_selected,
- struct __go_channel **selected_pointer)
-{
- uintptr_t selected;
- uintptr_t ret;
- _Bool needs_broadcast;
- uintptr_t i;
- int x;
-
- /* Pick which channel we are going to return. */
-#if defined(HAVE_RANDOM)
- selected = (uintptr_t) random () % ready_count;
-#else
- selected = (uintptr_t) rand () % ready_count;
-#endif
- ret = 0;
- needs_broadcast = 0;
-
- /* Look at the channels in reverse order so that we don't unlock a
- duplicated channel until we have seen all its dups. */
- for (i = 0; i < count; ++i)
- {
- uintptr_t j = count - i - 1;
- struct __go_channel *channel = channels[j].channel;
- _Bool is_send = channels[j].is_send;
-
- if (channel == NULL)
- continue;
-
- if (channels[j].is_ready)
- {
- if (selected == 0)
- {
- if (mark_channel_selected (channel, is_send, is_selected,
- &needs_broadcast))
- ret = channels[j].retval;
- }
-
- --selected;
- }
-
- if (channels[j].dup_index == (uintptr_t) -1UL)
- {
- if (selected_pointer != NULL)
- clear_select_waiting (&channels[j], selected_pointer);
-
- x = pthread_mutex_unlock (&channel->lock);
- __go_assert (x == 0);
- }
- }
-
- /* The NEEDS_BROADCAST variable is set if we are synchronizing with
- some other select statement. We can't do the actual broadcast
- until we have unlocked all the channels. */
-
- if (needs_broadcast)
- {
- x = pthread_mutex_lock (&__go_select_mutex);
- __go_assert (x == 0);
-
- x = pthread_cond_broadcast (&__go_select_cond);
- __go_assert (x == 0);
-
- x = pthread_mutex_unlock (&__go_select_mutex);
- __go_assert (x == 0);
- }
-
- return ret;
-}
-
-/* Mark all channels to show that we are waiting for them. This is
- called with the select mutex held, but none of the channels are
- locked. This returns true if some channel was found to be
- ready. */
-
-static _Bool
-mark_all_channels_waiting (struct select_channel* channels, uintptr_t count,
- struct __go_channel **selected_pointer,
- _Bool *selected_for_read_pointer)
-{
- _Bool ret;
- int x;
- uintptr_t i;
-
- ret = 0;
- for (i = 0; i < count; ++i)
- {
- struct __go_channel *channel = channels[i].channel;
- _Bool is_send = channels[i].is_send;
-
- if (channel == NULL)
- continue;
-
- if (channels[i].dup_index != (uintptr_t) -1UL)
- {
- uintptr_t j;
-
- /* A channel may be selected for both read and write. */
- if (channels[channels[i].dup_index].is_send == is_send)
- continue;
- else
- {
- for (j = channels[i].dup_index + 1; j < i; ++j)
- {
- if (channels[j].channel == channel
- && channels[j].is_send == is_send)
- break;
- }
- if (j < i)
- continue;
- }
- }
-
- x = pthread_mutex_lock (&channel->lock);
- __go_assert (x == 0);
-
- /* To avoid a race condition, we have to check again whether the
- channel is ready. It may have become ready since we did the
- first set of checks but before we acquired the select mutex.
- If we don't check here, we could sleep forever on the select
- condition variable. */
- if (is_channel_ready (channel, is_send))
- ret = 1;
-
- /* If SELECTED_POINTER is NULL, then we have already marked the
- channel as waiting. */
- if (selected_pointer != NULL)
- mark_select_waiting (&channels[i], selected_pointer,
- selected_for_read_pointer);
-
- x = pthread_mutex_unlock (&channel->lock);
- __go_assert (x == 0);
- }
-
- return ret;
-}
-
-/* Implement select. This is called by the compiler-generated code
- with pairs of arguments: a pointer to a channel, and an int which
- is non-zero for send, zero for receive. */
-
-uintptr_t
-__go_select (uintptr_t count, _Bool has_default,
- struct __go_channel **channel_args, _Bool *is_send_args)
-{
- struct select_channel stack_buffer[16];
- struct select_channel *allocated_buffer;
- struct select_channel *channels;
- uintptr_t i;
- int x;
- struct __go_channel *selected_channel;
- _Bool selected_for_read;
- _Bool is_queued;
-
- if (count < sizeof stack_buffer / sizeof stack_buffer[0])
- {
- channels = &stack_buffer[0];
- allocated_buffer = NULL;
- }
- else
- {
- allocated_buffer = ((struct select_channel *)
- malloc (count * sizeof (struct select_channel)));
- channels = allocated_buffer;
- }
-
- for (i = 0; i < count; ++i)
- {
- struct __go_channel *channel_arg = channel_args[i];
- _Bool is_send = is_send_args[i];
-
- channels[i].channel = (struct __go_channel*) channel_arg;
- channels[i].retval = i + 1;
- channels[i].dup_index = (uintptr_t) -1UL;
- channels[i].queue_entry.next = NULL;
- channels[i].queue_entry.selected = NULL;
- channels[i].is_send = is_send;
- channels[i].is_ready = 0;
- }
-
- qsort (channels, count, sizeof (struct select_channel), channel_sort);
-
- for (i = 0; i < count; ++i)
- {
- uintptr_t j;
-
- for (j = 0; j < i; ++j)
- {
- if (channels[j].channel == channels[i].channel)
- {
- channels[i].dup_index = j;
- break;
- }
- }
- }
-
- /* SELECT_CHANNEL is used to select synchronized channels. If no
- channels are ready, we store a pointer to this variable on the
- select queue for each synchronized channel. Because the variable
- may be set by channel operations running in other goroutines,
- SELECT_CHANNEL may only be accessed when all the channels are
- locked and/or when the select_data_mutex is locked. */
- selected_channel = NULL;
-
- /* SELECTED_FOR_READ is set to true if SELECTED_CHANNEL was set by a
- goroutine which wants to read from the channel. The access
- restrictions for this are like those for SELECTED_CHANNEL. */
- selected_for_read = 0;
-
- /* IS_QUEUED is true if we have queued up this select on the queues
- for any associated synchronous channels. We only do this if no
- channels are ready the first time around the loop. */
- is_queued = 0;
-
- while (1)
- {
- int ready_count;
- _Bool is_selected;
-
- /* Lock all channels, identify which ones are ready. */
- ready_count = lock_channels_find_ready (channels, count);
-
- /* All the channels are locked, so we can look at
- SELECTED_CHANNEL. If it is not NULL, then our choice has
- been forced by some other goroutine. This can only happen
- after the first time through the loop. */
- is_selected = selected_channel != NULL;
- if (is_selected)
- ready_count = force_selected_channel_ready (channels, count,
- selected_channel,
- selected_for_read);
-
- if (ready_count > 0)
- {
- uintptr_t ret;
-
- ret = unlock_channels_and_select (channels, count, ready_count,
- is_selected,
- (is_queued
- ? &selected_channel
- : NULL));
-
- /* If RET is zero, it means that the channel we picked
- turned out not to be ready, because some other select
- grabbed it during our traversal. Loop around and try
- again. */
- if (ret == 0)
- {
- is_queued = 0;
- /* We are no longer on any channel queues, so it is safe
- to touch SELECTED_CHANNEL here. It must be NULL,
- because otherwise that would somebody has promised to
- synch up with us and then failed to do so. */
- __go_assert (selected_channel == NULL);
- continue;
- }
-
- if (allocated_buffer != NULL)
- free (allocated_buffer);
-
- return ret;
- }
-
- /* No channels were ready. */
-
- unlock_channels (channels, count);
-
- if (has_default)
- {
- /* Use the default clause. */
- if (allocated_buffer != NULL)
- free (allocated_buffer);
- return 0;
- }
-
- /* This is a blocking select. Grab the select lock, tell all
- the channels to notify us when something happens, and wait
- for something to happen. */
-
- x = pthread_mutex_lock (&__go_select_mutex);
- __go_assert (x == 0);
-
- /* Check whether CHANNEL_SELECTED was set while the channels
- were unlocked. If it was set, then we can simply loop around
- again. We need to check this while the select mutex is held.
- It is possible that something will set CHANNEL_SELECTED while
- we mark the channels as waiting. If this happens, that
- goroutine is required to signal the select condition
- variable, which means acquiring the select mutex. Since we
- have the select mutex locked ourselves, we can not miss that
- signal. */
-
- x = pthread_mutex_lock (&__go_select_data_mutex);
- __go_assert (x == 0);
-
- is_selected = selected_channel != NULL;
-
- x = pthread_mutex_unlock (&__go_select_data_mutex);
- __go_assert (x == 0);
-
- if (!is_selected)
- {
- /* Mark the channels as waiting, and check whether they have
- become ready. */
- if (!mark_all_channels_waiting (channels, count,
- (is_queued
- ? NULL
- : &selected_channel),
- (is_queued
- ? NULL
- : &selected_for_read)))
- runtime_cond_wait (&__go_select_cond, &__go_select_mutex);
-
- is_queued = 1;
- }
-
- x = pthread_mutex_unlock (&__go_select_mutex);
- __go_assert (x == 0);
- }
-}
diff --git a/libgo/runtime/go-send-big.c b/libgo/runtime/go-send-big.c
deleted file mode 100644
index 61d4a0f13d9..00000000000
--- a/libgo/runtime/go-send-big.c
+++ /dev/null
@@ -1,34 +0,0 @@
-/* go-send-big.c -- send something bigger than uint64_t on a channel.
-
- Copyright 2009 The Go Authors. All rights reserved.
- Use of this source code is governed by a BSD-style
- license that can be found in the LICENSE file. */
-
-#include <stdint.h>
-
-#include "go-panic.h"
-#include "channel.h"
-
-void
-__go_send_big (struct __go_channel* channel, const void *val, _Bool for_select)
-{
- uintptr_t element_size;
- size_t alloc_size;
- size_t offset;
-
- if (channel == NULL)
- {
- // Block forever.
- __go_select (0, 0, NULL, NULL);
- }
-
- element_size = channel->element_type->__size;
- alloc_size = (element_size + sizeof (uint64_t) - 1) / sizeof (uint64_t);
-
- __go_send_acquire (channel, for_select);
-
- offset = channel->next_store * alloc_size;
- __builtin_memcpy (&channel->data[offset], val, element_size);
-
- __go_send_release (channel);
-}
diff --git a/libgo/runtime/go-send-nb-big.c b/libgo/runtime/go-send-nb-big.c
deleted file mode 100644
index e039874ef9a..00000000000
--- a/libgo/runtime/go-send-nb-big.c
+++ /dev/null
@@ -1,33 +0,0 @@
-/* go-send-nb-big.c -- nonblocking send of something big on a channel.
-
- Copyright 2009 The Go Authors. All rights reserved.
- Use of this source code is governed by a BSD-style
- license that can be found in the LICENSE file. */
-
-#include <stdint.h>
-
-#include "channel.h"
-
-_Bool
-__go_send_nonblocking_big (struct __go_channel* channel, const void *val)
-{
- uintptr_t element_size;
- size_t alloc_size;
- size_t offset;
-
- if (channel == NULL)
- return 0;
-
- element_size = channel->element_type->__size;
- alloc_size = (element_size + sizeof (uint64_t) - 1) / sizeof (uint64_t);
-
- if (!__go_send_nonblocking_acquire (channel))
- return 0;
-
- offset = channel->next_store * alloc_size;
- __builtin_memcpy (&channel->data[offset], val, element_size);
-
- __go_send_release (channel);
-
- return 1;
-}
diff --git a/libgo/runtime/go-send-nb-small.c b/libgo/runtime/go-send-nb-small.c
deleted file mode 100644
index c77ee9183e2..00000000000
--- a/libgo/runtime/go-send-nb-small.c
+++ /dev/null
@@ -1,107 +0,0 @@
-/* go-send-nb-small.c -- nonblocking send of something small on a channel.
-
- Copyright 2009 The Go Authors. All rights reserved.
- Use of this source code is governed by a BSD-style
- license that can be found in the LICENSE file. */
-
-#include <stdint.h>
-
-#include "runtime.h"
-#include "go-assert.h"
-#include "go-panic.h"
-#include "channel.h"
-
-/* Prepare to send something on a nonblocking channel. Return true if
- we acquired the channel, false if we did not acquire it because
- there is no space to send a value. */
-
-_Bool
-__go_send_nonblocking_acquire (struct __go_channel *channel)
-{
- int i;
- _Bool has_space;
-
- i = pthread_mutex_lock (&channel->lock);
- __go_assert (i == 0);
-
- while (channel->selected_for_send)
- runtime_cond_wait (&channel->cond, &channel->lock);
-
- if (channel->is_closed)
- {
- i = pthread_mutex_unlock (&channel->lock);
- __go_assert (i == 0);
- runtime_panicstring ("send on closed channel");
- }
-
- if (channel->num_entries > 0)
- has_space = ((channel->next_store + 1) % channel->num_entries
- != channel->next_fetch);
- else
- {
- /* This is a synchronous channel. If somebody is current
- sending, then we can't send. Otherwise, see if somebody is
- waiting to receive, or see if we can synch with a select. */
- if (channel->waiting_to_send)
- {
- /* Some other goroutine is currently sending on this
- channel, which means that we can't. */
- has_space = 0;
- }
- else if (channel->waiting_to_receive)
- {
- /* Some other goroutine is waiting to receive a value, so we
- can send directly to them. */
- has_space = 1;
- }
- else if (__go_synch_with_select (channel, 1))
- {
- /* We found a select waiting to receive data, so we can send
- to that. */
- __go_broadcast_to_select (channel);
- has_space = 1;
- }
- else
- {
- /* Otherwise, we can't send, because nobody is waiting to
- receive. */
- has_space = 0;
- }
-
- if (has_space)
- {
- channel->waiting_to_send = 1;
- __go_assert (channel->next_store == 0);
- }
- }
-
- if (!has_space)
- {
- i = pthread_mutex_unlock (&channel->lock);
- __go_assert (i == 0);
-
- return 0;
- }
-
- return 1;
-}
-
-/* Send something 64 bits or smaller on a channel. */
-
-_Bool
-__go_send_nonblocking_small (struct __go_channel *channel, uint64_t val)
-{
- if (channel == NULL)
- return 0;
-
- __go_assert (channel->element_type->__size <= sizeof (uint64_t));
-
- if (!__go_send_nonblocking_acquire (channel))
- return 0;
-
- channel->data[channel->next_store] = val;
-
- __go_send_release (channel);
-
- return 1;
-}
diff --git a/libgo/runtime/go-send-small.c b/libgo/runtime/go-send-small.c
deleted file mode 100644
index 06bcb41b9ad..00000000000
--- a/libgo/runtime/go-send-small.c
+++ /dev/null
@@ -1,159 +0,0 @@
-/* go-send-small.c -- send something 64 bits or smaller on a channel.
-
- Copyright 2009 The Go Authors. All rights reserved.
- Use of this source code is governed by a BSD-style
- license that can be found in the LICENSE file. */
-
-#include <stdint.h>
-
-#include "runtime.h"
-#include "go-assert.h"
-#include "go-panic.h"
-#include "channel.h"
-
-/* Prepare to send something on a channel. FOR_SELECT is true if this
- call is being made after a select statement returned with this
- channel selected. */
-
-void
-__go_send_acquire (struct __go_channel *channel, _Bool for_select)
-{
- int i;
-
- i = pthread_mutex_lock (&channel->lock);
- __go_assert (i == 0);
-
- while (1)
- {
- if (channel->is_closed)
- {
- if (for_select)
- channel->selected_for_send = 0;
- i = pthread_mutex_unlock (&channel->lock);
- __go_assert (i == 0);
- runtime_panicstring ("send on closed channel");
- }
-
- /* If somebody else has the channel locked for sending, we have
- to wait. If FOR_SELECT is true, then we are the one with the
- lock. */
- if (!channel->selected_for_send || for_select)
- {
- if (channel->num_entries == 0)
- {
- /* This is a synchronous channel. If nobody else is
- waiting to send, we grab the channel and tell the
- caller to send the data. We will then wait for a
- receiver. */
- if (!channel->waiting_to_send)
- {
- __go_assert (channel->next_store == 0);
- return;
- }
- }
- else
- {
- /* If there is room on the channel, we are OK. */
- if ((channel->next_store + 1) % channel->num_entries
- != channel->next_fetch)
- return;
- }
- }
-
- /* Wait for something to change, then loop around and try
- again. */
-
- runtime_cond_wait (&channel->cond, &channel->lock);
- }
-}
-
-/* Finished sending something on a channel. */
-
-void
-__go_send_release (struct __go_channel *channel)
-{
- int i;
-
- if (channel->num_entries != 0)
- {
- /* This is a buffered channel. Bump the store count and signal
- the condition variable. */
- channel->next_store = (channel->next_store + 1) % channel->num_entries;
-
- i = pthread_cond_signal (&channel->cond);
- __go_assert (i == 0);
- }
- else
- {
- _Bool synched_with_select;
-
- /* This is a synchronous channel. Indicate that we have a value
- waiting. */
- channel->next_store = 1;
- channel->waiting_to_send = 1;
-
- /* Tell everybody else to do something. This has to be a
- broadcast because we might have both senders and receivers
- waiting on the condition, but senders won't send another
- signal. */
- i = pthread_cond_broadcast (&channel->cond);
- __go_assert (i == 0);
-
- /* Wait until the value is received. */
- synched_with_select = 0;
- while (1)
- {
- if (channel->next_store == 0)
- break;
-
- /* If nobody is currently waiting to receive, try to synch
- up with a select. */
- if (!channel->waiting_to_receive && !synched_with_select)
- {
- if (__go_synch_with_select (channel, 1))
- {
- synched_with_select = 1;
- __go_broadcast_to_select (channel);
- continue;
- }
- }
-
- runtime_cond_wait (&channel->cond, &channel->lock);
- }
-
- channel->waiting_to_send = 0;
-
- /* Using the mutexes should implement a memory barrier. */
-
- /* We have to signal again since we cleared the waiting_to_send
- field. This has to be a broadcast because both senders and
- receivers might be waiting, but only senders will be able to
- act. */
- i = pthread_cond_broadcast (&channel->cond);
- __go_assert (i == 0);
- }
-
- channel->selected_for_send = 0;
-
- __go_unlock_and_notify_selects (channel);
-}
-
-/* Send something 64 bits or smaller on a channel. */
-
-void
-__go_send_small (struct __go_channel *channel, uint64_t val, _Bool for_select)
-{
- if (channel == NULL)
- {
- // Block forever.
- __go_select (0, 0, NULL, NULL);
- }
-
- __go_assert (channel->element_type->__size <= sizeof (uint64_t));
-
- __go_send_acquire (channel, for_select);
-
- channel->data[channel->next_store] = val;
-
- __go_send_release (channel);
-}
diff --git a/libgo/runtime/go-signal.c b/libgo/runtime/go-signal.c
index 958b421c871..cd165f45112 100644
--- 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);
diff --git a/libgo/runtime/runtime.h b/libgo/runtime/runtime.h
index 9455ae88c5a..e28bc82f8ab 100644
--- a/libgo/runtime/runtime.h
+++ b/libgo/runtime/runtime.h
@@ -55,14 +55,15 @@ typedef struct M M;
typedef union Note Note;
typedef struct MCache MCache;
typedef struct FixAlloc FixAlloc;
+typedef struct Hchan Hchan;
-typedef struct __go_defer_stack Defer;
+typedef struct __go_open_array Slice;
+typedef struct __go_string String;
typedef struct __go_interface Iface;
typedef struct __go_empty_interface Eface;
typedef struct __go_type_descriptor Type;
+typedef struct __go_defer_stack Defer;
typedef struct __go_panic_stack Panic;
-typedef struct __go_open_array Slice;
-typedef struct __go_string String;
typedef struct __go_func_type FuncType;
typedef struct __go_map_type MapType;
@@ -131,6 +132,7 @@ struct G
bool fromgogo; // reached from gogo
int16 status;
int32 goid;
+ uint32 selgen; // valid sudog pointer
const char* waitreason; // if status==Gwaiting
G* schedlink;
bool readyonstop;
@@ -335,6 +337,3 @@ void reflect_call(const struct __go_func_type *, const void *, _Bool, _Bool,
#ifdef __rtems__
void __wrap_rtems_task_variable_add(void **);
#endif
-
-/* Temporary. */
-void runtime_cond_wait(pthread_cond_t*, pthread_mutex_t*);
diff --git a/libgo/runtime/thread.c b/libgo/runtime/thread.c
index 459fc85c780..d43e224ffb2 100644
--- a/libgo/runtime/thread.c
+++ b/libgo/runtime/thread.c
@@ -90,27 +90,3 @@ runtime_minit(void)
if(sigaltstack(&ss, nil) < 0)
*(int *)0xf1 = 0xf1;
}
-
-// Temporary functions, which will be removed when we stop using
-// condition variables.
-
-void
-runtime_cond_wait(pthread_cond_t* cond, pthread_mutex_t* mutex)
-{
- int i;
-
- runtime_entersyscall();
-
- i = pthread_cond_wait(cond, mutex);
- if(i != 0)
- runtime_throw("pthread_cond_wait");
- i = pthread_mutex_unlock(mutex);
- if(i != 0)
- runtime_throw("pthread_mutex_unlock");
-
- runtime_exitsyscall();
-
- i = pthread_mutex_lock(mutex);
- if(i != 0)
- runtime_throw("pthread_mutex_lock");
-}