This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Go patch committed: Update Go library


This patch updates the Go library to the most recent weekly release.  I
think the only potential portability issues here are the use of the
ipv6_mreq struct.  I'm not entirely sure the new exp/terminal package is
portable, but it might be.

I have not included the entire patch here, because it is too large and
it's just copying changes anyhow.  I've included all patches to files
which are specific to the Go frontend version.

Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu.
Committed to mainline.

Ian

diff -r c36211271569 libgo/MERGE
--- a/libgo/MERGE	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/MERGE	Wed Oct 26 16:12:38 2011 -0700
@@ -1,4 +1,4 @@
-c1702f36df03
+6d7136d74b65
 
 The first line of this file holds the Mercurial revision number of the
 last merge done from the master library sources.
diff -r c36211271569 libgo/Makefile.am
--- a/libgo/Makefile.am	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/Makefile.am	Wed Oct 26 16:12:38 2011 -0700
@@ -107,7 +107,6 @@
 	cmath.gox \
 	crypto.gox \
 	csv.gox \
-	ebnf.gox \
 	exec.gox \
 	expvar.gox \
 	flag.gox \
@@ -124,7 +123,6 @@
 	mail.gox \
 	mime.gox \
 	net.gox \
-	netchan.gox \
 	os.gox \
 	patch.gox \
 	path.gox \
@@ -145,7 +143,6 @@
 	template.gox \
 	testing.gox \
 	time.gox \
-	try.gox \
 	unicode.gox \
 	url.gox \
 	utf16.gox \
@@ -173,13 +170,13 @@
 toolexeclibgocontainer_DATA = \
 	container/heap.gox \
 	container/list.gox \
-	container/ring.gox \
-	container/vector.gox
+	container/ring.gox
 
 toolexeclibgocryptodir = $(toolexeclibgodir)/crypto
 
 toolexeclibgocrypto_DATA = \
 	crypto/aes.gox \
+	crypto/bcrypt.gox \
 	crypto/blowfish.gox \
 	crypto/cast5.gox \
 	crypto/cipher.gox \
@@ -242,19 +239,24 @@
 toolexeclibgoexpdir = $(toolexeclibgodir)/exp
 
 toolexeclibgoexp_DATA = \
+	exp/ebnf.gox \
 	exp/gui.gox \
 	exp/norm.gox \
-	exp/regexp.gox
+	exp/spdy.gox \
+	exp/sql.gox \
+	exp/ssh.gox \
+	exp/terminal.gox \
+	exp/types.gox
 
 toolexeclibgoexpguidir = $(toolexeclibgoexpdir)/gui
 
 toolexeclibgoexpgui_DATA = \
 	exp/gui/x11.gox
 
-toolexeclibgoexpregexpdir = $(toolexeclibgoexpdir)/regexp
-
-toolexeclibgoexpregexp_DATA = \
-	exp/regexp/syntax.gox
+toolexeclibgoexpsqldir = $(toolexeclibgoexpdir)/sql
+
+toolexeclibgoexpsql_DATA = \
+	exp/sql/driver.gox
 
 toolexeclibgoexptemplatedir = $(toolexeclibgoexpdir)/template
 
@@ -270,9 +272,7 @@
 	go/parser.gox \
 	go/printer.gox \
 	go/scanner.gox \
-	go/token.gox \
-	go/typechecker.gox \
-	go/types.gox
+	go/token.gox
 
 toolexeclibgohashdir = $(toolexeclibgodir)/hash
 
@@ -288,13 +288,13 @@
 	http/cgi.gox \
 	http/fcgi.gox \
 	http/httptest.gox \
-	http/pprof.gox \
-	http/spdy.gox
+	http/pprof.gox
 
 toolexeclibgoimagedir = $(toolexeclibgodir)/image
 
 toolexeclibgoimage_DATA = \
 	image/bmp.gox \
+	image/color.gox \
 	image/draw.gox \
 	image/gif.gox \
 	image/jpeg.gox \
@@ -326,6 +326,8 @@
 toolexeclibgoolddir = $(toolexeclibgodir)/old
 
 toolexeclibgoold_DATA = \
+	old/netchan.gox \
+	old/regexp.gox \
 	old/template.gox
 
 toolexeclibgoosdir = $(toolexeclibgodir)/os
@@ -347,6 +349,11 @@
 toolexeclibgopath_DATA = \
 	path/filepath.gox
 
+toolexeclibgoregexpdir = $(toolexeclibgodir)/regexp
+
+toolexeclibgoregexp_DATA = \
+	regexp/syntax.gox
+
 toolexeclibgorpcdir = $(toolexeclibgodir)/rpc
 
 toolexeclibgorpc_DATA = \
@@ -479,6 +486,7 @@
 	runtime/msize.c \
 	runtime/proc.c \
 	runtime/thread.c \
+	runtime/yield.c \
 	$(rtems_task_variable_add_file) \
 	chan.c \
 	iface.c \
@@ -559,10 +567,6 @@
 	go/csv/reader.go \
 	go/csv/writer.go
 
-go_ebnf_files = \
-	go/ebnf/ebnf.go \
-	go/ebnf/parser.go
-
 go_exec_files = \
 	go/exec/exec.go \
 	go/exec/lp_unix.go
@@ -598,6 +602,7 @@
 	go/html/escape.go \
 	go/html/node.go \
 	go/html/parse.go \
+	go/html/render.go \
 	go/html/token.go
 
 go_http_files = \
@@ -605,6 +610,7 @@
 	go/http/client.go \
 	go/http/cookie.go \
 	go/http/dump.go \
+	go/http/filetransport.go \
 	go/http/fs.go \
 	go/http/header.go \
 	go/http/lex.go \
@@ -619,7 +625,6 @@
 	go/http/transport.go
 
 go_image_files = \
-	go/image/color.go \
 	go/image/format.go \
 	go/image/geom.go \
 	go/image/image.go \
@@ -642,6 +647,7 @@
 	go/log/log.go
 
 go_math_files = \
+	go/math/abs.go \
 	go/math/acosh.go \
 	go/math/asin.go \
 	go/math/asinh.go \
@@ -652,15 +658,13 @@
 	go/math/cbrt.go \
 	go/math/const.go \
 	go/math/copysign.go \
+	go/math/dim.go \
 	go/math/erf.go \
 	go/math/exp.go \
 	go/math/exp_port.go \
 	go/math/exp2.go \
 	go/math/expm1.go \
-	go/math/fabs.go \
-	go/math/fdim.go \
 	go/math/floor.go \
-	go/math/fmod.go \
 	go/math/frexp.go \
 	go/math/gamma.go \
 	go/math/hypot.go \
@@ -674,6 +678,7 @@
 	go/math/log1p.go \
 	go/math/log10.go \
 	go/math/logb.go \
+	go/math/mod.go \
 	go/math/modf.go \
 	go/math/nextafter.go \
 	go/math/pow.go \
@@ -777,11 +782,6 @@
 	go/net/unixsock.go \
 	go/net/unixsock_posix.go
 
-go_netchan_files = \
-	go/netchan/common.go \
-	go/netchan/export.go \
-	go/netchan/import.go
-
 if LIBGO_IS_SOLARIS
 if LIBGO_IS_386
 go_os_dir_file = go/os/dir_largefile.go
@@ -865,6 +865,7 @@
 	go/reflect/value.go
 
 go_regexp_files = \
+	go/regexp/exec.go \
 	go/regexp/regexp.go
 
 go_rpc_files = \
@@ -915,6 +916,7 @@
 
 go_strings_files = \
 	go/strings/reader.go \
+	go/strings/replace.go \
 	go/strings/strings.go
 
 go_sync_files = \
@@ -953,21 +955,19 @@
 
 go_testing_files = \
 	go/testing/benchmark.go \
+	go/testing/example.go \
 	go/testing/testing.go
 
 go_time_files = \
 	go/time/format.go \
 	go/time/sleep.go \
 	go/time/sys.go \
-	go/time/sys_posix.go \
+	go/time/sys_unix.go \
 	go/time/tick.go \
 	go/time/time.go \
 	go/time/zoneinfo_posix.go \
 	go/time/zoneinfo_unix.go
 
-go_try_files = \
-	go/try/try.go
-
 go_unicode_files = \
 	go/unicode/casetables.go \
 	go/unicode/digit.go \
@@ -987,6 +987,8 @@
 
 go_websocket_files = \
 	go/websocket/client.go \
+	go/websocket/hixie.go \
+	go/websocket/hybi.go \
 	go/websocket/server.go \
 	go/websocket/websocket.go
 
@@ -1041,16 +1043,13 @@
 go_container_ring_files = \
 	go/container/ring/ring.go
 
-go_container_vector_files = \
-	go/container/vector/defs.go \
-	go/container/vector/intvector.go \
-	go/container/vector/stringvector.go \
-	go/container/vector/vector.go
-
 go_crypto_aes_files = \
 	go/crypto/aes/block.go \
 	go/crypto/aes/cipher.go \
 	go/crypto/aes/const.go
+go_crypto_bcrypt_files = \
+	go/crypto/bcrypt/base64.go \
+	go/crypto/bcrypt/bcrypt.go
 go_crypto_blowfish_files = \
 	go/crypto/blowfish/block.go \
 	go/crypto/blowfish/const.go \
@@ -1123,11 +1122,13 @@
 	go/crypto/tls/handshake_server.go \
 	go/crypto/tls/key_agreement.go \
 	go/crypto/tls/prf.go \
+	go/crypto/tls/root_unix.go \
 	go/crypto/tls/tls.go
 go_crypto_twofish_files = \
 	go/crypto/twofish/twofish.go
 go_crypto_x509_files = \
 	go/crypto/x509/cert_pool.go \
+	go/crypto/x509/pkcs1.go \
 	go/crypto/x509/verify.go \
 	go/crypto/x509/x509.go
 go_crypto_xtea_files = \
@@ -1187,7 +1188,8 @@
 go_encoding_base64_files = \
 	go/encoding/base64/base64.go
 go_encoding_binary_files = \
-	go/encoding/binary/binary.go
+	go/encoding/binary/binary.go \
+	go/encoding/binary/varint.go
 go_encoding_git85_files = \
 	go/encoding/git85/git.go
 go_encoding_hex_files = \
@@ -1195,33 +1197,66 @@
 go_encoding_pem_files = \
 	go/encoding/pem/pem.go
 
+go_exp_ebnf_files = \
+	go/exp/ebnf/ebnf.go \
+	go/exp/ebnf/parser.go
 go_exp_gui_files = \
 	go/exp/gui/gui.go
 go_exp_norm_files = \
 	go/exp/norm/composition.go \
 	go/exp/norm/forminfo.go \
+	go/exp/norm/input.go \
 	go/exp/norm/normalize.go \
+	go/exp/norm/readwriter.go \
 	go/exp/norm/tables.go \
 	go/exp/norm/trie.go
-go_exp_regexp_files = \
-	go/exp/regexp/exec.go \
-	go/exp/regexp/regexp.go
+go_exp_spdy_files = \
+	go/exp/spdy/read.go \
+	go/exp/spdy/types.go \
+	go/exp/spdy/write.go
+go_exp_sql_files = \
+	go/exp/sql/convert.go \
+	go/exp/sql/sql.go
+go_exp_ssh_files = \
+	go/exp/ssh/channel.go \
+	go/exp/ssh/common.go \
+	go/exp/ssh/doc.go \
+	go/exp/ssh/messages.go \
+	go/exp/ssh/server.go \
+	go/exp/ssh/server_shell.go \
+	go/exp/ssh/transport.go
+go_exp_terminal_files = \
+	go/exp/terminal/shell.go \
+	go/exp/terminal/terminal.go
+go_exp_types_files = \
+	go/exp/types/check.go \
+	go/exp/types/const.go \
+	go/exp/types/exportdata.go \
+	go/exp/types/gcimporter.go \
+	go/exp/types/types.go \
+	go/exp/types/universe.go
 
 go_exp_gui_x11_files = \
 	go/exp/gui/x11/auth.go \
 	go/exp/gui/x11/conn.go
 
+go_exp_sql_driver_files = \
+	go/exp/sql/driver/driver.go \
+	go/exp/sql/driver/types.go
+
 go_exp_template_html_files = \
+	go/exp/template/html/attr.go \
+	go/exp/template/html/clone.go \
+	go/exp/template/html/content.go \
 	go/exp/template/html/context.go \
-	go/exp/template/html/escape.go
-
-go_exp_regexp_syntax_files = \
-	go/exp/regexp/syntax/compile.go \
-	go/exp/regexp/syntax/parse.go \
-	go/exp/regexp/syntax/perl_groups.go \
-	go/exp/regexp/syntax/prog.go \
-	go/exp/regexp/syntax/regexp.go \
-	go/exp/regexp/syntax/simplify.go
+	go/exp/template/html/css.go \
+	go/exp/template/html/doc.go \
+	go/exp/template/html/error.go \
+	go/exp/template/html/escape.go \
+	go/exp/template/html/html.go \
+	go/exp/template/html/js.go \
+	go/exp/template/html/transition.go \
+	go/exp/template/html/url.go
 
 go_go_ast_files = \
 	go/go/ast/ast.go \
@@ -1237,7 +1272,8 @@
 	syslist.go
 go_go_doc_files = \
 	go/go/doc/comment.go \
-	go/go/doc/doc.go
+	go/go/doc/doc.go \
+	go/go/doc/example.go
 go_go_parser_files = \
 	go/go/parser/interface.go \
 	go/go/parser/parser.go
@@ -1249,19 +1285,8 @@
 	go/go/scanner/scanner.go
 go_go_token_files = \
 	go/go/token/position.go \
+	go/go/token/serialize.go \
 	go/go/token/token.go
-go_go_typechecker_files = \
-	go/go/typechecker/scope.go \
-	go/go/typechecker/type.go \
-	go/go/typechecker/typechecker.go \
-	go/go/typechecker/universe.go
-go_go_types_files = \
-	go/go/types/check.go \
-	go/go/types/const.go \
-	go/go/types/exportdata.go \
-	go/go/types/gcimporter.go \
-	go/go/types/types.go \
-	go/go/types/universe.go
 
 go_hash_adler32_files = \
 	go/hash/adler32/adler32.go
@@ -1284,14 +1309,13 @@
 	go/http/httptest/server.go
 go_http_pprof_files = \
 	go/http/pprof/pprof.go
-go_http_spdy_files = \
-	go/http/spdy/read.go \
-	go/http/spdy/types.go \
-	go/http/spdy/write.go
 
 go_image_bmp_files = \
 	go/image/bmp/reader.go
 
+go_image_color_files = \
+	go/image/color/color.go
+
 go_image_draw_files = \
 	go/image/draw/draw.go
 
@@ -1311,6 +1335,7 @@
 
 go_image_tiff_files = \
 	go/image/tiff/buffer.go \
+	go/image/tiff/compress.go \
 	go/image/tiff/consts.go \
 	go/image/tiff/reader.go
 
@@ -1340,6 +1365,12 @@
 	go/net/textproto/textproto.go \
 	go/net/textproto/writer.go
 
+go_old_netchan_files = \
+	go/old/netchan/common.go \
+	go/old/netchan/export.go \
+	go/old/netchan/import.go
+go_old_regexp_files = \
+	go/old/regexp/regexp.go
 go_old_template_files = \
 	go/old/template/doc.go \
 	go/old/template/execute.go \
@@ -1361,6 +1392,14 @@
 	go/path/filepath/path.go \
 	go/path/filepath/path_unix.go
 
+go_regexp_syntax_files = \
+	go/regexp/syntax/compile.go \
+	go/regexp/syntax/parse.go \
+	go/regexp/syntax/perl_groups.go \
+	go/regexp/syntax/prog.go \
+	go/regexp/syntax/regexp.go \
+	go/regexp/syntax/simplify.go
+
 go_rpc_jsonrpc_files = \
 	go/rpc/jsonrpc/client.go \
 	go/rpc/jsonrpc/server.go
@@ -1559,7 +1598,6 @@
 	cmath/cmath.lo \
 	crypto/crypto.lo \
 	csv/csv.lo \
-	ebnf/ebnf.lo \
 	exec/exec.lo \
 	expvar/expvar.lo \
 	flag/flag.lo \
@@ -1576,7 +1614,6 @@
 	mail/mail.lo \
 	mime/mime.lo \
 	net/net.lo \
-	netchan/netchan.lo \
 	os/os.lo \
 	patch/patch.lo \
 	path/path.lo \
@@ -1596,7 +1633,6 @@
 	tabwriter/tabwriter.lo \
 	template/template.lo \
 	time/time.lo \
-	try/try.lo \
 	unicode/unicode.lo \
 	url/url.lo \
 	utf16/utf16.lo \
@@ -1613,8 +1649,8 @@
 	container/heap.lo \
 	container/list.lo \
 	container/ring.lo \
-	container/vector.lo \
 	crypto/aes.lo \
+	crypto/bcrypt.lo \
 	crypto/blowfish.lo \
 	crypto/cast5.lo \
 	crypto/cipher.lo \
@@ -1657,11 +1693,16 @@
 	encoding/git85.lo \
 	encoding/hex.lo \
 	encoding/pem.lo \
+	exp/ebnf.lo \
 	exp/gui.lo \
 	exp/norm.lo \
-	exp/regexp.lo \
+	exp/spdy.lo \
+	exp/sql.lo \
+	exp/ssh.lo \
+	exp/terminal.lo \
+	exp/types.lo \
 	exp/gui/x11.lo \
-	exp/regexp/syntax.lo \
+	exp/sql/driver.lo \
 	exp/template/html.lo \
 	go/ast.lo \
 	go/build.lo \
@@ -1670,8 +1711,6 @@
 	go/printer.lo \
 	go/scanner.lo \
 	go/token.lo \
-	go/typechecker.lo \
-	go/types.lo \
 	hash/adler32.lo \
 	hash/crc32.lo \
 	hash/crc64.lo \
@@ -1680,8 +1719,8 @@
 	http/fcgi.lo \
 	http/httptest.lo \
 	http/pprof.lo \
-	http/spdy.lo \
 	image/bmp.lo \
+	image/color.lo \
 	image/draw.lo \
 	image/gif.lo \
 	image/jpeg.lo \
@@ -1693,11 +1732,14 @@
 	mime/multipart.lo \
 	net/dict.lo \
 	net/textproto.lo \
+	old/netchan.lo \
+	old/regexp.lo \
 	old/template.lo \
 	$(os_lib_inotify_lo) \
 	os/user.lo \
 	os/signal.lo \
 	path/filepath.lo \
+	regexp/syntax.lo \
 	rpc/jsonrpc.lo \
 	runtime/debug.lo \
 	runtime/pprof.lo \
@@ -1853,13 +1895,6 @@
 	@$(CHECK)
 .PHONY: csv/check
 
-ebnf/ebnf.lo: $(go_ebnf_files) container/vector.gox go/scanner.gox \
-		go/token.gox os.gox strconv.gox unicode.gox utf8.gox
-	$(BUILDPACKAGE)
-ebnf/check: $(CHECK_DEPS)
-	@$(CHECK)
-.PHONY: ebnf/check
-
 exec/exec.lo: $(go_exec_files) bytes.gox io.gox os.gox strconv.gox \
 		strings.gox syscall.gox
 	$(BUILDPACKAGE)
@@ -1881,7 +1916,7 @@
 .PHONY: flag/check
 
 fmt/fmt.lo: $(go_fmt_files) bytes.gox io.gox math.gox os.gox reflect.gox \
-		strconv.gox strings.gox unicode.gox utf8.gox
+		strconv.gox strings.gox sync.gox unicode.gox utf8.gox
 	$(BUILDPACKAGE)
 fmt/check: $(CHECK_DEPS)
 	@$(CHECK)
@@ -1901,8 +1936,8 @@
 	@$(CHECK)
 .PHONY: hash/check
 
-html/html.lo: $(go_html_files) bytes.gox io.gox os.gox strconv.gox strings.gox \
-		utf8.gox
+html/html.lo: $(go_html_files) bufio.gox bytes.gox fmt.gox io.gox os.gox \
+		strconv.gox strings.gox utf8.gox
 	$(BUILDPACKAGE)
 html/check: $(CHECK_DEPS)
 	@$(CHECK)
@@ -1919,7 +1954,8 @@
 	@$(CHECK)
 .PHONY: http/check
 
-image/image.lo: $(go_image_files) bufio.gox io.gox os.gox strconv.gox
+image/image.lo: $(go_image_files) bufio.gox image/color.gox io.gox os.gox \
+		strconv.gox
 	$(BUILDPACKAGE)
 image/check: $(CHECK_DEPS)
 	@$(CHECK)
@@ -1975,13 +2011,6 @@
 	@$(CHECK)
 .PHONY: net/check
 
-netchan/netchan.lo: $(go_netchan_files) gob.gox io.gox log.gox net.gox os.gox \
-		reflect.gox strconv.gox sync.gox time.gox
-	$(BUILDPACKAGE)
-netchan/check: $(CHECK_DEPS)
-	@$(CHECK)
-.PHONY: netchan/check
-
 os/os.lo: $(go_os_files) runtime.gox sync.gox syscall.gox
 	$(BUILDPACKAGE)
 os/check: $(CHECK_DEPS)
@@ -2019,8 +2048,8 @@
 	@$(CHECK)
 .PHONY: reflect/check
 
-regexp/regexp.lo: $(go_regexp_files) bytes.gox io.gox os.gox strings.gox \
-		utf8.gox
+regexp/regexp.lo: $(go_regexp_files) bytes.gox io.gox os.gox \
+		regexp/syntax.gox strconv.gox strings.gox sync.gox utf8.gox
 	$(BUILDPACKAGE)
 regexp/check: $(CHECK_DEPS)
 	@$(CHECK)
@@ -2067,7 +2096,7 @@
 	@$(CHECK)
 .PHONY: strconv/check
 
-strings/strings.lo: $(go_strings_files) os.gox unicode.gox utf8.gox
+strings/strings.lo: $(go_strings_files) io.gox os.gox unicode.gox utf8.gox
 	$(BUILDPACKAGE)
 strings/check: $(CHECK_DEPS)
 	@$(CHECK)
@@ -2102,8 +2131,9 @@
 	@$(CHECK)
 .PHONY: template/check
 
-testing/testing.lo: $(go_testing_files) flag.gox fmt.gox os.gox regexp.gox \
-		runtime.gox runtime/pprof.gox strings.gox strconv.gox time.gox
+testing/testing.lo: $(go_testing_files) bytes.gox flag.gox fmt.gox io.gox \
+		os.gox regexp.gox runtime.gox runtime/pprof.gox strings.gox \
+		strconv.gox time.gox
 	$(BUILDPACKAGE)
 testing/check: $(CHECK_DEPS)
 	@$(CHECK)
@@ -2116,12 +2146,6 @@
 	@$(CHECK)
 .PHONY: time/check
 
-try/try.lo: $(go_try_files) fmt.gox io.gox os.gox reflect.gox unicode.gox
-	$(BUILDPACKAGE)
-try/check: $(CHECK_DEPS)
-	@$(CHECK)
-.PHONY: try/check
-
 unicode/unicode.lo: $(go_unicode_files)
 	$(BUILDPACKAGE)
 unicode/check: $(CHECK_DEPS)
@@ -2147,8 +2171,10 @@
 .PHONY: utf8/check
 
 websocket/websocket.lo: $(go_websocket_files) bufio.gox bytes.gox \
-		crypto/md5.gox crypto/tls.gox encoding/binary.gox fmt.gox \
-		http.gox io.gox net.gox os.gox rand.gox strings.gox url.gox
+		crypto/md5.gox crypto/rand.gox crypto/sha1.gox crypto/tls.gox \
+		encoding/base64.gox encoding/binary.gox fmt.gox http.gox \
+		io.gox io/ioutil.gox json.gox net.gox os.gox rand.gox \
+		strings.gox strconv.gox sync.gox url.gox
 	$(BUILDPACKAGE)
 websocket/check: $(CHECK_DEPS)
 	@$(CHECK)
@@ -2237,13 +2263,6 @@
 	@$(CHECK)
 .PHONY: container/ring/check
 
-container/vector.lo: $(go_container_vector_files)
-	$(BUILDPACKAGE)
-container/vector/check: $(CHECK_DEPS)
-	@$(MKDIR_P) container/vector
-	@$(CHECK)
-.PHONY: container/vector/check
-
 crypto/aes.lo: $(go_crypto_aes_files) os.gox strconv.gox
 	$(BUILDPACKAGE)
 crypto/aes/check: $(CHECK_DEPS)
@@ -2251,6 +2270,15 @@
 	@$(CHECK)
 .PHONY: crypto/aes/check
 
+crypto/bcrypt.lo: $(go_crypto_bcrypt_files) crypto/blowfish.gox \
+		crypto/rand.gox crypto/subtle.gox encoding/base64.gox \
+		fmt.gox io.gox os.gox strconv.gox
+	$(BUILDPACKAGE)
+crypto/bcrypt/check: $(CHECK_DEPS)
+	@$(MKDIR_P) crypto/bcrypt
+	@$(CHECK)
+.PHONY: crypto/bcrypt/check
+
 crypto/blowfish.lo: $(go_crypto_blowfish_files) os.gox strconv.gox
 	$(BUILDPACKAGE)
 crypto/blowfish/check: $(CHECK_DEPS)
@@ -2403,12 +2431,12 @@
 .PHONY: crypto/subtle/check
 
 crypto/tls.lo: $(go_crypto_tls_files) big.gox bytes.gox crypto.gox \
-		crypto/aes.gox crypto/cipher.gox crypto/elliptic.gox \
-		crypto/hmac.gox crypto/md5.gox crypto/rand.gox crypto/rc4.gox \
-		crypto/rsa.gox crypto/sha1.gox crypto/subtle.gox \
-		crypto/x509.gox crypto/x509/pkix.gox encoding/pem.gox \
-		hash.gox io.gox io/ioutil.gox net.gox os.gox strconv.gox \
-		strings.gox sync.gox time.gox
+		crypto/aes.gox crypto/cipher.gox crypto/des.gox \
+		crypto/elliptic.gox crypto/hmac.gox crypto/md5.gox \
+		crypto/rand.gox crypto/rc4.gox crypto/rsa.gox crypto/sha1.gox \
+		crypto/subtle.gox crypto/x509.gox crypto/x509/pkix.gox \
+		encoding/pem.gox hash.gox io.gox io/ioutil.gox net.gox os.gox \
+		strconv.gox strings.gox sync.gox time.gox
 	$(BUILDPACKAGE)
 crypto/tls/check: $(CHECK_DEPS)
 	@$(MKDIR_P) crypto/tls
@@ -2583,6 +2611,14 @@
 	@$(CHECK)
 .PHONY: encoding/pem/check
 
+exp/ebnf.lo: $(go_exp_ebnf_files) go/scanner.gox go/token.gox os.gox \
+		strconv.gox unicode.gox utf8.gox
+	$(BUILDPACKAGE)
+exp/ebnf/check: $(CHECK_DEPS)
+	@$(MKDIR_P) exp/ebnf
+	@$(CHECK)
+.PHONY: exp/ebnf/check
+
 exp/gui.lo: $(go_exp_gui_files) image.gox image/draw.gox os.gox
 	$(BUILDPACKAGE)
 exp/gui/check: $(CHECK_DEPS)
@@ -2590,20 +2626,55 @@
 	@$(CHECK)
 .PHONY: exp/gui/check
 
-exp/norm.lo: $(go_exp_norm_files) utf8.gox
+exp/norm.lo: $(go_exp_norm_files) io.gox os.gox utf8.gox
 	$(BUILDPACKAGE)
 exp/norm/check: $(CHECK_DEPS)
 	@$(MKDIR_P) exp/norm
 	@$(CHECK)
 .PHONY: exp/norm/check
 
-exp/regexp.lo: $(go_exp_regexp_files) bytes.gox exp/regexp/syntax.gox io.gox \
-		os.gox strings.gox sync.gox utf8.gox
+exp/spdy.lo: $(go_exp_spdy_files) bytes.gox compress/zlib.gox \
+		encoding/binary.gox http.gox io.gox os.gox strings.gox
 	$(BUILDPACKAGE)
-exp/regexp/check: $(CHECK_DEPS)
-	@$(MKDIR_P) exp/regexp
+exp/spdy/check: $(CHECK_DEPS)
+	@$(MKDIR_P) exp/spdy
 	@$(CHECK)
-.PHONY: exp/regexp/check
+.PHONY: exp/spdy/check
+
+exp/sql.lo: $(go_exp_sql_files) exp/sql/driver.gox fmt.gox os.gox reflect.gox \
+		runtime.gox strconv.gox sync.gox
+	$(BUILDPACKAGE)
+exp/sql/check: $(CHECK_DEPS)
+	@$(MKDIR_P) exp/sql
+	@$(CHECK)
+.PHONY: exp/sql/check
+
+exp/ssh.lo: $(go_exp_ssh_files) big.gox bufio.gox bytes.gox crypto.gox \
+		crypto/aes.gox crypto/cipher.gox crypto/hmac.gox \
+		crypto/rand.gox crypto/rsa.gox crypto/sha1.gox \
+		crypto/subtle.gox crypto/x509.gox encoding/pem.gox hash.gox \
+		io.gox net.gox os.gox reflect.gox strconv.gox sync.gox
+	$(BUILDPACKAGE)
+exp/ssh/check: $(CHECK_DEPS)
+	@$(MKDIR_P) exp/ssh
+	@$(CHECK)
+.PHONY: exp/ssh/check
+
+exp/terminal.lo: $(go_exp_terminal_files) io.gox os.gox syscall.gox
+	$(BUILDPACKAGE)
+exp/terminal/check: $(CHECK_DEPS)
+	@$(MKDIR_P) exp/terminal
+	@$(CHECK)
+.PHONY: exp/terminal/check
+
+exp/types.lo: $(go_exp_types_files) big.gox bufio.gox fmt.gox go/ast.gox \
+		go/token.gox io.gox os.gox path/filepath.gox runtime.gox \
+		scanner.gox sort.gox strconv.gox strings.gox
+	$(BUILDPACKAGE)
+exp/types/check: $(CHECK_DEPS)
+	@$(MKDIR_P) exp/types
+	@$(CHECK)
+.PHONY: exp/types/check
 
 exp/gui/x11.lo: $(go_exp_gui_x11_files) bufio.gox exp/gui.gox image.gox \
 		image/draw.gox io.gox log.gox net.gox os.gox strconv.gox \
@@ -2614,15 +2685,17 @@
 	@$(CHECK)
 .PHONY: exp/gui/x11/check
 
-exp/regexp/syntax.lo: $(go_exp_regexp_syntax_files) bytes.gox os.gox sort.gox strconv.gox strings.gox unicode.gox utf8.gox
+exp/sql/driver.lo: $(go_exp_sql_driver_files) fmt.gox os.gox reflect.gox \
+		strconv.gox
 	$(BUILDPACKAGE)
-exp/regexp/syntax/check: $(CHECK_DEPS)
-	@$(MKDIR_P) exp/regexp/syntax
+exp/sql/driver/check: $(CHECK_DEPS)
+	@$(MKDIR_P) exp/sql/driver
 	@$(CHECK)
-.PHONY: exp/regexp/syntax/check
-
-exp/template/html.lo: $(go_exp_template_html_files) fmt.gox template.gox \
-		template/parse.gox
+.PHONY: exp/sql/driver/check
+
+exp/template/html.lo: $(go_exp_template_html_files) bytes.gox fmt.gox \
+		html.gox json.gox os.gox strings.gox template.gox \
+		template/parse.gox unicode.gox utf8.gox 
 	$(BUILDPACKAGE)
 exp/template/html/check: $(CHECK_DEPS)
 	@$(MKDIR_P) exp/template/html
@@ -2637,9 +2710,10 @@
 	@$(CHECK)
 .PHONY: go/ast/check
 
-go/build.lo: $(go_go_build_files) bytes.gox exec.gox fmt.gox go/parser.gox \
-		go/token.gox log.gox os.gox path/filepath.gox regexp.gox \
-		runtime.gox strconv.gox strings.gox runtime.gox
+go/build.lo: $(go_go_build_files) bytes.gox exec.gox fmt.gox go/ast.gox \
+		go/doc.gox go/parser.gox go/token.gox io/ioutil.gox log.gox \
+		os.gox path.gox path/filepath.gox regexp.gox runtime.gox \
+		sort.gox strconv.gox strings.gox runtime.gox unicode.gox
 	$(BUILDPACKAGE)
 go/build/check: $(CHECK_DEPS)
 	@$(MKDIR_P) go/build
@@ -2656,7 +2730,7 @@
 	$(STAMP) $@
 
 go/doc.lo: $(go_go_doc_files) go/ast.gox go/token.gox io.gox regexp.gox \
-		sort.gox strings.gox template.gox
+		sort.gox strings.gox template.gox unicode.gox utf8.gox
 	$(BUILDPACKAGE)
 go/doc/check: $(CHECK_DEPS)
 	@$(MKDIR_P) go/doc
@@ -2674,7 +2748,7 @@
 
 go/printer.lo: $(go_go_printer_files) bytes.gox fmt.gox go/ast.gox \
 		go/token.gox io.gox os.gox path/filepath.gox reflect.gox \
-		runtime.gox strings.gox tabwriter.gox
+		strings.gox tabwriter.gox
 	$(BUILDPACKAGE)
 go/printer/check: $(CHECK_DEPS)
 	@$(MKDIR_P) go/printer
@@ -2690,30 +2764,14 @@
 	@$(CHECK)
 .PHONY: go/scanner/check
 
-go/token.lo: $(go_go_token_files) fmt.gox strconv.gox
+go/token.lo: $(go_go_token_files) fmt.gox gob.gox io.gox os.gox sort.gox \
+		strconv.gox sync.gox
 	$(BUILDPACKAGE)
 go/token/check: $(CHECK_DEPS)
 	@$(MKDIR_P) go/token
 	@$(CHECK)
 .PHONY: go/token/check
 
-go/typechecker.lo: $(go_go_typechecker_files) fmt.gox go/ast.gox go/token.gox \
-		go/scanner.gox os.gox
-	$(BUILDPACKAGE)
-go/typechecker/check: $(CHECK_DEPS)
-	@$(MKDIR_P) go/typechecker
-	@$(CHECK)
-.PHONY: go/typechecker/check
-
-go/types.lo: $(go_go_types_files) big.gox bufio.gox fmt.gox go/ast.gox \
-		go/token.gox io.gox os.gox path/filepath.gox runtime.gox \
-		scanner.gox sort.gox strconv.gox strings.gox
-	$(BUILDPACKAGE)
-go/types/check: $(CHECK_DEPS)
-	@$(MKDIR_P) go/types
-	@$(CHECK)
-.PHONY: go/types/check
-
 hash/adler32.lo: $(go_hash_adler32_files) hash.gox os.gox
 	$(BUILDPACKAGE)
 hash/adler32/check: $(CHECK_DEPS)
@@ -2777,23 +2835,21 @@
 	@$(CHECK)
 .PHONY: http/pprof/check
 
-http/spdy.lo: $(go_http_spdy_files) bytes.gox compress/zlib.gox \
-		encoding/binary.gox http.gox io.gox os.gox strconv.gox \
-		strings.gox sync.gox
-	$(BUILDPACKAGE)
-http/spdy/check: $(CHECK_DEPS)
-	@$(MKDIR_P) http/spdy
-	@$(CHECK)
-.PHONY: http/spdy/check
-
-image/bmp.lo: $(go_image_bmp_files) image.gox io.gox os.gox
+image/bmp.lo: $(go_image_bmp_files) image.gox image/color.gox io.gox os.gox
 	$(BUILDPACKAGE)
 image/bmp/check: $(CHECK_DEPS)
 	@$(MKDIR_P) image/bmp
 	@$(CHECK)
 .PHONY: image/bmp/check
 
-image/draw.lo: $(go_image_draw_files) image.gox image/ycbcr.gox
+image/color.lo: $(go_image_color_files)
+	$(BUILDPACKAGE)
+image/color/check: $(CHECK_DEPS)
+	@$(MKDIR_P) image/color
+	@$(CHECK)
+.PHONY: image/color/check
+
+image/draw.lo: $(go_image_draw_files) image.gox image/color.gox image/ycbcr.gox
 	$(BUILDPACKAGE)
 image/draw/check: $(CHECK_DEPS)
 	@$(MKDIR_P) image/draw
@@ -2801,46 +2857,48 @@
 .PHONY: image/draw/check
 
 image/gif.lo: $(go_image_gif_files) bufio.gox compress/lzw.gox fmt.gox \
-		image.gox io.gox os.gox
+		image.gox image/color.gox io.gox os.gox
 	$(BUILDPACKAGE)
 image/gif/check: $(CHECK_DEPS)
 	@$(MKDIR_P) image/gif
 	@$(CHECK)
 .PHONY: image/gif/check
 
-image/jpeg.lo: $(go_image_jpeg_files) bufio.gox image.gox image/ycbcr.gox \
-		io.gox os.gox
+image/jpeg.lo: $(go_image_jpeg_files) bufio.gox image.gox image/color.gox \
+		image/ycbcr.gox io.gox os.gox
 	$(BUILDPACKAGE)
 image/jpeg/check: $(CHECK_DEPS)
 	@$(MKDIR_P) image/jpeg
 	@$(CHECK)
 .PHONY: image/jpeg/check
 
-image/png.lo: $(go_image_png_files) bufio.gox compress/zlib.gox fmt.gox \
-		hash.gox hash/crc32.gox image.gox io.gox os.gox strconv.gox
+image/png.lo: $(go_image_png_files) bufio.gox compress/zlib.gox \
+		encoding/binary.gox fmt.gox hash.gox hash/crc32.gox image.gox \
+		image/color.gox io.gox os.gox strconv.gox
 	$(BUILDPACKAGE)
 image/png/check: $(CHECK_DEPS)
 	@$(MKDIR_P) image/png
 	@$(CHECK)
 .PHONY: image/png/check
 
-image/tiff.lo: $(go_image_tiff_files) compress/lzw.gox compress/zlib.gox \
-		encoding/binary.gox image.gox io.gox io/ioutil.gox os.gox
+image/tiff.lo: $(go_image_tiff_files) bufio.gox compress/lzw.gox \
+		compress/zlib.gox encoding/binary.gox image.gox \
+		image/color.gox io.gox io/ioutil.gox os.gox
 	$(BUILDPACKAGE)
 image/tiff/check: $(CHECK_DEPS)
 	@$(MKDIR_P) image/tiff
 	@$(CHECK)
 .PHONY: image/tiff/check
 
-image/ycbcr.lo: $(go_image_ycbcr_files) image.gox
+image/ycbcr.lo: $(go_image_ycbcr_files) image.gox image/color.gox
 	$(BUILDPACKAGE)
 image/ycbcr/check: $(CHECK_DEPS)
 	@$(MKDIR_P) image/ycbcr
 	@$(CHECK)
 .PHONY: image/ycbcr/check
 
-index/suffixarray.lo: $(go_index_suffixarray_files) bytes.gox regexp.gox \
-		sort.gox
+index/suffixarray.lo: $(go_index_suffixarray_files) bytes.gox \
+		encoding/binary.gox io.gox os.gox regexp.gox sort.gox
 	$(BUILDPACKAGE)
 index/suffixarray/check: $(CHECK_DEPS)
 	@$(MKDIR_P) index/suffixarray
@@ -2869,13 +2927,30 @@
 	$(BUILDPACKAGE)
 
 net/textproto.lo: $(go_net_textproto_files) bufio.gox bytes.gox fmt.gox \
-		io.gox io/ioutil.gox net.gox os.gox strconv.gox sync.gox
+		io.gox io/ioutil.gox net.gox os.gox strings.gox strconv.gox \
+		sync.gox
 	$(BUILDPACKAGE)
 net/textproto/check: $(CHECK_DEPS)
 	@$(MKDIR_P) net/textproto
 	@$(CHECK)
 .PHONY: net/textproto/check
 
+old/netchan.lo: $(go_old_netchan_files) gob.gox io.gox log.gox net.gox os.gox \
+		reflect.gox strconv.gox sync.gox time.gox
+	$(BUILDPACKAGE)
+old/netchan/check: $(CHECK_DEPS)
+	@$(MKDIR_P) old/netchan
+	@$(CHECK)
+.PHONY: old/netchan/check
+
+old/regexp.lo: $(go_old_regexp_files) bytes.gox io.gox os.gox strings.gox \
+		utf8.gox
+	$(BUILDPACKAGE)
+old/regexp/check: $(CHECK_DEPS)
+	@$(MKDIR_P) old/regexp
+	@$(CHECK)
+.PHONY: old/regexp/check
+
 old/template.lo: $(go_old_template_files) bytes.gox fmt.gox io.gox \
 		io/ioutil.gox os.gox reflect.gox strconv.gox strings.gox \
 		unicode.gox utf8.gox
@@ -2915,6 +2990,14 @@
 	@$(CHECK)
 .PHONY: path/filepath/check
 
+regexp/syntax.lo: $(go_regexp_syntax_files) bytes.gox os.gox sort.gox \
+		strconv.gox strings.gox unicode.gox utf8.gox
+	$(BUILDPACKAGE)
+regexp/syntax/check: $(CHECK_DEPS)
+	@$(MKDIR_P) regexp/syntax
+	@$(CHECK)
+.PHONY: regexp/syntax/check
+
 rpc/jsonrpc.lo: $(go_rpc_jsonrpc_files) fmt.gox io.gox json.gox net.gox \
 		os.gox rpc.gox sync.gox
 	$(BUILDPACKAGE)
@@ -3005,8 +3088,6 @@
 	$(BUILDGOX)
 csv.gox: csv/csv.lo
 	$(BUILDGOX)
-ebnf.gox: ebnf/ebnf.lo
-	$(BUILDGOX)
 exec.gox: exec/exec.lo
 	$(BUILDGOX)
 expvar.gox: expvar/expvar.lo
@@ -3039,8 +3120,6 @@
 	$(BUILDGOX)
 net.gox: net/net.lo
 	$(BUILDGOX)
-netchan.gox: netchan/netchan.lo
-	$(BUILDGOX)
 os.gox: os/os.lo
 	$(BUILDGOX)
 patch.gox: patch/patch.lo
@@ -3081,8 +3160,6 @@
 	$(BUILDGOX)
 time.gox: time/time.lo
 	$(BUILDGOX)
-try.gox: try/try.lo
-	$(BUILDGOX)
 unicode.gox: unicode/unicode.lo
 	$(BUILDGOX)
 url.gox: url/url.lo
@@ -3118,10 +3195,10 @@
 	$(BUILDGOX)
 container/ring.gox: container/ring.lo
 	$(BUILDGOX)
-container/vector.gox: container/vector.lo
+
+crypto/aes.gox: crypto/aes.lo
 	$(BUILDGOX)
-
-crypto/aes.gox: crypto/aes.lo
+crypto/bcrypt.gox: crypto/bcrypt.lo
 	$(BUILDGOX)
 crypto/blowfish.gox: crypto/blowfish.lo
 	$(BUILDGOX)
@@ -3212,17 +3289,27 @@
 encoding/pem.gox: encoding/pem.lo
 	$(BUILDGOX)
 
+exp/ebnf.gox: exp/ebnf.lo
+	$(BUILDGOX)
 exp/gui.gox: exp/gui.lo
 	$(BUILDGOX)
 exp/norm.gox: exp/norm.lo
 	$(BUILDGOX)
-exp/regexp.gox: exp/regexp.lo
+exp/spdy.gox: exp/spdy.lo
+	$(BUILDGOX)
+exp/sql.gox: exp/sql.lo
+	$(BUILDGOX)
+exp/ssh.gox: exp/ssh.lo
+	$(BUILDGOX)
+exp/terminal.gox: exp/terminal.lo
+	$(BUILDGOX)
+exp/types.gox: exp/types.lo
 	$(BUILDGOX)
 
 exp/gui/x11.gox: exp/gui/x11.lo
 	$(BUILDGOX)
 
-exp/regexp/syntax.gox: exp/regexp/syntax.lo
+exp/sql/driver.gox: exp/sql/driver.lo
 	$(BUILDGOX)
 
 exp/template/html.gox: exp/template/html.lo
@@ -3242,10 +3329,6 @@
 	$(BUILDGOX)
 go/token.gox: go/token.lo
 	$(BUILDGOX)
-go/typechecker.gox: go/typechecker.lo
-	$(BUILDGOX)
-go/types.gox: go/types.lo
-	$(BUILDGOX)
 
 hash/adler32.gox: hash/adler32.lo
 	$(BUILDGOX)
@@ -3264,10 +3347,10 @@
 	$(BUILDGOX)
 http/pprof.gox: http/pprof.lo
 	$(BUILDGOX)
-http/spdy.gox: http/spdy.lo
+
+image/bmp.gox: image/bmp.lo
 	$(BUILDGOX)
-
-image/bmp.gox: image/bmp.lo
+image/color.gox: image/color.lo
 	$(BUILDGOX)
 image/draw.gox: image/draw.lo
 	$(BUILDGOX)
@@ -3296,6 +3379,10 @@
 net/textproto.gox: net/textproto.lo
 	$(BUILDGOX)
 
+old/netchan.gox: old/netchan.lo
+	$(BUILDGOX)
+old/regexp.gox: old/regexp.lo
+	$(BUILDGOX)
 old/template.gox: old/template.lo
 	$(BUILDGOX)
 
@@ -3309,6 +3396,9 @@
 path/filepath.gox: path/filepath.lo
 	$(BUILDGOX)
 
+regexp/syntax.gox: regexp/syntax.lo
+	$(BUILDGOX)
+
 rpc/jsonrpc.gox: rpc/jsonrpc.lo
 	$(BUILDGOX)
 
@@ -3344,7 +3434,6 @@
 	bytes/check \
 	cmath/check \
 	csv/check \
-	ebnf/check \
 	exec/check \
 	expvar/check \
 	flag/check \
@@ -3360,7 +3449,6 @@
 	mail/check \
 	mime/check \
 	net/check \
-	netchan/check \
 	os/check \
 	patch/check \
 	path/check \
@@ -3379,7 +3467,6 @@
 	tabwriter/check \
 	template/check \
 	time/check \
-	try/check \
 	unicode/check \
 	url/check \
 	utf16/check \
@@ -3396,8 +3483,8 @@
 	container/heap/check \
 	container/list/check \
 	container/ring/check \
-	container/vector/check \
 	crypto/aes/check \
+	crypto/bcrypt/check \
 	crypto/blowfish/check \
 	crypto/cast5/check \
 	crypto/cipher/check \
@@ -3437,9 +3524,12 @@
 	encoding/git85/check \
 	encoding/hex/check \
 	encoding/pem/check \
+	exp/ebnf/check \
 	exp/norm/check \
-	exp/regexp/check \
-	exp/regexp/syntax/check \
+	exp/spdy/check \
+	exp/sql/check \
+	exp/ssh/check \
+	exp/terminal/check \
 	exp/template/html/check \
 	go/ast/check \
 	$(go_build_check_omitted_since_it_calls_6g) \
@@ -3447,7 +3537,6 @@
 	go/printer/check \
 	go/scanner/check \
 	go/token/check \
-	go/typechecker/check \
 	$(go_types_check_omitted_since_it_calls_6g) \
 	hash/adler32/check \
 	hash/crc32/check \
@@ -3455,7 +3544,6 @@
 	hash/fnv/check \
 	http/cgi/check \
 	http/fcgi/check \
-	http/spdy/check \
 	image/draw/check \
 	image/jpeg/check \
 	image/png/check \
@@ -3465,11 +3553,14 @@
 	io/ioutil/check \
 	mime/multipart/check \
 	net/textproto/check \
+	old/netchan/check \
+	old/regexp/check \
 	old/template/check \
 	$(os_inotify_check) \
 	os/user/check \
 	os/signal/check \
 	path/filepath/check \
+	regexp/syntax/check \
 	rpc/jsonrpc/check \
 	sync/atomic/check \
 	template/parse/check \
diff -r c36211271569 libgo/go/syscall/exec_unix.go
--- a/libgo/go/syscall/exec_unix.go	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/go/syscall/exec_unix.go	Wed Oct 26 16:12:38 2011 -0700
@@ -2,8 +2,6 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin freebsd linux openbsd
-
 // Fork, exec, wait, etc.
 
 package syscall
@@ -87,10 +85,10 @@
 // 2) Socket.  Does not block.  Use the ForkLock.
 // 3) Accept.  If using non-blocking mode, use the ForkLock.
 //             Otherwise, live with the race.
-// 4) Open.    Can block.  Use O_CLOEXEC if available (Linux).
+// 4) Open.    Can block.  Use O_CLOEXEC if available (GNU/Linux).
 //             Otherwise, live with the race.
 // 5) Dup.     Does not block.  Use the ForkLock.
-//             On Linux, could use fcntl F_DUPFD_CLOEXEC
+//             On GNU/Linux, could use fcntl F_DUPFD_CLOEXEC
 //             instead of the ForkLock, but only for dup(fd, -1).
 
 var ForkLock sync.RWMutex
@@ -254,8 +252,8 @@
 			continue
 		}
 		if fd[i] == int(i) {
-			// Dup2(i, i) won't clear close-on-exec flag on Linux,
-			// probably not elsewhere either.
+			// Dup2(i, i) won't clear close-on-exec flag on
+			// GNU/Linux, probably not elsewhere either.
 			_, err1 = raw_fcntl(fd[i], F_SETFD, 0)
 			if err1 != 0 {
 				goto childerror
diff -r c36211271569 libgo/go/syscall/libcall_linux.go
--- a/libgo/go/syscall/libcall_linux.go	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/go/syscall/libcall_linux.go	Wed Oct 26 16:12:38 2011 -0700
@@ -21,7 +21,7 @@
 }
 
 func Futimes(fd int, tv []Timeval) (errno int) {
-	// Believe it or not, this is the best we can do on Linux
+	// Believe it or not, this is the best we can do on GNU/Linux
 	// (and is what glibc does).
 	return Utimes("/proc/self/fd/"+itoa(fd), tv)
 }
diff -r c36211271569 libgo/go/syscall/libcall_posix.go
--- a/libgo/go/syscall/libcall_posix.go	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/go/syscall/libcall_posix.go	Wed Oct 26 16:12:38 2011 -0700
@@ -73,7 +73,7 @@
 		return nil, 0
 	}
 
-	// Sanity check group count.  Max is 1<<16 on Linux.
+	// Sanity check group count.  Max is 1<<16 on GNU/Linux.
 	if n < 0 || n > 1<<20 {
 		return nil, EINVAL
 	}
diff -r c36211271569 libgo/go/syscall/lsf_linux.go
--- a/libgo/go/syscall/lsf_linux.go	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/go/syscall/lsf_linux.go	Wed Oct 26 16:12:38 2011 -0700
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// Linux socket filter
+// GNU/Linux socket filter
 
 package syscall
 
diff -r c36211271569 libgo/go/syscall/socket.go
--- a/libgo/go/syscall/socket.go	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/go/syscall/socket.go	Wed Oct 26 16:12:38 2011 -0700
@@ -296,14 +296,10 @@
 
 */
 
-/* FIXME: mksysinfo needs to support IPv6Mreq.
-
 func SetsockoptIPv6Mreq(fd, level, opt int, mreq *IPv6Mreq) (errno int) {
 	return setsockopt(fd, level, opt, (*byte)(unsafe.Pointer(mreq)), Socklen_t(unsafe.Sizeof(*mreq)))
 }
 
-*/
-
 func SetsockoptString(fd, level, opt int, s string) (errno int) {
 	return setsockopt(fd, level, opt, (*byte)(unsafe.Pointer(&[]byte(s)[0])), Socklen_t(len(s)))
 }
diff -r c36211271569 libgo/go/syscall/socket_irix.go
--- a/libgo/go/syscall/socket_irix.go	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/go/syscall/socket_irix.go	Wed Oct 26 16:12:38 2011 -0700
@@ -52,7 +52,7 @@
 	}
 
 	// Assume path ends at NUL.
-	// This is not technically the Linux semantics for
+	// This is not technically the GNU/Linux semantics for
 	// abstract Unix domain sockets--they are supposed
 	// to be uninterpreted fixed-size binary blobs--but
 	// everyone uses this convention.
diff -r c36211271569 libgo/go/syscall/socket_linux.go
--- a/libgo/go/syscall/socket_linux.go	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/go/syscall/socket_linux.go	Wed Oct 26 16:12:38 2011 -0700
@@ -1,4 +1,4 @@
-// socket_linux.go -- Socket handling specific to Linux.
+// socket_linux.go -- Socket handling specific to GNU/Linux.
 
 // Copyright 2010 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
@@ -98,7 +98,7 @@
 	}
 
 	// Assume path ends at NUL.
-	// This is not technically the Linux semantics for
+	// This is not technically the GNU/Linux semantics for
 	// abstract Unix domain sockets--they are supposed
 	// to be uninterpreted fixed-size binary blobs--but
 	// everyone uses this convention.
diff -r c36211271569 libgo/go/syscall/socket_solaris.go
--- a/libgo/go/syscall/socket_solaris.go	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/go/syscall/socket_solaris.go	Wed Oct 26 16:12:38 2011 -0700
@@ -53,7 +53,7 @@
 	}
 
 	// Assume path ends at NUL.
-	// This is not technically the Linux semantics for
+	// This is not technically the GNU/Linux semantics for
 	// abstract Unix domain sockets--they are supposed
 	// to be uninterpreted fixed-size binary blobs--but
 	// everyone uses this convention.
diff -r c36211271569 libgo/merge.sh
--- a/libgo/merge.sh	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/merge.sh	Wed Oct 26 16:12:38 2011 -0700
@@ -38,9 +38,9 @@
 hg clone -r ${old_rev} ${repository} ${OLDDIR}
 
 rm -rf ${NEWDIR}
-hg clone -u release ${repository} ${NEWDIR}
+hg clone -u weekly ${repository} ${NEWDIR}
 
-new_rev=`cd ${NEWDIR} && hg log -r release | sed 1q | sed -e 's/.*://'`
+new_rev=`cd ${NEWDIR} && hg log -r weekly | sed 1q | sed -e 's/.*://'`
 
 merge() {
   name=$1
diff -r c36211271569 libgo/mksysinfo.sh
--- a/libgo/mksysinfo.sh	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/mksysinfo.sh	Wed Oct 26 16:12:38 2011 -0700
@@ -463,7 +463,7 @@
       -e 's/msg_flags/Flags/' \
     >> ${OUT}
 
-# The ip_mreq struct
+# The ip_mreq struct.
 grep '^type _ip_mreq ' gen-sysinfo.go | \
     sed -e 's/_ip_mreq/IPMreq/' \
       -e 's/imr_multiaddr/Multiaddr/' \
@@ -476,6 +476,14 @@
   echo 'var SizeofIPMreq = int(unsafe.Sizeof(IPMreq{}))' >> ${OUT}
 fi
 
+# The ipv6_mreq struct.
+grep '^type _ipv6_mreq ' gen-sysinfo.go | \
+    sed -e 's/_ipv6_mreq/IPv6Mreq/' \
+      -e 's/ipv6mr_multiaddr/Multiaddr/' \
+      -e 's/ipv6mr_interface/Interface/' \
+      -e 's/_in6_addr/[16]byte/' \
+    >> ${OUT}
+
 # Try to guess the type to use for fd_set.
 fd_set=`grep '^type _fd_set ' gen-sysinfo.go || true`
 fds_bits_type="_C_long"
@@ -504,6 +512,10 @@
 grep '^const _TIOC' gen-sysinfo.go | \
     sed -e 's/^\(const \)_\(TIOC[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
 
+# The ioctl flags for terminal control
+grep '^const _TC[GS]ET' gen-sysinfo.go | \
+    sed -e 's/^\(const \)_\(TC[GS]ET[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+
 # ioctl constants.  Might fall back to 0 if TIOCNXCL is missing, too, but
 # needs handling in syscalls.exec.go.
 if ! grep '^const _TIOCSCTTY ' gen-sysinfo.go >/dev/null 2>&1; then
@@ -619,4 +631,33 @@
   echo 'var SizeofRtAttr = int(unsafe.Sizeof(RtAttr{}))' >> ${OUT}
 fi
 
+# The termios struct.
+grep '^type _termios ' gen-sysinfo.go | \
+    sed -e 's/_termios/Termios/' \
+      -e 's/c_iflag/Iflag/' \
+      -e 's/c_oflag/Oflag/' \
+      -e 's/c_cflag/Cflag/' \
+      -e 's/c_lflag/Lflag/' \
+      -e 's/c_line/Line/' \
+      -e 's/c_cc/Cc/' \
+      -e 's/c_ispeed/Ispeed/' \
+      -e 's/c_ospeed/Ospeed/' \
+    >> ${OUT}
+
+# The termios constants.  The ones starting with 'E' were picked up above.
+for n in IGNBRK BRKINT IGNPAR PARMRK INPCK ISTRIP INLCR IGNCR ICRNL IUCLC \
+    IXON IXANY IXOFF IMAXBEL IUTF8 OPOST OLCUC ONLCR OCRNL ONOCR ONLRET \
+    OFILL OFDEL NLDLY NL0 NL1 CRDLY CR0 CR1 CR2 CR3 TABDLY BSDLY VTDLY \
+    FFDLY CBAUD CBAUDEX CSIZE CSTOPB CREAD PARENB PARODD HUPCL CLOCAL \
+    LOBLK CIBAUD CMSPAR CRTSCTS ISIG ICANON XCASE DEFECHK FLUSHO NOFLSH \
+    TOSTOP PENDIN IEXTEN VINTR VQUIT VERASE VKILL VEOF VMIN VEOL VTIME VEOL2 \
+    VSWTCH VSTART VSTOP VSUSP VDSUSP VLNEXT VWERASE VREPRINT VDISCARD VSTATUS \
+    TCSANOW TCSADRAIN, TCSAFLUSH TCIFLUSH TCOFLUSH TCIOFLUSH TCOOFF TCOON \
+    TCIOFF TCION B0 B50 B75 B110 B134 B150 B200 B300 B600 B1200 B1800 B2400 \
+    B4800 B9600 B19200 B38400 B57600 B115200 B230400; do
+
+    grep "^const _$n " gen-sysinfo.go | \
+	sed -e 's/^\(const \)_\([^=]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+done
+
 exit $?
diff -r c36211271569 libgo/runtime/arch.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgo/runtime/arch.h	Wed Oct 26 16:12:38 2011 -0700
@@ -0,0 +1,8 @@
+// Copyright 2011 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.
+
+// FIXME: Ideally CacheLineSize would be dependent on the host architecture.
+enum {
+	CacheLineSize = 64
+};
diff -r c36211271569 libgo/runtime/cpuprof.c
--- a/libgo/runtime/cpuprof.c	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/cpuprof.c	Wed Oct 26 16:12:38 2011 -0700
@@ -49,6 +49,7 @@
 // in the situation when normally the goroutine "owns" handoff.
 
 #include "runtime.h"
+#include "arch.h"
 #include "malloc.h"
 
 #include "array.h"
diff -r c36211271569 libgo/runtime/go-append.c
--- a/libgo/runtime/go-append.c	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/go-append.c	Wed Oct 26 16:12:38 2011 -0700
@@ -8,6 +8,7 @@
 #include "go-panic.h"
 #include "array.h"
 #include "runtime.h"
+#include "arch.h"
 #include "malloc.h"
 
 /* We should be OK if we don't split the stack here, since the only
diff -r c36211271569 libgo/runtime/go-byte-array-to-string.c
--- a/libgo/runtime/go-byte-array-to-string.c	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/go-byte-array-to-string.c	Wed Oct 26 16:12:38 2011 -0700
@@ -6,6 +6,7 @@
 
 #include "go-string.h"
 #include "runtime.h"
+#include "arch.h"
 #include "malloc.h"
 
 struct __go_string
diff -r c36211271569 libgo/runtime/go-go.c
--- a/libgo/runtime/go-go.c	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/go-go.c	Wed Oct 26 16:12:38 2011 -0700
@@ -17,6 +17,7 @@
 #include "go-panic.h"
 #include "go-alloc.h"
 #include "runtime.h"
+#include "arch.h"
 #include "malloc.h"
 
 #ifdef USING_SPLIT_STACK
@@ -561,7 +562,7 @@
 /* Start the other threads after garbage collection.  */
 
 void
-runtime_starttheworld (void)
+runtime_starttheworld (bool extra __attribute__ ((unused)))
 {
   int i;
   pthread_t me;
diff -r c36211271569 libgo/runtime/go-int-array-to-string.c
--- a/libgo/runtime/go-int-array-to-string.c	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/go-int-array-to-string.c	Wed Oct 26 16:12:38 2011 -0700
@@ -7,6 +7,7 @@
 #include "go-assert.h"
 #include "go-string.h"
 #include "runtime.h"
+#include "arch.h"
 #include "malloc.h"
 
 struct __go_string
diff -r c36211271569 libgo/runtime/go-int-to-string.c
--- a/libgo/runtime/go-int-to-string.c	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/go-int-to-string.c	Wed Oct 26 16:12:38 2011 -0700
@@ -6,6 +6,7 @@
 
 #include "go-string.h"
 #include "runtime.h"
+#include "arch.h"
 #include "malloc.h"
 
 struct __go_string
diff -r c36211271569 libgo/runtime/go-main.c
--- a/libgo/runtime/go-main.c	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/go-main.c	Wed Oct 26 16:12:38 2011 -0700
@@ -19,6 +19,7 @@
 #include "go-string.h"
 
 #include "runtime.h"
+#include "arch.h"
 #include "malloc.h"
 
 #undef int
diff -r c36211271569 libgo/runtime/go-make-slice.c
--- a/libgo/runtime/go-make-slice.c	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/go-make-slice.c	Wed Oct 26 16:12:38 2011 -0700
@@ -12,6 +12,7 @@
 #include "go-type.h"
 #include "array.h"
 #include "runtime.h"
+#include "arch.h"
 #include "malloc.h"
 
 struct __go_open_array
diff -r c36211271569 libgo/runtime/go-new.c
--- a/libgo/runtime/go-new.c	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/go-new.c	Wed Oct 26 16:12:38 2011 -0700
@@ -6,6 +6,7 @@
 
 #include "go-alloc.h"
 #include "runtime.h"
+#include "arch.h"
 #include "malloc.h"
 
 void *
diff -r c36211271569 libgo/runtime/go-note.c
--- a/libgo/runtime/go-note.c	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/go-note.c	Wed Oct 26 16:12:38 2011 -0700
@@ -12,7 +12,7 @@
 #include "runtime.h"
 
 /* We use a single global lock and condition variable.  It would be
-   better to use a futex on Linux.  */
+   better to use a futex on GNU/Linux.  */
 
 static pthread_mutex_t note_lock = PTHREAD_MUTEX_INITIALIZER;
 static pthread_cond_t note_cond = PTHREAD_COND_INITIALIZER;
diff -r c36211271569 libgo/runtime/go-panic.c
--- a/libgo/runtime/go-panic.c	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/go-panic.c	Wed Oct 26 16:12:38 2011 -0700
@@ -8,6 +8,7 @@
 #include <stdlib.h>
 
 #include "runtime.h"
+#include "arch.h"
 #include "malloc.h"
 #include "go-alloc.h"
 #include "go-defer.h"
diff -r c36211271569 libgo/runtime/go-semacquire.c
--- a/libgo/runtime/go-semacquire.c	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/go-semacquire.c	Wed Oct 26 16:12:38 2011 -0700
@@ -13,9 +13,9 @@
 
 /* We use a single global lock and condition variable.  This is
    painful, since it will cause unnecessary contention, but is hard to
-   avoid in a portable manner.  On Linux we can use futexes, but they
-   are unfortunately not exposed by libc and are thus also hard to use
-   portably.  */
+   avoid in a portable manner.  On GNU/Linux we can use futexes, but
+   they are unfortunately not exposed by libc and are thus also hard
+   to use portably.  */
 
 static pthread_mutex_t sem_lock = PTHREAD_MUTEX_INITIALIZER;
 static pthread_cond_t sem_cond = PTHREAD_COND_INITIALIZER;
diff -r c36211271569 libgo/runtime/go-string-to-byte-array.c
--- a/libgo/runtime/go-string-to-byte-array.c	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/go-string-to-byte-array.c	Wed Oct 26 16:12:38 2011 -0700
@@ -7,6 +7,7 @@
 #include "go-string.h"
 #include "array.h"
 #include "runtime.h"
+#include "arch.h"
 #include "malloc.h"
 
 struct __go_open_array
diff -r c36211271569 libgo/runtime/go-string-to-int-array.c
--- a/libgo/runtime/go-string-to-int-array.c	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/go-string-to-int-array.c	Wed Oct 26 16:12:38 2011 -0700
@@ -8,6 +8,7 @@
 #include "go-string.h"
 #include "array.h"
 #include "runtime.h"
+#include "arch.h"
 #include "malloc.h"
 
 struct __go_open_array
diff -r c36211271569 libgo/runtime/go-strplus.c
--- a/libgo/runtime/go-strplus.c	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/go-strplus.c	Wed Oct 26 16:12:38 2011 -0700
@@ -6,6 +6,7 @@
 
 #include "go-string.h"
 #include "runtime.h"
+#include "arch.h"
 #include "malloc.h"
 
 struct __go_string
diff -r c36211271569 libgo/runtime/go-strslice.c
--- a/libgo/runtime/go-strslice.c	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/go-strslice.c	Wed Oct 26 16:12:38 2011 -0700
@@ -7,6 +7,7 @@
 #include "go-string.h"
 #include "go-panic.h"
 #include "runtime.h"
+#include "arch.h"
 #include "malloc.h"
 
 struct __go_string
diff -r c36211271569 libgo/runtime/goc2c.c
--- a/libgo/runtime/goc2c.c	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/goc2c.c	Wed Oct 26 16:12:38 2011 -0700
@@ -219,13 +219,14 @@
 }
 
 /*
- * Read and return a token.  Tokens are delimited by whitespace or by
- * [(),{}].  The latter are all returned as single characters.
+ * Read and return a token.  Tokens are string or character literals
+ * or else delimited by whitespace or by [(),{}].
+ * The latter are all returned as single characters.
  */
 static char *
 read_token(void)
 {
-	int c;
+	int c, q;
 	char *buf;
 	unsigned int alc, off;
 	const char* delims = "(),{}";
@@ -240,7 +241,26 @@
 	alc = 16;
 	buf = xmalloc(alc + 1);
 	off = 0;
-	if (strchr(delims, c) != NULL) {
+	if(c == '"' || c == '\'') {
+		q = c;
+		buf[off] = c;
+		++off;
+		while (1) {
+			if (off+2 >= alc) { // room for c and maybe next char
+				alc *= 2;
+				buf = xrealloc(buf, alc + 1);
+			}
+			c = getchar_no_eof();
+			buf[off] = c;
+			++off;
+			if(c == q)
+				break;
+			if(c == '\\') {
+				buf[off] = getchar_no_eof();
+				++off;
+			}
+		}
+	} else if (strchr(delims, c) != NULL) {
 		buf[off] = c;
 		++off;
 	} else {
diff -r c36211271569 libgo/runtime/malloc.goc
--- a/libgo/runtime/malloc.goc	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/malloc.goc	Wed Oct 26 16:12:38 2011 -0700
@@ -12,6 +12,7 @@
 #include <stdlib.h>
 #include "go-alloc.h"
 #include "runtime.h"
+#include "arch.h"
 #include "malloc.h"
 #include "go-string.h"
 #include "interface.h"
@@ -96,11 +97,12 @@
 			m->mcache->next_sample -= size;
 		else {
 			// pick next profile time
+			// If you change this, also change allocmcache.
 			if(rate > 0x3fffffff)	// make 2*rate not overflow
 				rate = 0x3fffffff;
 			m->mcache->next_sample = runtime_fastrand1() % (2*rate);
 		profile:
-			runtime_setblockspecial(v);
+			runtime_setblockspecial(v, true);
 			runtime_MProf_Malloc(v, size);
 		}
 	}
@@ -224,6 +226,7 @@
 MCache*
 runtime_allocmcache(void)
 {
+	int32 rate;
 	MCache *c;
 
 	if(!__sync_bool_compare_and_swap(&m->mallocing, 0, 1))
@@ -239,6 +242,13 @@
 	mstats.mcache_sys = runtime_mheap.cachealloc.sys;
 	runtime_unlock(&runtime_mheap);
 
+	// Set first allocation sample size.
+	rate = runtime_MemProfileRate;
+	if(rate > 0x3fffffff)	// make 2*rate not overflow
+		rate = 0x3fffffff;
+	if(rate != 0)
+		c->next_sample = runtime_fastrand1() % (2*rate);
+
 	__sync_bool_compare_and_swap(&m->mallocing, 1, 0);
 	if(__sync_bool_compare_and_swap(&m->gcing, 1, 0))
 		__go_run_goroutine_gc(2);
@@ -280,6 +290,7 @@
 	byte *p;
 	uintptr arena_size, bitmap_size;
 	extern byte end[];
+	byte *want;
 
 	runtime_sizeof_C_MStats = sizeof(MStats);
 
@@ -341,9 +352,13 @@
 		// not as an absolute requirement.  If we ask for the end
 		// of the data segment but the operating system requires
 		// a little more space before we can start allocating, it will
-		// give out a slightly higher pointer.  That's fine.  
-		// Run with what we get back.
-		p = runtime_SysReserve(end, bitmap_size + arena_size);
+		// give out a slightly higher pointer.  Except QEMU, which
+		// is buggy, as usual: it won't adjust the pointer upward.
+		// So adjust it upward a little bit ourselves: 1/4 MB to get
+		// away from the running binary image and then round up
+		// to a MB boundary.
+		want = (byte*)(((uintptr)end + (1<<18) + (1<<20) - 1)&~((1<<20)-1));
+		p = runtime_SysReserve(want, bitmap_size + arena_size);
 		if(p == nil)
 			runtime_throw("runtime: cannot reserve arena virtual address space");
 	}
@@ -418,8 +433,9 @@
 	return runtime_mallocgc(n, 0, 1, 1);
 }
 
-func new(n uint32) (ret *uint8) {
-	ret = runtime_mal(n);
+func new(typ *Type) (ret *uint8) {
+	uint32 flag = typ->__code&GO_NO_POINTERS ? FlagNoPointers : 0;
+	ret = runtime_mallocgc(typ->__size, flag, 1, 1);
 }
 
 func Alloc(n uintptr) (p *byte) {
@@ -444,9 +460,8 @@
 	const FuncType *ft;
 
 	if(obj.__type_descriptor == nil) {
-		// runtime_printf("runtime.SetFinalizer: first argument is nil interface\n");
-	throw:
-		runtime_throw("runtime.SetFinalizer");
+		// runtimeÂprintf("runtime.SetFinalizer: first argument is nil interface\n");
+		goto throw;
 	}
 	if(obj.__type_descriptor->__code != GO_PTR) {
 		// runtime_printf("runtime.SetFinalizer: first argument is %S, not pointer\n", *obj.type->string);
@@ -458,19 +473,21 @@
 	}
 	ft = nil;
 	if(finalizer.__type_descriptor != nil) {
-		if(finalizer.__type_descriptor->__code != GO_FUNC) {
-		badfunc:
-			// runtime_printf("runtime.SetFinalizer: second argument is %S, not func(%S)\n", *finalizer.type->string, *obj.type->string);
-			goto throw;
-		}
+		if(finalizer.__type_descriptor->__code != GO_FUNC)
+			goto badfunc;
 		ft = (const FuncType*)finalizer.__type_descriptor;
 		if(ft->__dotdotdot || ft->__in.__count != 1 || !__go_type_descriptors_equal(*(Type**)ft->__in.__values, obj.__type_descriptor))
 			goto badfunc;
+	}
 
-		if(runtime_getfinalizer(obj.__object, 0)) {
-			// runtime_printf("runtime.SetFinalizer: finalizer already set");
-			goto throw;
-		}
+	if(!runtime_addfinalizer(obj.__object, finalizer.__type_descriptor != nil ? *(void**)finalizer.__object : nil, ft)) {
+		runtime_printf("runtime.SetFinalizer: finalizer already set\n");
+		goto throw;
 	}
-	runtime_addfinalizer(obj.__object, finalizer.__type_descriptor != nil ? *(void**)finalizer.__object : nil, ft);
+	return;
+
+badfunc:
+	// runtime_printf("runtime.SetFinalizer: second argument is %S, not func(%S)\n", *finalizer.type->string, *obj.type->string);
+throw:
+	runtime_throw("runtime.SetFinalizer");
 }
diff -r c36211271569 libgo/runtime/malloc.h
--- a/libgo/runtime/malloc.h	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/malloc.h	Wed Oct 26 16:12:38 2011 -0700
@@ -120,6 +120,13 @@
 #else
 	MHeapMap_Bits = 20,
 #endif
+
+	// Max number of threads to run garbage collection.
+	// 2, 3, and 4 are all plausible maximums depending
+	// on the hardware details of the machine.  The second
+	// proc is the one that helps the most (after the first),
+	// so start with just 2 for now.
+	MaxGcproc = 2,
 };
 
 // A generic linked list of blocks.  (Typically the block is bigger than sizeof(MLink).)
@@ -192,7 +199,7 @@
 	uint64	nlookup;	// number of pointer lookups
 	uint64	nmalloc;	// number of mallocs
 	uint64	nfree;  // number of frees
-	
+
 	// Statistics about malloc heap.
 	// protected by mheap.Lock
 	uint64	heap_alloc;	// bytes allocated and still in use
@@ -210,7 +217,7 @@
 	uint64	mcache_inuse;	// MCache structures
 	uint64	mcache_sys;
 	uint64	buckhash_sys;	// profiling bucket hash table
-	
+
 	// Statistics about garbage collector.
 	// Protected by stopping the world during GC.
 	uint64	next_gc;	// next GC (in heap_alloc time)
@@ -219,7 +226,7 @@
 	uint32	numgc;
 	bool	enablegc;
 	bool	debuggc;
-	
+
 	// Statistics about allocation size classes.
 	struct {
 		uint32 size;
@@ -240,7 +247,7 @@
 //
 // class_to_size[i] = largest size in class i
 // class_to_allocnpages[i] = number of pages to allocate when
-// 	making new objects in class i
+//	making new objects in class i
 // class_to_transfercount[i] = number of objects to move when
 //	taking a bunch of objects out of the central lists
 //	and putting them in the thread free list.
@@ -279,7 +286,7 @@
 		int64 nmalloc;
 		int64 nfree;
 	} local_by_size[NumSizeClasses];
-	
+
 };
 
 void*	runtime_MCache_Alloc(MCache *c, int32 sizeclass, uintptr size, int32 zeroed);
@@ -352,14 +359,14 @@
 	byte *arena_start;
 	byte *arena_used;
 	byte *arena_end;
-	
+
 	// central free lists for small size classes.
 	// the union makes sure that the MCentrals are
-	// spaced 64 bytes apart, so that each MCentral.Lock
+	// spaced CacheLineSize bytes apart, so that each MCentral.Lock
 	// gets its own cache line.
 	union {
 		MCentral;
-		byte pad[64];
+		byte pad[CacheLineSize];
 	} central[NumSizeClasses];
 
 	FixAlloc spanalloc;	// allocator for Span*
@@ -387,7 +394,7 @@
 void	runtime_markspan(void *v, uintptr size, uintptr n, bool leftover);
 void	runtime_unmarkspan(void *v, uintptr size);
 bool	runtime_blockspecial(void*);
-void	runtime_setblockspecial(void*);
+void	runtime_setblockspecial(void*, bool);
 void	runtime_purgecachedstats(M*);
 
 enum
@@ -402,6 +409,8 @@
 void	runtime_MProf_Malloc(void*, uintptr);
 void	runtime_MProf_Free(void*, uintptr);
 void	runtime_MProf_Mark(void (*scan)(byte *, int64));
+int32	runtime_helpgc(bool*);
+void	runtime_gchelper(void);
 
 // Malloc profiling settings.
 // Must match definition in extern.go.
@@ -412,13 +421,6 @@
 };
 extern int32 runtime_malloc_profile;
 
-typedef struct Finalizer Finalizer;
-struct Finalizer
-{
-	Finalizer *next;	// for use by caller of getfinalizer
-	void (*fn)(void*);
-	void *arg;
-	const struct __go_func_type *ft;
-};
-
-Finalizer*	runtime_getfinalizer(void*, bool);
+struct __go_func_type;
+bool	runtime_getfinalizer(void *p, bool del, void (**fn)(void*), const struct __go_func_type **ft);
+void	runtime_walkfintab(void (*fn)(void*), void (*scan)(byte*, int64));
diff -r c36211271569 libgo/runtime/mcache.c
--- a/libgo/runtime/mcache.c	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/mcache.c	Wed Oct 26 16:12:38 2011 -0700
@@ -7,6 +7,7 @@
 // See malloc.h for an overview.
 
 #include "runtime.h"
+#include "arch.h"
 #include "malloc.h"
 
 void*
diff -r c36211271569 libgo/runtime/mcentral.c
--- a/libgo/runtime/mcentral.c	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/mcentral.c	Wed Oct 26 16:12:38 2011 -0700
@@ -15,6 +15,7 @@
 // so that it is faster to move those lists between MCaches and MCentrals.
 
 #include "runtime.h"
+#include "arch.h"
 #include "malloc.h"
 
 static bool MCentral_Grow(MCentral *c);
diff -r c36211271569 libgo/runtime/mem.c
--- a/libgo/runtime/mem.c	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/mem.c	Wed Oct 26 16:12:38 2011 -0700
@@ -2,6 +2,7 @@
 #include <unistd.h>
 
 #include "runtime.h"
+#include "arch.h"
 #include "malloc.h"
 
 #ifndef MAP_ANON
diff -r c36211271569 libgo/runtime/mem_posix_memalign.c
--- a/libgo/runtime/mem_posix_memalign.c	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/mem_posix_memalign.c	Wed Oct 26 16:12:38 2011 -0700
@@ -1,6 +1,7 @@
 #include <errno.h>
 
 #include "runtime.h"
+#include "arch.h"
 #include "malloc.h"
 
 void*
diff -r c36211271569 libgo/runtime/mfinal.c
--- a/libgo/runtime/mfinal.c	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/mfinal.c	Wed Oct 26 16:12:38 2011 -0700
@@ -3,18 +3,17 @@
 // license that can be found in the LICENSE file.
 
 #include "runtime.h"
+#include "arch.h"
 #include "malloc.h"
 
-// Lock to protect finalizer data structures.
-// Cannot reuse mheap.Lock because the finalizer
-// maintenance requires allocation.
-static Lock finlock;
+enum { debug = 0 };
 
-void
-runtime_initfintab()
+typedef struct Fin Fin;
+struct Fin
 {
-	runtime_initlock(&finlock);
-}
+	void (*fn)(void*);
+	const struct __go_func_type *ft;
+};
 
 // Finalizer hash table.  Direct hash, linear scan, at most 3/4 full.
 // Table size is power of 3 so that hash can be key % max.
@@ -26,25 +25,43 @@
 typedef struct Fintab Fintab;
 struct Fintab
 {
-	void **key;
-	Finalizer **val;
+	Lock;
+	void **fkey;
+	Fin *val;
 	int32 nkey;	// number of non-nil entries in key
 	int32 ndead;	// number of dead (-1) entries in key
 	int32 max;	// size of key, val allocations
 };
 
+#define TABSZ 17
+#define TAB(p) (&fintab[((uintptr)(p)>>3)%TABSZ])
+
+static struct {
+	Fintab;
+	uint8 pad[0 /* CacheLineSize - sizeof(Fintab) */];	
+} fintab[TABSZ];
+
+void
+runtime_initfintab()
+{
+	int32 i;
+
+	for(i=0; i<TABSZ; i++)
+		runtime_initlock(&fintab[i]);
+}
+
 static void
-addfintab(Fintab *t, void *k, Finalizer *v)
+addfintab(Fintab *t, void *k, void (*fn)(void*), const struct __go_func_type *ft)
 {
 	int32 i, j;
 
 	i = (uintptr)k % (uintptr)t->max;
 	for(j=0; j<t->max; j++) {
-		if(t->key[i] == nil) {
+		if(t->fkey[i] == nil) {
 			t->nkey++;
 			goto ret;
 		}
-		if(t->key[i] == (void*)-1) {
+		if(t->fkey[i] == (void*)-1) {
 			t->ndead--;
 			goto ret;
 		}
@@ -56,30 +73,32 @@
 	runtime_throw("finalizer table inconsistent");
 
 ret:
-	t->key[i] = k;
-	t->val[i] = v;
+	t->fkey[i] = k;
+	t->val[i].fn = fn;
+	t->val[i].ft = ft;
 }
 
-static Finalizer*
-lookfintab(Fintab *t, void *k, bool del)
+static bool
+lookfintab(Fintab *t, void *k, bool del, Fin *f)
 {
 	int32 i, j;
-	Finalizer *v;
 
 	if(t->max == 0)
-		return nil;
+		return false;
 	i = (uintptr)k % (uintptr)t->max;
 	for(j=0; j<t->max; j++) {
-		if(t->key[i] == nil)
-			return nil;
-		if(t->key[i] == k) {
-			v = t->val[i];
+		if(t->fkey[i] == nil)
+			return false;
+		if(t->fkey[i] == k) {
+			if(f)
+				*f = t->val[i];
 			if(del) {
-				t->key[i] = (void*)-1;
-				t->val[i] = nil;
+				t->fkey[i] = (void*)-1;
+				t->val[i].fn = nil;
+				t->val[i].ft = nil;
 				t->ndead++;
 			}
-			return v;
+			return true;
 		}
 		if(++i == t->max)
 			i = 0;
@@ -87,108 +106,123 @@
 
 	// cannot happen - table is known to be non-full
 	runtime_throw("finalizer table inconsistent");
-	return nil;
+	return false;
 }
 
-static Fintab fintab;
+static void
+resizefintab(Fintab *tab)
+{
+	Fintab newtab;
+	void *k;
+	int32 i;
 
-// add finalizer; caller is responsible for making sure not already in table
-void
+	runtime_memclr((byte*)&newtab, sizeof newtab);
+	newtab.max = tab->max;
+	if(newtab.max == 0)
+		newtab.max = 3*3*3;
+	else if(tab->ndead < tab->nkey/2) {
+		// grow table if not many dead values.
+		// otherwise just rehash into table of same size.
+		newtab.max *= 3;
+	}
+	
+	newtab.fkey = runtime_mallocgc(newtab.max*sizeof newtab.fkey[0], FlagNoPointers, 0, 1);
+	newtab.val = runtime_mallocgc(newtab.max*sizeof newtab.val[0], 0, 0, 1);
+	
+	for(i=0; i<tab->max; i++) {
+		k = tab->fkey[i];
+		if(k != nil && k != (void*)-1)
+			addfintab(&newtab, k, tab->val[i].fn, tab->val[i].ft);
+	}
+	
+	runtime_free(tab->fkey);
+	runtime_free(tab->val);
+	
+	tab->fkey = newtab.fkey;
+	tab->val = newtab.val;
+	tab->nkey = newtab.nkey;
+	tab->ndead = newtab.ndead;
+	tab->max = newtab.max;
+}
+
+bool
 runtime_addfinalizer(void *p, void (*f)(void*), const struct __go_func_type *ft)
 {
-	Fintab newtab;
-	int32 i;
+	Fintab *tab;
 	byte *base;
-	Finalizer *e;
+	bool ret = false;
 	
-	e = nil;
-	if(f != nil) {
-		e = runtime_mal(sizeof *e);
-		e->fn = f;
-		e->ft = ft;
+	if(debug) {
+		if(!runtime_mlookup(p, &base, nil, nil) || p != base)
+			runtime_throw("addfinalizer on invalid pointer");
 	}
-
+	
 	if(!__sync_bool_compare_and_swap(&m->holds_finlock, 0, 1))
 		runtime_throw("finalizer deadlock");
 
-	runtime_lock(&finlock);
-	if(!runtime_mlookup(p, &base, nil, nil) || p != base) {
-		runtime_unlock(&finlock);
-		__sync_bool_compare_and_swap(&m->holds_finlock, 1, 0);
-		runtime_throw("addfinalizer on invalid pointer");
-	}
+	tab = TAB(p);
+	runtime_lock(tab);
 	if(f == nil) {
-		lookfintab(&fintab, p, 1);
+		if(lookfintab(tab, p, true, nil))
+			runtime_setblockspecial(p, false);
+		ret = true;
 		goto unlock;
 	}
 
-	if(lookfintab(&fintab, p, 0)) {
-		runtime_unlock(&finlock);
-		__sync_bool_compare_and_swap(&m->holds_finlock, 1, 0);
-		runtime_throw("double finalizer");
+	if(lookfintab(tab, p, false, nil)) {
+		ret = false;
+		goto unlock;
 	}
-	runtime_setblockspecial(p);
 
-	if(fintab.nkey >= fintab.max/2+fintab.max/4) {
+	if(tab->nkey >= tab->max/2+tab->max/4) {
 		// keep table at most 3/4 full:
 		// allocate new table and rehash.
-
-		runtime_memclr((byte*)&newtab, sizeof newtab);
-		newtab.max = fintab.max;
-		if(newtab.max == 0)
-			newtab.max = 3*3*3;
-		else if(fintab.ndead < fintab.nkey/2) {
-			// grow table if not many dead values.
-			// otherwise just rehash into table of same size.
-			newtab.max *= 3;
-		}
-
-		newtab.key = runtime_mallocgc(newtab.max*sizeof newtab.key[0], FlagNoPointers, 0, 1);
-		newtab.val = runtime_mallocgc(newtab.max*sizeof newtab.val[0], 0, 0, 1);
-
-		for(i=0; i<fintab.max; i++) {
-			void *k;
-
-			k = fintab.key[i];
-			if(k != nil && k != (void*)-1)
-				addfintab(&newtab, k, fintab.val[i]);
-		}
-		runtime_free(fintab.key);
-		runtime_free(fintab.val);
-		fintab = newtab;
+		resizefintab(tab);
 	}
 
-	addfintab(&fintab, p, e);
+	addfintab(tab, p, f, ft);
+	runtime_setblockspecial(p, true);
+	ret = true;
+
  unlock:
-	runtime_unlock(&finlock);
+	runtime_unlock(tab);
 
 	__sync_bool_compare_and_swap(&m->holds_finlock, 1, 0);
 
 	if(__sync_bool_compare_and_swap(&m->gcing_for_finlock, 1, 0)) {
 		__go_run_goroutine_gc(200);
 	}
+
+	return ret;
 }
 
 // get finalizer; if del, delete finalizer.
-// caller is responsible for updating RefHasFinalizer bit.
-Finalizer*
-runtime_getfinalizer(void *p, bool del)
+// caller is responsible for updating RefHasFinalizer (special) bit.
+bool
+runtime_getfinalizer(void *p, bool del, void (**fn)(void*), const struct __go_func_type **ft)
 {
-	Finalizer *f;
+	Fintab *tab;
+	bool res;
+	Fin f;
 	
 	if(!__sync_bool_compare_and_swap(&m->holds_finlock, 0, 1))
 		runtime_throw("finalizer deadlock");
 
-	runtime_lock(&finlock);
-	f = lookfintab(&fintab, p, del);
-	runtime_unlock(&finlock);
+	tab = TAB(p);
+	runtime_lock(tab);
+	res = lookfintab(tab, p, del, &f);
+	runtime_unlock(tab);
 
 	__sync_bool_compare_and_swap(&m->holds_finlock, 1, 0);
 	if(__sync_bool_compare_and_swap(&m->gcing_for_finlock, 1, 0)) {
 		__go_run_goroutine_gc(201);
 	}
 
-	return f;
+	if(res==false)
+		return false;
+	*fn = f.fn;
+	*ft = f.ft;
+	return true;
 }
 
 void
@@ -196,18 +230,22 @@
 {
 	void **key;
 	void **ekey;
+	int32 i;
 
 	if(!__sync_bool_compare_and_swap(&m->holds_finlock, 0, 1))
 		runtime_throw("finalizer deadlock");
 
-	scan((byte*)&fintab, sizeof fintab);
-	runtime_lock(&finlock);
-	key = fintab.key;
-	ekey = key + fintab.max;
-	for(; key < ekey; key++)
-		if(*key != nil && *key != ((void*)-1))
-			fn(*key);
-	runtime_unlock(&finlock);
+	for(i=0; i<TABSZ; i++) {
+		runtime_lock(&fintab[i]);
+		key = fintab[i].fkey;
+		ekey = key + fintab[i].max;
+		for(; key < ekey; key++)
+			if(*key != nil && *key != ((void*)-1))
+				fn(*key);
+		scan((byte*)&fintab[i].fkey, sizeof(void*));
+		scan((byte*)&fintab[i].val, sizeof(void*));
+		runtime_unlock(&fintab[i]);
+	}
 
 	__sync_bool_compare_and_swap(&m->holds_finlock, 1, 0);
 	if(__sync_bool_compare_and_swap(&m->gcing_for_finlock, 1, 0)) {
diff -r c36211271569 libgo/runtime/mfixalloc.c
--- a/libgo/runtime/mfixalloc.c	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/mfixalloc.c	Wed Oct 26 16:12:38 2011 -0700
@@ -7,6 +7,7 @@
 // See malloc.h for overview.
 
 #include "runtime.h"
+#include "arch.h"
 #include "malloc.h"
 
 // Initialize f to allocate objects of the given size,
diff -r c36211271569 libgo/runtime/mgc0.c
--- a/libgo/runtime/mgc0.c	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/mgc0.c	Wed Oct 26 16:12:38 2011 -0700
@@ -5,13 +5,14 @@
 // Garbage collector.
 
 #include "runtime.h"
+#include "arch.h"
 #include "malloc.h"
 
 enum {
 	Debug = 0,
-	UseCas = 1,
 	PtrSize = sizeof(void*),
-	
+	DebugMark = 0,  // run second pass to check mark
+
 	// Four bits per word (see #defines below).
 	wordsPerBitmapWord = sizeof(void*)*8/4,
 	bitShift = sizeof(void*)*8/4,
@@ -50,28 +51,72 @@
 
 #define bitMask (bitBlockBoundary | bitAllocated | bitMarked | bitSpecial)
 
+// TODO: Make these per-M.
 static uint64 nlookup;
 static uint64 nsizelookup;
 static uint64 naddrlookup;
+static uint64 nhandoff;
+
 static int32 gctrace;
 
 typedef struct Workbuf Workbuf;
 struct Workbuf
 {
 	Workbuf *next;
-	uintptr nw;
-	byte *w[2048-2];
+	uintptr nobj;
+	byte *obj[512-2];
+};
+
+typedef struct Finalizer Finalizer;
+struct Finalizer
+{
+	void (*fn)(void*);
+	void *arg;
+	const struct __go_func_type *ft;
+};
+
+typedef struct FinBlock FinBlock;
+struct FinBlock
+{
+	FinBlock *alllink;
+	FinBlock *next;
+	int32 cnt;
+	int32 cap;
+	Finalizer fin[1];
 };
 
 static bool finstarted;
 static pthread_mutex_t finqlock = PTHREAD_MUTEX_INITIALIZER;
 static pthread_cond_t finqcond = PTHREAD_COND_INITIALIZER;
-static Finalizer *finq;
+static FinBlock *finq; // list of finalizers that are to be executed
+static FinBlock *finc; // cache of free blocks
+static FinBlock *allfin; // list of all blocks
+static Lock finlock;
 static int32 fingwait;
 
 static void runfinq(void*);
 static Workbuf* getempty(Workbuf*);
 static Workbuf* getfull(Workbuf*);
+static void	putempty(Workbuf*);
+static Workbuf* handoff(Workbuf*);
+
+static struct {
+	Lock fmu;
+	Workbuf	*full;
+	Lock emu;
+	Workbuf	*empty;
+	uint32	nproc;
+	volatile uint32	nwait;
+	volatile uint32	ndone;
+	Note	alldone;
+	Lock	markgate;
+	Lock	sweepgate;
+	MSpan	*spans;
+
+	Lock;
+	byte	*chunk;
+	uintptr	nchunk;
+} work;
 
 // scanblock scans a block of n bytes starting at pointer b for references
 // to other objects, scanning any it finds recursively until there are no
@@ -82,13 +127,14 @@
 static void
 scanblock(byte *b, int64 n)
 {
-	byte *obj, *arena_start, *p;
+	byte *obj, *arena_start, *arena_used, *p;
 	void **vp;
-	uintptr size, *bitp, bits, shift, i, j, x, xbits, off;
+	uintptr size, *bitp, bits, shift, i, j, x, xbits, off, nobj, nproc;
 	MSpan *s;
 	PageID k;
-	void **bw, **w, **ew;
+	void **wp;
 	Workbuf *wbuf;
+	bool keepworking;
 
 	if((int64)(uintptr)n != n || n < 0) {
 		// runtime_printf("scanblock %p %lld\n", b, (long long)n);
@@ -97,11 +143,19 @@
 
 	// Memory arena parameters.
 	arena_start = runtime_mheap.arena_start;
-	
+	arena_used = runtime_mheap.arena_used;
+	nproc = work.nproc;
+
 	wbuf = nil;  // current work buffer
-	ew = nil;  // end of work buffer
-	bw = nil;  // beginning of work buffer
-	w = nil;  // current pointer into work buffer
+	wp = nil;  // storage for next queued pointer (write pointer)
+	nobj = 0;  // number of queued objects
+
+	// Scanblock helpers pass b==nil.
+	// The main proc needs to return to make more
+	// calls to scanblock.  But if work.nproc==1 then
+	// might as well process blocks as soon as we
+	// have them.
+	keepworking = b == nil || work.nproc == 1;
 
 	// Align b to a word boundary.
 	off = (uintptr)b & (PtrSize-1);
@@ -117,17 +171,17 @@
 			runtime_printf("scanblock %p %lld\n", b, (long long) n);
 
 		vp = (void**)b;
-		n /= PtrSize;
+		n >>= (2+PtrSize/8);  /* n /= PtrSize (4 or 8) */
 		for(i=0; i<(uintptr)n; i++) {
 			obj = (byte*)vp[i];
-			
+
 			// Words outside the arena cannot be pointers.
-			if((byte*)obj < arena_start || (byte*)obj >= runtime_mheap.arena_used)
+			if((byte*)obj < arena_start || (byte*)obj >= arena_used)
 				continue;
-			
+
 			// obj may be a pointer to a live object.
 			// Try to find the beginning of the object.
-			
+
 			// Round down to word boundary.
 			obj = (void*)((uintptr)obj & ~((uintptr)PtrSize-1));
 
@@ -185,47 +239,72 @@
 		found:
 			// Now we have bits, bitp, and shift correct for
 			// obj pointing at the base of the object.
-			// If not allocated or already marked, done.
-			if((bits & bitAllocated) == 0 || (bits & bitMarked) != 0)
+			// Only care about allocated and not marked.
+			if((bits & (bitAllocated|bitMarked)) != bitAllocated)
 				continue;
-			*bitp |= bitMarked<<shift;
+			if(nproc == 1)
+				*bitp |= bitMarked<<shift;
+			else {
+				for(;;) {
+					x = *bitp;
+					if(x & (bitMarked<<shift))
+						goto continue_obj;
+					if(runtime_casp((void**)bitp, (void*)x, (void*)(x|(bitMarked<<shift))))
+						break;
+				}
+			}
 
 			// If object has no pointers, don't need to scan further.
 			if((bits & bitNoPointers) != 0)
 				continue;
 
+			// If another proc wants a pointer, give it some.
+			if(nobj > 4 && work.nwait > 0 && work.full == nil) {
+				wbuf->nobj = nobj;
+				wbuf = handoff(wbuf);
+				nobj = wbuf->nobj;
+				wp = (void**)(wbuf->obj + nobj);
+			}
+
 			// If buffer is full, get a new one.
-			if(w >= ew) {
+			if(wbuf == nil || nobj >= nelem(wbuf->obj)) {
+				if(wbuf != nil)
+					wbuf->nobj = nobj;
 				wbuf = getempty(wbuf);
-				bw = (void**)wbuf->w;
-				w = bw;
-				ew = bw + nelem(wbuf->w);
+				wp = (void**)(wbuf->obj);
+				nobj = 0;
 			}
-			*w++ = obj;
+			*wp++ = obj;
+			nobj++;
+		continue_obj:;
 		}
-		
+
 		// Done scanning [b, b+n).  Prepare for the next iteration of
 		// the loop by setting b and n to the parameters for the next block.
 
-		// Fetch b from the work buffers.
-		if(w <= bw) {
+		// Fetch b from the work buffer.
+		if(nobj == 0) {
+			if(!keepworking) {
+				putempty(wbuf);
+				return;
+			}
 			// Emptied our buffer: refill.
 			wbuf = getfull(wbuf);
 			if(wbuf == nil)
-				break;
-			bw = (void**)wbuf->w;
-			ew = (void**)(wbuf->w + nelem(wbuf->w));
-			w = bw+wbuf->nw;
+				return;
+			nobj = wbuf->nobj;
+			wp = (void**)(wbuf->obj + wbuf->nobj);
 		}
-		b = *--w;
-	
+		b = *--wp;
+		nobj--;
+
 		// Figure out n = size of b.  Start by loading bits for b.
 		off = (uintptr*)b - (uintptr*)arena_start;
 		bitp = (uintptr*)arena_start - off/wordsPerBitmapWord - 1;
 		shift = off % wordsPerBitmapWord;
 		xbits = *bitp;
 		bits = xbits >> shift;
-		
+
 		// Might be small; look for nearby block boundary.
 		// A block boundary is marked by either bitBlockBoundary
 		// or bitAllocated being set (see notes near their definition).
@@ -244,12 +323,12 @@
 		// apply a mask to keep only the bits corresponding
 		// to shift+j < bitShift aka j < bitShift-shift.
 		bits &= (boundary<<(bitShift-shift)) - boundary;
-		
+
 		// A block boundary j words before b is indicated by
 		//	xbits>>(shift-j) & boundary
 		// (assuming shift >= j).  There is no cleverness here
 		// avoid the test, because when j gets too large the shift
-		// turns negative, which is undefined in C.		
+		// turns negative, which is undefined in C.
 
 		for(j=1; j<bitShift; j++) {
 			if(((bits>>j)&boundary) != 0 || (shift>=j && ((xbits>>(shift-j))&boundary) != 0)) {
@@ -257,7 +336,7 @@
 				goto scan;
 			}
 		}
-		
+
 		// Fall back to asking span about size class.
 		// (Manually inlined copy of MHeap_Lookup.)
 		nlookup++;
@@ -274,29 +353,123 @@
 	}
 }
 
-static struct {
-	Workbuf	*full;
-	Workbuf	*empty;
-	byte	*chunk;
-	uintptr	nchunk;
-} work;
+// debug_scanblock is the debug copy of scanblock.
+// it is simpler, slower, single-threaded, recursive,
+// and uses bitSpecial as the mark bit.
+static void
+debug_scanblock(byte *b, int64 n)
+{
+	byte *obj, *p;
+	void **vp;
+	uintptr size, *bitp, bits, shift, i, xbits, off;
+	MSpan *s;
+
+	if(!DebugMark)
+		runtime_throw("debug_scanblock without DebugMark");
+
+	if((int64)(uintptr)n != n || n < 0) {
+		//runtime_printf("debug_scanblock %p %D\n", b, n);
+		runtime_throw("debug_scanblock");
+	}
+
+	// Align b to a word boundary.
+	off = (uintptr)b & (PtrSize-1);
+	if(off != 0) {
+		b += PtrSize - off;
+		n -= PtrSize - off;
+	}
+
+	vp = (void**)b;
+	n /= PtrSize;
+	for(i=0; i<(uintptr)n; i++) {
+		obj = (byte*)vp[i];
+
+		// Words outside the arena cannot be pointers.
+		if((byte*)obj < runtime_mheap.arena_start || (byte*)obj >= runtime_mheap.arena_used)
+			continue;
+
+		// Round down to word boundary.
+		obj = (void*)((uintptr)obj & ~((uintptr)PtrSize-1));
+
+		// Consult span table to find beginning.
+		s = runtime_MHeap_LookupMaybe(&runtime_mheap, obj);
+		if(s == nil)
+			continue;
+
+
+		p =  (byte*)((uintptr)s->start<<PageShift);
+		if(s->sizeclass == 0) {
+			obj = p;
+			size = (uintptr)s->npages<<PageShift;
+		} else {
+			if((byte*)obj >= (byte*)s->limit)
+				continue;
+			size = runtime_class_to_size[s->sizeclass];
+			int32 i = ((byte*)obj - p)/size;
+			obj = p+i*size;
+		}
+
+		// Now that we know the object header, reload bits.
+		off = (uintptr*)obj - (uintptr*)runtime_mheap.arena_start;
+		bitp = (uintptr*)runtime_mheap.arena_start - off/wordsPerBitmapWord - 1;
+		shift = off % wordsPerBitmapWord;
+		xbits = *bitp;
+		bits = xbits >> shift;
+
+		// Now we have bits, bitp, and shift correct for
+		// obj pointing at the base of the object.
+		// If not allocated or already marked, done.
+		if((bits & bitAllocated) == 0 || (bits & bitSpecial) != 0)  // NOTE: bitSpecial not bitMarked
+			continue;
+		*bitp |= bitSpecial<<shift;
+		if(!(bits & bitMarked))
+			runtime_printf("found unmarked block %p in %p\n", obj, vp+i);
+
+		// If object has no pointers, don't need to scan further.
+		if((bits & bitNoPointers) != 0)
+			continue;
+
+		debug_scanblock(obj, size);
+	}
+}
 
 // Get an empty work buffer off the work.empty list,
 // allocating new buffers as needed.
 static Workbuf*
 getempty(Workbuf *b)
 {
-	if(b != nil) {
-		b->nw = nelem(b->w);
-		b->next = work.full;
-		work.full = b;
+	if(work.nproc == 1) {
+		// Put b on full list.
+		if(b != nil) {
+			b->next = work.full;
+			work.full = b;
+		}
+		// Grab from empty list if possible.
+		b = work.empty;
+		if(b != nil) {
+			work.empty = b->next;
+			goto haveb;
+		}
+	} else {
+		// Put b on full list.
+		if(b != nil) {
+			runtime_lock(&work.fmu);
+			b->next = work.full;
+			work.full = b;
+			runtime_unlock(&work.fmu);
+		}
+		// Grab from empty list if possible.
+		runtime_lock(&work.emu);
+		b = work.empty;
+		if(b != nil)
+			work.empty = b->next;
+		runtime_unlock(&work.emu);
+		if(b != nil)
+			goto haveb;
 	}
-	b = work.empty;
-	if(b != nil) {
-		work.empty = b->next;
-		return b;
-	}
-	
+
+	// Need to allocate.
+	runtime_lock(&work);
 	if(work.nchunk < sizeof *b) {
 		work.nchunk = 1<<20;
 		work.chunk = runtime_SysAlloc(work.nchunk);
@@ -304,25 +477,121 @@
 	b = (Workbuf*)work.chunk;
 	work.chunk += sizeof *b;
 	work.nchunk -= sizeof *b;
+	runtime_unlock(&work);
+
+haveb:
+	b->nobj = 0;
 	return b;
 }
 
+static void
+putempty(Workbuf *b)
+{
+	if(b == nil)
+		return;
+
+	if(work.nproc == 1) {
+		b->next = work.empty;
+		work.empty = b;
+		return;
+	}
+
+	runtime_lock(&work.emu);
+	b->next = work.empty;
+	work.empty = b;
+	runtime_unlock(&work.emu);
+}
+
 // Get a full work buffer off the work.full list, or return nil.
 static Workbuf*
 getfull(Workbuf *b)
 {
-	if(b != nil) {
-		b->nw = 0;
-		b->next = work.empty;
-		work.empty = b;
+	int32 i;
+	Workbuf *b1;
+
+	if(work.nproc == 1) {
+		// Put b on empty list.
+		if(b != nil) {
+			b->next = work.empty;
+			work.empty = b;
+		}
+		// Grab from full list if possible.
+		// Since work.nproc==1, no one else is
+		// going to give us work.
+		b = work.full;
+		if(b != nil)
+			work.full = b->next;
+		return b;
 	}
-	b = work.full;
-	if(b != nil)
-		work.full = b->next;
-	return b;
+
+	putempty(b);
+
+	// Grab buffer from full list if possible.
+	for(;;) {
+		b1 = work.full;
+		if(b1 == nil)
+			break;
+		runtime_lock(&work.fmu);
+		if(work.full != nil) {
+			b1 = work.full;
+			work.full = b1->next;
+			runtime_unlock(&work.fmu);
+			return b1;
+		}
+		runtime_unlock(&work.fmu);
+	}
+
+	runtime_xadd(&work.nwait, +1);
+	for(i=0;; i++) {
+		b1 = work.full;
+		if(b1 != nil) {
+			runtime_lock(&work.fmu);
+			if(work.full != nil) {
+				runtime_xadd(&work.nwait, -1);
+				b1 = work.full;
+				work.full = b1->next;
+				runtime_unlock(&work.fmu);
+				return b1;
+			}
+			runtime_unlock(&work.fmu);
+			continue;
+		}
+		if(work.nwait == work.nproc)
+			return nil;
+		if(i < 10)
+			runtime_procyield(20);
+		else if(i < 20)
+			runtime_osyield();
+		else
+			runtime_usleep(100);
+	}
 }
 
-// Scanstack calls scanblock on each of gp's stack segments.
+static Workbuf*
+handoff(Workbuf *b)
+{
+	int32 n;
+	Workbuf *b1;
+
+	// Make new buffer with half of b's pointers.
+	b1 = getempty(nil);
+	n = b->nobj/2;
+	b->nobj -= n;
+	b1->nobj = n;
+	runtime_memmove(b1->obj, b->obj+b->nobj, n*sizeof b1->obj[0]);
+	nhandoff += n;
+
+	// Put b on full list - let first half of b get stolen.
+	runtime_lock(&work.fmu);
+	b->next = work.full;
+	work.full = b;
+	runtime_unlock(&work.fmu);
+
+	return b1;
+}
+
+// Markfin calls scanblock on the blocks that have finalizers:
+// the things pointed at cannot be freed until the finalizers have run.
 static void
 markfin(void *v)
 {
@@ -355,11 +624,22 @@
 	roots = r;
 }
 
-// Mark 
 static void
-mark(void)
+debug_markfin(void *v)
+{
+	uintptr size;
+
+	if(!runtime_mlookup(v, (byte**)&v, &size, nil))
+		runtime_throw("debug_mark - finalizer inconsistency");
+	debug_scanblock(v, size);
+}
+
+// Mark
+static void
+mark(void (*scan)(byte*, int64))
 {
 	struct root_list *pl;
+	FinBlock *fb;
 
 	for(pl = roots; pl != nil; pl = pl->next) {
 		struct root* pr = &pl->roots[0];
@@ -372,18 +652,63 @@
 		}
 	}
 
-	scanblock((byte*)&m0, sizeof m0);
-	scanblock((byte*)&finq, sizeof finq);
-	runtime_MProf_Mark(scanblock);
+	scan((byte*)&m0, sizeof m0);
+	scan((byte*)&finq, sizeof finq);
+	runtime_MProf_Mark(scan);
 
 	// mark stacks
-	__go_scanstacks(scanblock);
+	__go_scanstacks(scan);
 
 	// mark things pointed at by objects with finalizers
-	runtime_walkfintab(markfin, scanblock);
+	if(scan == debug_scanblock)
+		runtime_walkfintab(debug_markfin, scan);
+	else
+		runtime_walkfintab(markfin, scan);
+
+	for(fb=allfin; fb; fb=fb->alllink)
+		scanblock((byte*)fb->fin, fb->cnt*sizeof(fb->fin[0]));
+
+	// in multiproc mode, join in the queued work.
+	scan(nil, 0);
 }
 
-// Sweep frees or calls finalizers for blocks not marked in the mark phase.
+static bool
+handlespecial(byte *p, uintptr size)
+{
+	void (*fn)(void*);
+	const struct __go_func_type *ft;
+	FinBlock *block;
+	Finalizer *f;
+	
+	if(!runtime_getfinalizer(p, true, &fn, &ft)) {
+		runtime_setblockspecial(p, false);
+		runtime_MProf_Free(p, size);
+		return false;
+	}
+
+	runtime_lock(&finlock);
+	if(finq == nil || finq->cnt == finq->cap) {
+		if(finc == nil) {
+			finc = runtime_SysAlloc(PageSize);
+			finc->cap = (PageSize - sizeof(FinBlock)) / sizeof(Finalizer) + 1;
+			finc->alllink = allfin;
+			allfin = finc;
+		}
+		block = finc;
+		finc = block->next;
+		block->next = finq;
+		finq = block;
+	}
+	f = &finq->fin[finq->cnt];
+	finq->cnt++;
+	f->fn = fn;
+	f->ft = ft;
+	f->arg = p;
+	runtime_unlock(&finlock); 
+	return true;
+}
+
+// Sweep frees or collects finalizers for blocks not marked in the mark phase.
 // It clears the mark bits in preparation for the next GC round.
 static void
 sweep(void)
@@ -393,9 +718,17 @@
 	uintptr size;
 	byte *p;
 	MCache *c;
-	Finalizer *f;
+	byte *arena_start;
 
-	for(s = runtime_mheap.allspans; s != nil; s = s->allnext) {
+	arena_start = runtime_mheap.arena_start;
+
+	for(;;) {
+		s = work.spans;
+		if(s == nil)
+			break;
+		if(!runtime_casp(&work.spans, s, s->allnext))
+			continue;
+
 		if(s->state != MSpanInUse)
 			continue;
 
@@ -410,13 +743,15 @@
 			npages = runtime_class_to_allocnpages[cl];
 			n = (npages << PageShift) / size;
 		}
-	
-		// sweep through n objects of given size starting at p.
+
+		// Sweep through n objects of given size starting at p.
+		// This thread owns the span now, so it can manipulate
+		// the block bitmap without atomic operations.
 		for(; n > 0; n--, p += size) {
 			uintptr off, *bitp, shift, bits;
 
-			off = (uintptr*)p - (uintptr*)runtime_mheap.arena_start;
-			bitp = (uintptr*)runtime_mheap.arena_start - off/wordsPerBitmapWord - 1;
+			off = (uintptr*)p - (uintptr*)arena_start;
+			bitp = (uintptr*)arena_start - off/wordsPerBitmapWord - 1;
 			shift = off % wordsPerBitmapWord;
 			bits = *bitp>>shift;
 
@@ -424,20 +759,21 @@
 				continue;
 
 			if((bits & bitMarked) != 0) {
+				if(DebugMark) {
+					if(!(bits & bitSpecial))
+						runtime_printf("found spurious mark on %p\n", p);
+					*bitp &= ~(bitSpecial<<shift);
+				}
 				*bitp &= ~(bitMarked<<shift);
 				continue;
 			}
 
-			if((bits & bitSpecial) != 0) {
-				// Special means it has a finalizer or is being profiled.
-				f = runtime_getfinalizer(p, 1);
-				if(f != nil) {
-					f->arg = p;
-					f->next = finq;
-					finq = f;
+			// Special means it has a finalizer or is being profiled.
+			// In DebugMark mode, the bit has been coopted so
+			// we have to assume all blocks are special.
+			if(DebugMark || (bits & bitSpecial) != 0) {
+				if(handlespecial(p, size))
 					continue;
-				}
-				runtime_MProf_Free(p, size);
 			}
 
 			// Mark freed; restore block boundary bit.
@@ -464,6 +800,23 @@
 
 static pthread_mutex_t gcsema = PTHREAD_MUTEX_INITIALIZER;
 
+void
+runtime_gchelper(void)
+{
+	// Wait until main proc is ready for mark help.
+	runtime_lock(&work.markgate);
+	runtime_unlock(&work.markgate);
+	scanblock(nil, 0);
+
+	// Wait until main proc is ready for sweep help.
+	runtime_lock(&work.sweepgate);
+	runtime_unlock(&work.sweepgate);
+	sweep();
+
+	if(runtime_xadd(&work.ndone, +1) == work.nproc-1)
+		runtime_notewakeup(&work.alldone);
+}
+
 // Initialized from $GOGC.  GOGC=off means no gc.
 //
 // Next gc is after we've allocated an extra amount of
@@ -481,7 +834,7 @@
 	int64 t0, t1, t2, t3;
 	uint64 heap0, heap1, obj0, obj1;
 	char *p;
-	Finalizer *fp;
+	bool extra;
 
 	// The gc is turned off (via enablegc) until
 	// the bootstrap has completed.
@@ -502,10 +855,16 @@
 			gcpercent = -1;
 		else
 			gcpercent = runtime_atoi(p);
-		
+
 		p = runtime_getenv("GOGCTRACE");
 		if(p != nil)
 			gctrace = runtime_atoi(p);
+
+		runtime_initlock(&work.fmu);
+		runtime_initlock(&work.emu);
+		runtime_initlock(&work.markgate);
+		runtime_initlock(&work.sweepgate);
+		runtime_initlock(&work.Lock);
 	}
 	if(gcpercent < 0)
 		return;
@@ -522,20 +881,42 @@
 	nlookup = 0;
 	nsizelookup = 0;
 	naddrlookup = 0;
+	nhandoff = 0;
 
 	m->gcing = 1;
 	runtime_stoptheworld();
-	if(runtime_mheap.Lock.key != 0)
-		runtime_throw("runtime_mheap locked during gc");
 
 	__go_cachestats();
 	heap0 = mstats.heap_alloc;
 	obj0 = mstats.nmalloc - mstats.nfree;
 
-	mark();
+	runtime_lock(&work.markgate);
+	runtime_lock(&work.sweepgate);
+
+	extra = false;
+	work.nproc = 1;
+#if 0
+	if(runtime_gomaxprocs > 1 && runtime_ncpu > 1) {
+		runtime_noteclear(&work.alldone);
+		work.nproc += runtime_helpgc(&extra);
+	}
+#endif
+	work.nwait = 0;
+	work.ndone = 0;
+
+	runtime_unlock(&work.markgate);  // let the helpers in
+	mark(scanblock);
+	if(DebugMark)
+		mark(debug_scanblock);
 	t1 = runtime_nanotime();
+
+	work.spans = runtime_mheap.allspans;
+	runtime_unlock(&work.sweepgate);  // let the helpers in
 	sweep();
+	if(work.nproc > 1)
+		runtime_notesleep(&work.alldone);
 	t2 = runtime_nanotime();
+
 	__go_stealcache();
 	__go_cachestats();
 
@@ -553,21 +934,28 @@
 	mstats.numgc++;
 	if(mstats.debuggc)
 		runtime_printf("pause %llu\n", (unsigned long long)t3-t0);
-	
+
 	if(gctrace) {
-		runtime_printf("gc%d: %llu+%llu+%llu ms %llu -> %llu MB %llu -> %llu (%llu-%llu) objects %llu pointer lookups (%llu size, %llu addr)\n",
+		runtime_printf("gc%d: %llu+%llu+%llu ms %llu -> %llu MB %llu -> %llu (%llu-%llu) objects %llu pointer lookups (%llu size, %llu addr) %llu handoff\n",
 			mstats.numgc, (unsigned long long)(t1-t0)/1000000, (unsigned long long)(t2-t1)/1000000, (unsigned long long)(t3-t2)/1000000,
 			(unsigned long long)heap0>>20, (unsigned long long)heap1>>20, (unsigned long long)obj0, (unsigned long long)obj1,
 			(unsigned long long)mstats.nmalloc, (unsigned long long)mstats.nfree,
-			(unsigned long long)nlookup, (unsigned long long)nsizelookup, (unsigned long long)naddrlookup);
+			(unsigned long long)nlookup, (unsigned long long)nsizelookup, (unsigned long long)naddrlookup, (unsigned long long) nhandoff);
 	}
 
 	pthread_mutex_unlock(&gcsema);
-	runtime_starttheworld();
+
+	// If we could have used another helper proc, start one now,
+	// in the hope that it will be available next time.
+	// It would have been even better to start it before the collection,
+	// but doing so requires allocating memory, so it's tricky to
+	// coordinate.  This lazy approach works out in practice:
+	// we don't mind if the first couple gc rounds don't have quite
+	// the maximum number of procs.
+	runtime_starttheworld(extra);
 
 	// finqlock is still held.
-	fp = finq;
-	if(fp != nil) {
+	if(finq != nil) {
 		// kick off or wake up goroutine to run queued finalizers
 		if(!finstarted) {
 			__go_go(runfinq, nil);
@@ -601,37 +989,44 @@
 	__go_cachestats();
 	m->gcing = 0;
 	pthread_mutex_unlock(&gcsema);
-	runtime_starttheworld();
+	runtime_starttheworld(false);
 }
 
 static void
 runfinq(void* dummy)
 {
-	Finalizer *f, *next;
+	Finalizer *f;
+	FinBlock *fb, *next;
+	uint32 i;
 
 	USED(dummy);
 
 	for(;;) {
 		pthread_mutex_lock(&finqlock);
-		f = finq;
+		fb = finq;
 		finq = nil;
-		if(f == nil) {
+		if(fb == nil) {
 			fingwait = 1;
 			pthread_cond_wait(&finqcond, &finqlock);
 			pthread_mutex_unlock(&finqlock);
 			continue;
 		}
 		pthread_mutex_unlock(&finqlock);
-		for(; f; f=next) {
-			void *params[1];
+		for(; fb; fb=next) {
+			next = fb->next;
+			for(i=0; i<(uint32)fb->cnt; i++) {
+				void *params[1];
 
-			next = f->next;
-			params[0] = &f->arg;
-			reflect_call(f->ft, (void*)f->fn, 0, 0, params, nil);
-			f->fn = nil;
-			f->arg = nil;
-			f->next = nil;
-			runtime_free(f);
+				f = &fb->fin[i];
+				params[0] = &f->arg;
+				runtime_setblockspecial(f->arg, false);
+				reflect_call(f->ft, (void*)f->fn, 0, 0, params, nil);
+				f->fn = nil;
+				f->arg = nil;
+			}
+			fb->cnt = 0;
+			fb->next = finc;
+			finc = fb;
 		}
 		runtime_gc(1);	// trigger another gc to clean up the finalized objects, if possible
 	}
@@ -783,6 +1178,9 @@
 {
 	uintptr *b, off, shift;
 
+	if(DebugMark)
+		return true;
+
 	off = (uintptr*)v - (uintptr*)runtime_mheap.arena_start;
 	b = (uintptr*)runtime_mheap.arena_start - off/wordsPerBitmapWord - 1;
 	shift = off % wordsPerBitmapWord;
@@ -791,17 +1189,23 @@
 }
 
 void
-runtime_setblockspecial(void *v)
+runtime_setblockspecial(void *v, bool s)
 {
 	uintptr *b, off, shift, bits, obits;
 
+	if(DebugMark)
+		return;
+
 	off = (uintptr*)v - (uintptr*)runtime_mheap.arena_start;
 	b = (uintptr*)runtime_mheap.arena_start - off/wordsPerBitmapWord - 1;
 	shift = off % wordsPerBitmapWord;
 
 	for(;;) {
 		obits = *b;
-		bits = obits | (bitSpecial<<shift);
+		if(s)
+			bits = obits | (bitSpecial<<shift);
+		else
+			bits = obits & ~(bitSpecial<<shift);
 		if(runtime_singleproc) {
 			*b = bits;
 			break;
@@ -812,7 +1216,7 @@
 		}
 	}
 }
- 
+
 void
 runtime_MHeap_MapBits(MHeap *h)
 {
@@ -823,7 +1227,7 @@
 		bitmapChunk = 8192
 	};
 	uintptr n;
-	
+
 	n = (h->arena_used - h->arena_start) / wordsPerBitmapWord;
 	n = (n+bitmapChunk-1) & ~(bitmapChunk-1);
 	if(h->bitmap_mapped >= n)
diff -r c36211271569 libgo/runtime/mheap.c
--- a/libgo/runtime/mheap.c	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/mheap.c	Wed Oct 26 16:12:38 2011 -0700
@@ -13,6 +13,7 @@
 // and heapmap(i) == span for all s->start <= i < s->start+s->npages.
 
 #include "runtime.h"
+#include "arch.h"
 #include "malloc.h"
 
 static MSpan *MHeap_AllocLocked(MHeap*, uintptr, int32);
@@ -102,6 +103,7 @@
 		runtime_throw("MHeap_AllocLocked - bad npages");
 	runtime_MSpanList_Remove(s);
 	s->state = MSpanInUse;
+	mstats.heap_idle -= s->npages<<PageShift;
 
 	if(s->npages > npage) {
 		// Trim extra and put it back in the heap.
@@ -277,6 +279,7 @@
 		// runtime_printf("MHeap_FreeLocked - span %p ptr %p state %d ref %d\n", s, s->start<<PageShift, s->state, s->ref);
 		runtime_throw("MHeap_FreeLocked - invalid free");
 	}
+	mstats.heap_idle += s->npages<<PageShift;
 	s->state = MSpanFree;
 	runtime_MSpanList_Remove(s);
 	sp = (uintptr*)(s->start<<PageShift);
diff -r c36211271569 libgo/runtime/mprof.goc
--- a/libgo/runtime/mprof.goc	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/mprof.goc	Wed Oct 26 16:12:38 2011 -0700
@@ -7,6 +7,7 @@
 
 package runtime
 #include "runtime.h"
+#include "arch.h"
 #include "malloc.h"
 #include "defs.h"
 #include "go-type.h"
diff -r c36211271569 libgo/runtime/msize.c
--- a/libgo/runtime/msize.c	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/msize.c	Wed Oct 26 16:12:38 2011 -0700
@@ -26,6 +26,7 @@
 // TODO(rsc): Compute max waste for any given size.
 
 #include "runtime.h"
+#include "arch.h"
 #include "malloc.h"
 
 int32 runtime_class_to_size[NumSizeClasses];
diff -r c36211271569 libgo/runtime/proc.c
--- a/libgo/runtime/proc.c	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/proc.c	Wed Oct 26 16:12:38 2011 -0700
@@ -3,6 +3,7 @@
 // license that can be found in the LICENSE file.
 
 #include "runtime.h"
+#include "arch.h"
 #include "malloc.h"	/* so that acid generated from proc.c includes malloc data structures */
 
 typedef struct Sched Sched;
diff -r c36211271569 libgo/runtime/runtime.h
--- a/libgo/runtime/runtime.h	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/runtime.h	Wed Oct 26 16:12:38 2011 -0700
@@ -136,7 +136,7 @@
 int64	runtime_nanotime(void);
 
 void	runtime_stoptheworld(void);
-void	runtime_starttheworld(void);
+void	runtime_starttheworld(bool);
 void	__go_go(void (*pfn)(void*), void*);
 void	__go_gc_goroutine_init(void*);
 void	__go_enable_gc(void);
@@ -184,18 +184,21 @@
 MCache*	runtime_allocmcache(void);
 void	free(void *v);
 struct __go_func_type;
-void	runtime_addfinalizer(void*, void(*fn)(void*), const struct __go_func_type *);
-void	runtime_walkfintab(void (*fn)(void*), void (*scan)(byte *, int64));
+bool	runtime_addfinalizer(void*, void(*fn)(void*), const struct __go_func_type *);
 #define runtime_mmap mmap
 #define runtime_munmap(p, s) munmap((p), (s))
 #define runtime_cas(pval, old, new) __sync_bool_compare_and_swap (pval, old, new)
 #define runtime_casp(pval, old, new) __sync_bool_compare_and_swap (pval, old, new)
+#define runtime_xadd(p, v) __sync_add_and_fetch (p, v)
 
 void	runtime_sigprof(uint8 *pc, uint8 *sp, uint8 *lr);
 void	runtime_cpuprofinit(void);
 void	runtime_resetcpuprofiler(int32);
 void	runtime_setcpuprofilerate(void(*)(uintptr*, int32), int32);
 uint32	runtime_fastrand1(void);
+void	runtime_procyield(uint32);
+void	runtime_osyield(void);
+void	runtime_usleep(uint32);
 
 struct __go_func_type;
 void reflect_call(const struct __go_func_type *, const void *, _Bool, _Bool,
diff -r c36211271569 libgo/runtime/sigqueue.goc
--- a/libgo/runtime/sigqueue.goc	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/sigqueue.goc	Wed Oct 26 16:12:38 2011 -0700
@@ -39,6 +39,7 @@
 package runtime
 #include "config.h"
 #include "runtime.h"
+#include "arch.h"
 #include "malloc.h"
 #include "defs.h"
 
diff -r c36211271569 libgo/runtime/thread.c
--- a/libgo/runtime/thread.c	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/runtime/thread.c	Wed Oct 26 16:12:38 2011 -0700
@@ -14,19 +14,6 @@
 		runtime_throw("sem_init failed");
 }
 
-static uint32
-runtime_xadd(uint32 volatile *val, int32 delta)
-{
-	uint32 oval, nval;
-
-	for(;;){
-		oval = *val;
-		nval = oval + delta;
-		if(runtime_cas(val, oval, nval))
-			return nval;
-	}
-}
-
 // noinline so that runtime_lock doesn't have to split the stack.
 static void runtime_lock_full(Lock *l) __attribute__ ((noinline));
 
diff -r c36211271569 libgo/runtime/yield.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgo/runtime/yield.c	Wed Oct 26 16:12:38 2011 -0700
@@ -0,0 +1,54 @@
+// Copyright 2011 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.
+
+#define _GNU_SOURCE
+
+#include "config.h"
+
+#include <stddef.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <pthread.h>
+#include <unistd.h>
+
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+
+#include "runtime.h"
+
+/* Spin wait.  */
+
+void
+runtime_procyield (uint32 cnt)
+{
+  volatile uint32 i;
+
+  for (i = 0; i < cnt; ++i)
+    {
+#if defined (__i386__) || defined (__x86_64__)
+      __builtin_ia32_pause ();
+#endif
+    }
+}
+
+/* Ask the OS to reschedule this thread.  */
+
+void
+runtime_osyield (void)
+{
+  pthread_yield ();
+}
+
+/* Sleep for some number of microseconds.  */
+
+void
+runtime_usleep (uint32 us)
+{
+  struct timeval tv;
+
+  tv.tv_sec = us / 1000000;
+  tv.tv_usec = us % 1000000;
+  select (0, NULL, NULL, NULL, &tv);
+}
diff -r c36211271569 libgo/testsuite/gotest
--- a/libgo/testsuite/gotest	Tue Oct 25 11:05:51 2011 -0700
+++ b/libgo/testsuite/gotest	Wed Oct 26 16:12:38 2011 -0700
@@ -331,6 +331,10 @@
 	pattern='Benchmark([^a-z].*)?'
 	benchmarks=$($NM -p -v _gotest_.o $xofile | egrep ' T .*\.'$pattern'$' | grep -v '\..*\..*\.' | sed 's/.* //' | sed 's/.*\.\(.*\.\)/\1/')
 
+	# examples are named ExampleFoo
+	pattern='Example([^a-z].*)?'
+	examples=$($NM -p -v _gotest_.o $xofile | egrep ' T .*\.'$pattern'$' | grep -v '\..*\..*\.' | sed 's/.* //' | sed 's/.*\.\(.*\.\)/\1/')
+
 	# package spec
 	echo 'package main'
 	echo
@@ -353,6 +357,7 @@
 		echo '	{"'$i'", '$j'},'
 	done
 	echo '}'
+
 	# benchmark array
 	# The comment makes the multiline declaration
 	# gofmt-safe even when there are no benchmarks.
@@ -363,6 +368,17 @@
 		echo '	{"'$i'", '$j'},'
 	done
 	echo '}'
+
+	# examples array
+	echo 'var examples = []testing.InternalExample{ //'
+	# This doesn't work because we don't pick up the output.
+	#for i in $examples
+	#do
+	#	j=$(localname $i)
+	#	echo '	{"'$i'", '$j', ""},'
+	#done
+	echo '}'
+
 	# body
 	echo \
 '
@@ -381,7 +397,7 @@
 }
 
 func main() {
-	testing.Main(matchString, tests, benchmarks)
+	testing.Main(matchString, tests, benchmarks, examples)
 }'
 }>_testmain.go
 

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]