diff options
Diffstat (limited to 'libgo/go/runtime/export_test.go')
-rw-r--r-- | libgo/go/runtime/export_test.go | 241 |
1 files changed, 158 insertions, 83 deletions
diff --git a/libgo/go/runtime/export_test.go b/libgo/go/runtime/export_test.go index fd328a1d36..cc4b188b60 100644 --- a/libgo/go/runtime/export_test.go +++ b/libgo/go/runtime/export_test.go @@ -1,4 +1,4 @@ -// Copyright 2010 The Go Authors. All rights reserved. +// Copyright 2010 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. @@ -7,6 +7,8 @@ package runtime import ( + "runtime/internal/atomic" + "runtime/internal/sys" "unsafe" ) @@ -21,66 +23,130 @@ import ( //var F64toint = f64toint //var Sqrt = sqrt -func entersyscall(int32) -func exitsyscall(int32) -func golockedOSThread() bool - var Entersyscall = entersyscall var Exitsyscall = exitsyscall -var LockedOSThread = golockedOSThread +var LockedOSThread = lockedOSThread // var Xadduintptr = xadduintptr // var FuncPC = funcPC +var Atoi = atoi +var Atoi32 = atoi32 + type LFNode struct { Next uint64 Pushcnt uintptr } -func lfstackpush_go(head *uint64, node *LFNode) -func lfstackpop_go(head *uint64) *LFNode - -var LFStackPush = lfstackpush_go -var LFStackPop = lfstackpop_go - -type ParFor struct { - body func(*ParFor, uint32) - done uint32 - Nthr uint32 - thrseq uint32 - Cnt uint32 - wait bool +func LFStackPush(head *uint64, node *LFNode) { + lfstackpush(head, (*lfnode)(unsafe.Pointer(node))) } -func newParFor(nthrmax uint32) *ParFor -func parForSetup(desc *ParFor, nthr, n uint32, wait bool, body func(*ParFor, uint32)) -func parForDo(desc *ParFor) -func parForIters(desc *ParFor, tid uintptr) (uintptr, uintptr) - -var NewParFor = newParFor -var ParForSetup = parForSetup -var ParForDo = parForDo - -func ParForIters(desc *ParFor, tid uint32) (uint32, uint32) { - begin, end := parForIters(desc, uintptr(tid)) - return uint32(begin), uint32(end) +func LFStackPop(head *uint64) *LFNode { + return (*LFNode)(unsafe.Pointer(lfstackpop(head))) } func GCMask(x interface{}) (ret []byte) { return nil } -//func testSchedLocalQueue() -//func testSchedLocalQueueSteal() -// -//func RunSchedLocalQueueTest() { -// testSchedLocalQueue() -//} -// -//func RunSchedLocalQueueStealTest() { -// testSchedLocalQueueSteal() -//} +func RunSchedLocalQueueTest() { + _p_ := new(p) + gs := make([]g, len(_p_.runq)) + for i := 0; i < len(_p_.runq); i++ { + if g, _ := runqget(_p_); g != nil { + throw("runq is not empty initially") + } + for j := 0; j < i; j++ { + runqput(_p_, &gs[i], false) + } + for j := 0; j < i; j++ { + if g, _ := runqget(_p_); g != &gs[i] { + print("bad element at iter ", i, "/", j, "\n") + throw("bad element") + } + } + if g, _ := runqget(_p_); g != nil { + throw("runq is not empty afterwards") + } + } +} + +func RunSchedLocalQueueStealTest() { + p1 := new(p) + p2 := new(p) + gs := make([]g, len(p1.runq)) + for i := 0; i < len(p1.runq); i++ { + for j := 0; j < i; j++ { + gs[j].sig = 0 + runqput(p1, &gs[j], false) + } + gp := runqsteal(p2, p1, true) + s := 0 + if gp != nil { + s++ + gp.sig++ + } + for { + gp, _ = runqget(p2) + if gp == nil { + break + } + s++ + gp.sig++ + } + for { + gp, _ = runqget(p1) + if gp == nil { + break + } + gp.sig++ + } + for j := 0; j < i; j++ { + if gs[j].sig != 1 { + print("bad element ", j, "(", gs[j].sig, ") at iter ", i, "\n") + throw("bad element") + } + } + if s != i/2 && s != i/2+1 { + print("bad steal ", s, ", want ", i/2, " or ", i/2+1, ", iter ", i, "\n") + throw("bad steal") + } + } +} + +func RunSchedLocalQueueEmptyTest(iters int) { + // Test that runq is not spuriously reported as empty. + // Runq emptiness affects scheduling decisions and spurious emptiness + // can lead to underutilization (both runnable Gs and idle Ps coexist + // for arbitrary long time). + done := make(chan bool, 1) + p := new(p) + gs := make([]g, 2) + ready := new(uint32) + for i := 0; i < iters; i++ { + *ready = 0 + next0 := (i & 1) == 0 + next1 := (i & 2) == 0 + runqput(p, &gs[0], next0) + go func() { + for atomic.Xadd(ready, 1); atomic.Load(ready) != 2; { + } + if runqempty(p) { + println("next:", next0, next1) + throw("queue is empty") + } + done <- true + }() + for atomic.Xadd(ready, 1); atomic.Load(ready) != 2; { + } + runqput(p, &gs[1], next1) + runqget(p) + <-done + runqget(p) + } +} //var StringHash = stringHash //var BytesHash = bytesHash @@ -88,9 +154,13 @@ func GCMask(x interface{}) (ret []byte) { //var Int64Hash = int64Hash //var EfaceHash = efaceHash //var IfaceHash = ifaceHash -//var MemclrBytes = memclrBytes -// var HashLoad = &hashLoad +func MemclrBytes(b []byte) { + s := (*slice)(unsafe.Pointer(&b)) + memclrNoHeapPointers(s.array, uintptr(s.len)) +} + +var HashLoad = &hashLoad // entry point for testing //func GostringW(w []uint16) (s string) { @@ -98,44 +168,15 @@ func GCMask(x interface{}) (ret []byte) { // return //} -//var Gostringnocopy = gostringnocopy -//var Maxstring = &maxstring +type Uintreg sys.Uintreg -//type Uintreg uintreg +var Open = open +var Close = closefd +var Read = read +var Write = write -//extern __go_open -func open(path *byte, mode int32, perm int32) int32 - -func Open(path *byte, mode int32, perm int32) int32 { - return open(path, mode, perm) -} - -//extern close -func close(int32) int32 - -func Close(fd int32) int32 { - return close(fd) -} - -//extern read -func read(fd int32, buf unsafe.Pointer, size int32) int32 - -func Read(fd int32, buf unsafe.Pointer, size int32) int32 { - return read(fd, buf, size) -} - -//extern write -func write(fd int32, buf unsafe.Pointer, size int32) int32 - -func Write(fd uintptr, buf unsafe.Pointer, size int32) int32 { - return write(int32(fd), buf, size) -} - -func envs() []string -func setenvs([]string) - -var Envs = envs -var SetEnvs = setenvs +func Envs() []string { return envs } +func SetEnvs(e []string) { envs = e } //var BigEndian = sys.BigEndian @@ -171,13 +212,47 @@ func BenchSetType(n int, x interface{}) { const PtrSize = sys.PtrSize -var TestingAssertE2I2GC = &testingAssertE2I2GC -var TestingAssertE2T2GC = &testingAssertE2T2GC - var ForceGCPeriod = &forcegcperiod */ // SetTracebackEnv is like runtime/debug.SetTraceback, but it raises // the "environment" traceback level, so later calls to // debug.SetTraceback (e.g., from testing timeouts) can't lower it. -func SetTracebackEnv(level string) +func SetTracebackEnv(level string) { + setTraceback(level) + traceback_env = traceback_cache +} + +/* +var ReadUnaligned32 = readUnaligned32 +var ReadUnaligned64 = readUnaligned64 + +func CountPagesInUse() (pagesInUse, counted uintptr) { + stopTheWorld("CountPagesInUse") + + pagesInUse = uintptr(mheap_.pagesInUse) + + for _, s := range mheap_.allspans { + if s.state == mSpanInUse { + counted += s.npages + } + } + + startTheWorld() + + return +} +*/ + +// BlockOnSystemStack switches to the system stack, prints "x\n" to +// stderr, and blocks in a stack containing +// "runtime.blockOnSystemStackInternal". +func BlockOnSystemStack() { + systemstack(blockOnSystemStackInternal) +} + +func blockOnSystemStackInternal() { + print("x\n") + lock(&deadlock) + lock(&deadlock) +} |