
Remove the old locking code written in C. Add a shell script mkrsysinfo.sh to generate the runtime_sysinfo.go file, so that we can get Go copies of the system time structures and other types. Tweak the compiler so that when compiling the runtime package the address operator does not cause local variables to escape. When the gc compiler compiles the runtime, an escaping local variable is treated as an error. We should implement that, instead of this change, when escape analysis is turned on. Tweak the compiler so that the generated C header does not include names that start with an underscore followed by a non-upper-case letter, except for the special cases of _defer and _panic. Otherwise we translate C types to Go in runtime_sysinfo.go and then generate those Go types back as C types in runtime.inc, which is useless and painful for the C code. Change entersyscall and friends to take a dummy argument, as the gc versions do, to simplify calls from the shared code. Reviewed-on: https://go-review.googlesource.com/30079 From-SVN: r240657
282 lines
5.8 KiB
Go
282 lines
5.8 KiB
Go
// 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.
|
|
|
|
// Export guts for testing.
|
|
|
|
package runtime
|
|
|
|
//var Fadd64 = fadd64
|
|
//var Fsub64 = fsub64
|
|
//var Fmul64 = fmul64
|
|
//var Fdiv64 = fdiv64
|
|
//var F64to32 = f64to32
|
|
//var F32to64 = f32to64
|
|
//var Fcmp64 = fcmp64
|
|
//var Fintto64 = fintto64
|
|
//var F64toint = f64toint
|
|
//var Sqrt = sqrt
|
|
|
|
func golockedOSThread() bool
|
|
|
|
var Entersyscall = entersyscall
|
|
var Exitsyscall = exitsyscall
|
|
var LockedOSThread = golockedOSThread
|
|
|
|
// var Xadduintptr = xadduintptr
|
|
|
|
// var FuncPC = funcPC
|
|
|
|
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 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 GCMask(x interface{}) (ret []byte) {
|
|
return nil
|
|
}
|
|
|
|
//func testSchedLocalQueue()
|
|
//func testSchedLocalQueueSteal()
|
|
//
|
|
//func RunSchedLocalQueueTest() {
|
|
// testSchedLocalQueue()
|
|
//}
|
|
//
|
|
//func RunSchedLocalQueueStealTest() {
|
|
// testSchedLocalQueueSteal()
|
|
//}
|
|
|
|
//var StringHash = stringHash
|
|
//var BytesHash = bytesHash
|
|
//var Int32Hash = int32Hash
|
|
//var Int64Hash = int64Hash
|
|
//var EfaceHash = efaceHash
|
|
//var IfaceHash = ifaceHash
|
|
//var MemclrBytes = memclrBytes
|
|
|
|
var HashLoad = &hashLoad
|
|
|
|
// entry point for testing
|
|
//func GostringW(w []uint16) (s string) {
|
|
// s = gostringw(&w[0])
|
|
// return
|
|
//}
|
|
|
|
//var Gostringnocopy = gostringnocopy
|
|
//var Maxstring = &maxstring
|
|
|
|
//type Uintreg uintreg
|
|
|
|
/*
|
|
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
|
|
var Int32Hash = int32Hash
|
|
var Int64Hash = int64Hash
|
|
var EfaceHash = efaceHash
|
|
var IfaceHash = ifaceHash
|
|
var MemclrBytes = memclrBytes
|
|
*/
|
|
|
|
var Open = open
|
|
var Close = closefd
|
|
var Read = read
|
|
var Write = write
|
|
|
|
func Envs() []string { return envs }
|
|
func SetEnvs(e []string) { envs = e }
|
|
|
|
//var BigEndian = sys.BigEndian
|
|
|
|
// For benchmarking.
|
|
|
|
/*
|
|
func BenchSetType(n int, x interface{}) {
|
|
e := *efaceOf(&x)
|
|
t := e._type
|
|
var size uintptr
|
|
var p unsafe.Pointer
|
|
switch t.kind & kindMask {
|
|
case kindPtr:
|
|
t = (*ptrtype)(unsafe.Pointer(t)).elem
|
|
size = t.size
|
|
p = e.data
|
|
case kindSlice:
|
|
slice := *(*struct {
|
|
ptr unsafe.Pointer
|
|
len, cap uintptr
|
|
})(e.data)
|
|
t = (*slicetype)(unsafe.Pointer(t)).elem
|
|
size = t.size * slice.len
|
|
p = slice.ptr
|
|
}
|
|
allocSize := roundupsize(size)
|
|
systemstack(func() {
|
|
for i := 0; i < n; i++ {
|
|
heapBitsSetType(uintptr(p), allocSize, size, t)
|
|
}
|
|
})
|
|
}
|
|
|
|
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) {
|
|
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 h_allspans {
|
|
if s.state == mSpanInUse {
|
|
counted += s.npages
|
|
}
|
|
}
|
|
|
|
startTheWorld()
|
|
|
|
return
|
|
}
|
|
*/
|