-14854533dcc7
+883bc6ed0ea815293fe6309d66f967ea60630e87
-The first line of this file holds the Mercurial revision number of the
+The first line of this file holds the git revision number of the
last merge done from the master library sources.
-go1.4
\ No newline at end of file
+go1.4.2
\ No newline at end of file
Go generate accepts one specific flag:
-run=""
+ TODO: This flag is unimplemented.
if non-empty, specifies a regular expression to
select directives whose command matches the expression.
Go generate accepts one specific flag:
-run=""
+ TODO: This flag is unimplemented.
if non-empty, specifies a regular expression to
select directives whose command matches the expression.
// Parse line, obeying quoted strings.
var words []string
line = line[len("//go:generate ") : len(line)-1] // Drop preamble and final newline.
+ // There may still be a carriage return.
+ if len(line) > 0 && line[len(line)-1] == '\r' {
+ line = line[:len(line)-1]
+ }
// One (possibly quoted) word per iteration.
Words:
for {
}
g.setShorthand([]string{"-command", "yacc", "go", "tool", "yacc"})
for _, test := range splitTests {
+ // First with newlines.
got := g.split("//go:generate " + test.in + "\n")
if !reflect.DeepEqual(got, test.out) {
t.Errorf("split(%q): got %q expected %q", test.in, got, test.out)
}
+ // Then with CRLFs, thank you Windows.
+ got = g.split("//go:generate " + test.in + "\r\n")
+ if !reflect.DeepEqual(got, test.out) {
+ t.Errorf("split(%q): got %q expected %q", test.in, got, test.out)
+ }
}
}
}
}
if remote != repo {
- return fmt.Errorf("%s is from %s, should be from %s", dir, remote, repo)
+ return fmt.Errorf("%s is a custom import path for %s, but %s is checked out from %s", rr.root, repo, dir, remote)
}
}
}
}
// x &^ (-y) == x &^ ^(y-1) == x & (y-1)
- y1 := nat(nil).add(y.abs, natOne)
+ y1 := nat(nil).sub(y.abs, natOne)
z.abs = z.abs.and(x.abs, y1)
z.neg = false
return z
{"-0x01", "-0x01", "-0x01", "-0x01", "0x00", "0x00"},
{"0x07", "0x08", "0x00", "0x0f", "0x0f", "0x07"},
{"0x05", "0x0f", "0x05", "0x0f", "0x0a", "0x00"},
+ {"0xff", "-0x0a", "0xf6", "-0x01", "-0xf7", "0x09"},
{"0x013ff6", "0x9a4e", "0x1a46", "0x01bffe", "0x01a5b8", "0x0125b0"},
{"-0x013ff6", "0x9a4e", "0x800a", "-0x0125b2", "-0x01a5bc", "-0x01c000"},
{"-0x013ff6", "-0x9a4e", "-0x01bffe", "-0x1a46", "0x01a5b8", "0x8008"},
// with a unique tag like `reflect:"array"` or `reflect:"ptr"`
// so that code cannot convert from, say, *arrayType to *ptrType.
type rtype struct {
- kind uint8 // enumeration for C
- align int8 // alignment of variable with this type
- fieldAlign uint8 // alignment of struct field with this type
- _ uint8 // unused/padding
+ kind uint8 // enumeration for C
+ align int8 // alignment of variable with this type
+ fieldAlign uint8 // alignment of struct field with this type
+ _ uint8 // unused/padding
size uintptr
- hash uint32 // hash of type; avoids computation in hash tables
+ hash uint32 // hash of type; avoids computation in hash tables
hashfn uintptr // hash function code
equalfn uintptr // equality function code
// gcProg is a helper type for generatation of GC pointer info.
type gcProg struct {
- gc []byte
- size uintptr // size of type in bytes
+ gc []byte
+ size uintptr // size of type in bytes
+ hasPtr bool
}
func (gc *gcProg) append(v byte) {
gc.gc[nptr/2] &= ^(3 << ((nptr%2)*4 + 2))
gc.gc[nptr/2] |= v << ((nptr%2)*4 + 2)
gc.size += ptrsize
+ if v == bitsPointer {
+ gc.hasPtr = true
+ }
}
-func (gc *gcProg) finalize() unsafe.Pointer {
+func (gc *gcProg) finalize() (unsafe.Pointer, bool) {
if gc.size == 0 {
- return nil
+ return nil, false
}
ptrsize := unsafe.Sizeof(uintptr(0))
gc.align(ptrsize)
gc.appendWord(extractGCWord(gc.gc, i))
}
}
- return unsafe.Pointer(&gc.gc[0])
+ return unsafe.Pointer(&gc.gc[0]), gc.hasPtr
}
func extractGCWord(gc []byte, i uintptr) byte {
for i := 0; i < int(bucketSize*unsafe.Sizeof(uint8(0))/ptrsize); i++ {
gc.append(bitsScalar)
}
- gc.append(bitsPointer) // overflow
- if runtime.GOARCH == "amd64p32" {
- gc.append(bitsScalar)
- }
// keys
for i := 0; i < bucketSize; i++ {
gc.appendProg(ktyp)
for i := 0; i < bucketSize; i++ {
gc.appendProg(etyp)
}
+ // overflow
+ gc.append(bitsPointer)
+ if runtime.GOARCH == "amd64p32" {
+ gc.append(bitsScalar)
+ }
b := new(rtype)
b.size = gc.size
- // b.gc[0] = gc.finalize()
+ // b.gc[0], _ = gc.finalize()
b.kind |= kindGCProg
s := "bucket(" + *ktyp.string + "," + *etyp.string + ")"
b.string = &s
package runtime_test
import (
+ "os/exec"
"runtime"
"strings"
"testing"
}
}
+func TestCgoExternalThreadSIGPROF(t *testing.T) {
+ // issue 9456.
+ switch runtime.GOOS {
+ case "plan9", "windows":
+ t.Skipf("no pthreads on %s", runtime.GOOS)
+ case "darwin":
+ // static constructor needs external linking, but we don't support
+ // external linking on OS X 10.6.
+ out, err := exec.Command("uname", "-r").Output()
+ if err != nil {
+ t.Fatalf("uname -r failed: %v", err)
+ }
+ // OS X 10.6 == Darwin 10.x
+ if strings.HasPrefix(string(out), "10.") {
+ t.Skipf("no external linking on OS X 10.6")
+ }
+ }
+ got := executeTest(t, cgoExternalThreadSIGPROFSource, nil)
+ want := "OK\n"
+ if got != want {
+ t.Fatalf("expected %q, but got %q", want, got)
+ }
+}
+
const cgoSignalDeadlockSource = `
package main
printf("_beginthreadex failed\n");
}
`
+
+const cgoExternalThreadSIGPROFSource = `
+package main
+
+/*
+#include <stdint.h>
+#include <signal.h>
+#include <pthread.h>
+
+volatile int32_t spinlock;
+
+static void *thread1(void *p) {
+ (void)p;
+ while (spinlock == 0)
+ ;
+ pthread_kill(pthread_self(), SIGPROF);
+ spinlock = 0;
+ return NULL;
+}
+__attribute__((constructor)) void issue9456() {
+ pthread_t tid;
+ pthread_create(&tid, 0, thread1, NULL);
+}
+*/
+import "C"
+
+import (
+ "runtime"
+ "sync/atomic"
+ "unsafe"
+)
+
+func main() {
+ // This test intends to test that sending SIGPROF to foreign threads
+ // before we make any cgo call will not abort the whole process, so
+ // we cannot make any cgo call here. See http://golang.org/issue/9456.
+ atomic.StoreInt32((*int32)(unsafe.Pointer(&C.spinlock)), 1)
+ for atomic.LoadInt32((*int32)(unsafe.Pointer(&C.spinlock))) == 1 {
+ runtime.Gosched()
+ }
+ println("OK")
+}
+`
// A bucket for a Go map.
type bmap struct {
- tophash [bucketCnt]uint8
- overflow *bmap
+ tophash [bucketCnt]uint8
// Followed by bucketCnt keys and then bucketCnt values.
// NOTE: packing all the keys together and then all the values together makes the
// code a bit more complicated than alternating key/value/key/value/... but it allows
// us to eliminate padding which would be needed for, e.g., map[int64]int8.
+ // Followed by an overflow pointer.
}
// A hash iteration structure.
return h > empty && h < minTopHash
}
+func (b *bmap) overflow(t *maptype) *bmap {
+ return *(**bmap)(add(unsafe.Pointer(b), uintptr(t.bucketsize)-regSize))
+}
+func (b *bmap) setoverflow(t *maptype, ovf *bmap) {
+ *(**bmap)(add(unsafe.Pointer(b), uintptr(t.bucketsize)-regSize)) = ovf
+}
+
func makemap(t *maptype, hint int64) *hmap {
if sz := unsafe.Sizeof(hmap{}); sz > 48 || sz != uintptr(t.hmap.size) {
gothrow("bad hmap size")
return v
}
}
- b = b.overflow
+ b = b.overflow(t)
if b == nil {
return unsafe.Pointer(t.elem.zero)
}
return v, true
}
}
- b = b.overflow
+ b = b.overflow(t)
if b == nil {
return unsafe.Pointer(t.elem.zero), false
}
return k, v
}
}
- b = b.overflow
+ b = b.overflow(t)
if b == nil {
return nil, nil
}
memmove(v2, val, uintptr(t.elem.size))
return
}
- if b.overflow == nil {
+ ovf := b.overflow(t)
+ if ovf == nil {
break
}
- b = b.overflow
+ b = ovf
}
// did not find mapping for key. Allocate new cell & add entry.
memstats.next_gc = memstats.heap_alloc
}
newb := (*bmap)(newobject(t.bucket))
- b.overflow = newb
+ b.setoverflow(t, newb)
inserti = &newb.tophash[0]
insertk = add(unsafe.Pointer(newb), dataOffset)
insertv = add(insertk, bucketCnt*uintptr(t.keysize))
h.count--
return
}
- b = b.overflow
+ b = b.overflow(t)
if b == nil {
return
}
return
}
}
- b = b.overflow
+ b = b.overflow(t)
i = 0
goto next
}
yk := add(unsafe.Pointer(y), dataOffset)
xv := add(xk, bucketCnt*uintptr(t.keysize))
yv := add(yk, bucketCnt*uintptr(t.keysize))
- for ; b != nil; b = b.overflow {
+ for ; b != nil; b = b.overflow(t) {
k := add(unsafe.Pointer(b), dataOffset)
v := add(k, bucketCnt*uintptr(t.keysize))
for i := 0; i < bucketCnt; i, k, v = i+1, add(k, uintptr(t.keysize)), add(v, uintptr(t.valuesize)) {
memstats.next_gc = memstats.heap_alloc
}
newx := (*bmap)(newobject(t.bucket))
- x.overflow = newx
+ x.setoverflow(t, newx)
x = newx
xi = 0
xk = add(unsafe.Pointer(x), dataOffset)
memstats.next_gc = memstats.heap_alloc
}
newy := (*bmap)(newobject(t.bucket))
- y.overflow = newy
+ y.setoverflow(t, newy)
y = newy
yi = 0
yk = add(unsafe.Pointer(y), dataOffset)
// Unlink the overflow buckets & clear key/value to help GC.
if h.flags&oldIterator == 0 {
b = (*bmap)(add(h.oldbuckets, oldbucket*uintptr(t.bucketsize)))
- b.overflow = nil
memclr(add(unsafe.Pointer(b), dataOffset), uintptr(t.bucketsize)-dataOffset)
}
}
}
return add(unsafe.Pointer(b), dataOffset+bucketCnt*4+i*uintptr(t.valuesize))
}
- b = b.overflow
+ b = b.overflow(t)
if b == nil {
return unsafe.Pointer(t.elem.zero)
}
}
return add(unsafe.Pointer(b), dataOffset+bucketCnt*4+i*uintptr(t.valuesize)), true
}
- b = b.overflow
+ b = b.overflow(t)
if b == nil {
return unsafe.Pointer(t.elem.zero), false
}
}
return add(unsafe.Pointer(b), dataOffset+bucketCnt*8+i*uintptr(t.valuesize))
}
- b = b.overflow
+ b = b.overflow(t)
if b == nil {
return unsafe.Pointer(t.elem.zero)
}
}
return add(unsafe.Pointer(b), dataOffset+bucketCnt*8+i*uintptr(t.valuesize)), true
}
- b = b.overflow
+ b = b.overflow(t)
if b == nil {
return unsafe.Pointer(t.elem.zero), false
}
return add(unsafe.Pointer(b), dataOffset+bucketCnt*2*ptrSize+i*uintptr(t.valuesize))
}
}
- b = b.overflow
+ b = b.overflow(t)
if b == nil {
return unsafe.Pointer(t.elem.zero)
}
return add(unsafe.Pointer(b), dataOffset+bucketCnt*2*ptrSize+i*uintptr(t.valuesize)), true
}
}
- b = b.overflow
+ b = b.overflow(t)
if b == nil {
return unsafe.Pointer(t.elem.zero), false
}
// If all is true, Stack formats stack traces of all other goroutines
// into buf after the trace for the current goroutine.
func Stack(buf []byte, all bool) int {
- mp := acquirem()
- gp := mp.curg
if all {
semacquire(&worldsema, false)
- mp.gcing = 1
- releasem(mp)
+ gp := getg()
+ gp.m.gcing = 1
onM(stoptheworld)
- if mp != acquirem() {
- gothrow("Stack: rescheduled")
- }
}
n := 0
if len(buf) > 0 {
+ gp := getg()
sp := getcallersp(unsafe.Pointer(&buf))
pc := getcallerpc(unsafe.Pointer(&buf))
onM(func() {
}
if all {
- mp.gcing = 0
+ gp := getg()
+ gp.m.gcing = 0
semrelease(&worldsema)
onM(starttheworld)
}
- releasem(mp)
return n
}
import "unsafe"
+const _SIGPROF = 0 // dummy value for badsignal
+
func pread(fd int32, buf unsafe.Pointer, nbytes int32, offset int64) int32
func pwrite(fd int32, buf unsafe.Pointer, nbytes int32, offset int64) int32
func seek(fd int32, offset int64, whence int32) int64
// This runs on a foreign stack, without an m or a g. No stack split.
//go:nosplit
func badsignal(sig uintptr) {
+ // Some external libraries, for example, OpenBLAS, create worker threads in
+ // a global constructor. If we're doing cpu profiling, and the SIGPROF signal
+ // comes to one of the foreign threads before we make our first cgo call, the
+ // call to cgocallback below will bring down the whole process.
+ // It's better to miss a few SIGPROF signals than to abort in this case.
+ // See http://golang.org/issue/9456.
+ if _SIGPROF != 0 && sig == _SIGPROF && needextram != 0 {
+ return
+ }
cgocallback(unsafe.Pointer(funcPC(sigsend)), noescape(unsafe.Pointer(&sig)), unsafe.Sizeof(sig))
}
"unsafe"
)
+const _SIGPROF = 0 // dummy value for badsignal
+
type callbacks struct {
lock mutex
ctxt [cb_max]*wincallbackcontext
panic("compilecallback: output parameter size is wrong")
}
argsize := uintptr(0)
- for _, t := range (*[1024](*_type))(unsafe.Pointer(&ft.in[0]))[:len(ft.in)] {
- if (*t).size > uintptrSize {
- panic("compilecallback: input parameter size is wrong")
+ if len(ft.in) > 0 {
+ for _, t := range (*[1024](*_type))(unsafe.Pointer(&ft.in[0]))[:len(ft.in)] {
+ if (*t).size > uintptrSize {
+ panic("compilecallback: input parameter size is wrong")
+ }
+ argsize += uintptrSize
}
- argsize += uintptrSize
}
lock(&cbs.lock)
switch any.Type {
case RTM_ADD, RTM_DELETE, RTM_CHANGE, RTM_GET, RTM_LOSING, RTM_REDIRECT, RTM_MISS, RTM_LOCK, RTM_RESOLVE:
p := (*RouteMessage)(unsafe.Pointer(any))
- return &RouteMessage{Header: p.Header, Data: b[SizeofRtMsghdr:any.Msglen]}
+ return &RouteMessage{Header: p.Header, Data: b[p.Header.Hdrlen:any.Msglen]}
case RTM_IFINFO:
p := (*InterfaceMessage)(unsafe.Pointer(any))
- return &InterfaceMessage{Header: p.Header, Data: b[SizeofIfMsghdr:any.Msglen]}
+ return &InterfaceMessage{Header: p.Header, Data: b[p.Header.Hdrlen:any.Msglen]}
case RTM_IFANNOUNCE:
p := (*InterfaceAnnounceMessage)(unsafe.Pointer(any))
return &InterfaceAnnounceMessage{Header: p.Header}
case RTM_NEWADDR, RTM_DELADDR:
p := (*InterfaceAddrMessage)(unsafe.Pointer(any))
- return &InterfaceAddrMessage{Header: p.Header, Data: b[SizeofIfaMsghdr:any.Msglen]}
+ return &InterfaceAddrMessage{Header: p.Header, Data: b[p.Header.Hdrlen:any.Msglen]}
}
return nil
}
old_rev=`sed 1q MERGE`
rm -rf ${OLDDIR}
-hg clone -r ${old_rev} ${repository} ${OLDDIR}
+git clone ${repository} ${OLDDIR}
+(cd ${OLDDIR} && git checkout ${old_rev})
rm -rf ${NEWDIR}
-hg clone -u ${rev} ${repository} ${NEWDIR}
+git clone ${repository} ${NEWDIR}
+(cd ${NEWDIR} && git checkout ${rev})
-new_rev=`cd ${NEWDIR} && hg log -r ${rev} | sed 1q | sed -e 's/.*://'`
+new_rev=`cd ${NEWDIR} && git log | sed 1q | sed -e 's/commit //'`
merge() {
name=$1
elif test -f ${old}; then
# The file exists in the old version.
if ! test -f ${libgo}; then
- echo "merge.sh: $name: skipping: exists in old and new hg, but not in libgo"
+ echo "merge.sh: $name: skipping: exists in old and new git, but not in libgo"
continue
fi
if cmp -s ${old} ${libgo}; then
if ! test -d ${oldtd}; then
continue
fi
- (cd ${oldtd} && hg status -A .) | while read f; do
- if test "`basename $f`" = ".hgignore"; then
+ (cd ${oldtd} && git ls-files .) | while read f; do
+ if test "`basename $f`" = ".gitignore"; then
continue
fi
- f=`echo $f | sed -e 's/^..//'`
name=$d/$f
oldfile=${oldtd}/$f
newfile=${newtd}/$f
if ! test -d ${oldtd}; then
continue
fi
- (cd ${oldtd} && hg status -A .) | while read f; do
- if test "`basename $f`" = ".hgignore"; then
+ (cd ${oldtd} && git ls-files .) | while read f; do
+ if test "`basename $f`" = ".gitignore"; then
continue
fi
- f=`echo $f | sed -e 's/^..//'`
name=$d/$f
oldfile=${oldtd}/$f
newfile=${newtd}/$f