github.com/sbinet/go@v0.0.0-20160827155028-54d7de7dd62b/src/runtime/export_test.go (about) 1 // Copyright 2010 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Export guts for testing. 6 7 package runtime 8 9 import ( 10 "runtime/internal/atomic" 11 "runtime/internal/sys" 12 "unsafe" 13 ) 14 15 var Fadd64 = fadd64 16 var Fsub64 = fsub64 17 var Fmul64 = fmul64 18 var Fdiv64 = fdiv64 19 var F64to32 = f64to32 20 var F32to64 = f32to64 21 var Fcmp64 = fcmp64 22 var Fintto64 = fintto64 23 var F64toint = f64toint 24 var Sqrt = sqrt 25 26 var Entersyscall = entersyscall 27 var Exitsyscall = exitsyscall 28 var LockedOSThread = lockedOSThread 29 var Xadduintptr = atomic.Xadduintptr 30 31 var FuncPC = funcPC 32 33 var Fastlog2 = fastlog2 34 35 type LFNode struct { 36 Next uint64 37 Pushcnt uintptr 38 } 39 40 func LFStackPush(head *uint64, node *LFNode) { 41 lfstackpush(head, (*lfnode)(unsafe.Pointer(node))) 42 } 43 44 func LFStackPop(head *uint64) *LFNode { 45 return (*LFNode)(unsafe.Pointer(lfstackpop(head))) 46 } 47 48 func GCMask(x interface{}) (ret []byte) { 49 systemstack(func() { 50 ret = getgcmask(x) 51 }) 52 return 53 } 54 55 func RunSchedLocalQueueTest() { 56 _p_ := new(p) 57 gs := make([]g, len(_p_.runq)) 58 for i := 0; i < len(_p_.runq); i++ { 59 if g, _ := runqget(_p_); g != nil { 60 throw("runq is not empty initially") 61 } 62 for j := 0; j < i; j++ { 63 runqput(_p_, &gs[i], false) 64 } 65 for j := 0; j < i; j++ { 66 if g, _ := runqget(_p_); g != &gs[i] { 67 print("bad element at iter ", i, "/", j, "\n") 68 throw("bad element") 69 } 70 } 71 if g, _ := runqget(_p_); g != nil { 72 throw("runq is not empty afterwards") 73 } 74 } 75 } 76 77 func RunSchedLocalQueueStealTest() { 78 p1 := new(p) 79 p2 := new(p) 80 gs := make([]g, len(p1.runq)) 81 for i := 0; i < len(p1.runq); i++ { 82 for j := 0; j < i; j++ { 83 gs[j].sig = 0 84 runqput(p1, &gs[j], false) 85 } 86 gp := runqsteal(p2, p1, true) 87 s := 0 88 if gp != nil { 89 s++ 90 gp.sig++ 91 } 92 for { 93 gp, _ = runqget(p2) 94 if gp == nil { 95 break 96 } 97 s++ 98 gp.sig++ 99 } 100 for { 101 gp, _ = runqget(p1) 102 if gp == nil { 103 break 104 } 105 gp.sig++ 106 } 107 for j := 0; j < i; j++ { 108 if gs[j].sig != 1 { 109 print("bad element ", j, "(", gs[j].sig, ") at iter ", i, "\n") 110 throw("bad element") 111 } 112 } 113 if s != i/2 && s != i/2+1 { 114 print("bad steal ", s, ", want ", i/2, " or ", i/2+1, ", iter ", i, "\n") 115 throw("bad steal") 116 } 117 } 118 } 119 120 func RunSchedLocalQueueEmptyTest(iters int) { 121 // Test that runq is not spuriously reported as empty. 122 // Runq emptiness affects scheduling decisions and spurious emptiness 123 // can lead to underutilization (both runnable Gs and idle Ps coexist 124 // for arbitrary long time). 125 done := make(chan bool, 1) 126 p := new(p) 127 gs := make([]g, 2) 128 ready := new(uint32) 129 for i := 0; i < iters; i++ { 130 *ready = 0 131 next0 := (i & 1) == 0 132 next1 := (i & 2) == 0 133 runqput(p, &gs[0], next0) 134 go func() { 135 for atomic.Xadd(ready, 1); atomic.Load(ready) != 2; { 136 } 137 if runqempty(p) { 138 println("next:", next0, next1) 139 throw("queue is empty") 140 } 141 done <- true 142 }() 143 for atomic.Xadd(ready, 1); atomic.Load(ready) != 2; { 144 } 145 runqput(p, &gs[1], next1) 146 runqget(p) 147 <-done 148 runqget(p) 149 } 150 } 151 152 var StringHash = stringHash 153 var BytesHash = bytesHash 154 var Int32Hash = int32Hash 155 var Int64Hash = int64Hash 156 var EfaceHash = efaceHash 157 var IfaceHash = ifaceHash 158 var MemclrBytes = memclrBytes 159 160 var HashLoad = &hashLoad 161 162 // entry point for testing 163 func GostringW(w []uint16) (s string) { 164 systemstack(func() { 165 s = gostringw(&w[0]) 166 }) 167 return 168 } 169 170 var Gostringnocopy = gostringnocopy 171 var Maxstring = &maxstring 172 173 type Uintreg sys.Uintreg 174 175 var Open = open 176 var Close = closefd 177 var Read = read 178 var Write = write 179 180 func Envs() []string { return envs } 181 func SetEnvs(e []string) { envs = e } 182 183 var BigEndian = sys.BigEndian 184 185 // For benchmarking. 186 187 func BenchSetType(n int, x interface{}) { 188 e := *efaceOf(&x) 189 t := e._type 190 var size uintptr 191 var p unsafe.Pointer 192 switch t.kind & kindMask { 193 case kindPtr: 194 t = (*ptrtype)(unsafe.Pointer(t)).elem 195 size = t.size 196 p = e.data 197 case kindSlice: 198 slice := *(*struct { 199 ptr unsafe.Pointer 200 len, cap uintptr 201 })(e.data) 202 t = (*slicetype)(unsafe.Pointer(t)).elem 203 size = t.size * slice.len 204 p = slice.ptr 205 } 206 allocSize := roundupsize(size) 207 systemstack(func() { 208 for i := 0; i < n; i++ { 209 heapBitsSetType(uintptr(p), allocSize, size, t) 210 } 211 }) 212 } 213 214 const PtrSize = sys.PtrSize 215 216 var TestingAssertE2I2GC = &testingAssertE2I2GC 217 var TestingAssertE2T2GC = &testingAssertE2T2GC 218 219 var ForceGCPeriod = &forcegcperiod 220 221 // SetTracebackEnv is like runtime/debug.SetTraceback, but it raises 222 // the "environment" traceback level, so later calls to 223 // debug.SetTraceback (e.g., from testing timeouts) can't lower it. 224 func SetTracebackEnv(level string) { 225 setTraceback(level) 226 traceback_env = traceback_cache 227 } 228 229 var ReadUnaligned32 = readUnaligned32 230 var ReadUnaligned64 = readUnaligned64 231 232 func CountPagesInUse() (pagesInUse, counted uintptr) { 233 stopTheWorld("CountPagesInUse") 234 235 pagesInUse = uintptr(mheap_.pagesInUse) 236 237 for _, s := range h_allspans { 238 if s.state == mSpanInUse { 239 counted += s.npages 240 } 241 } 242 243 startTheWorld() 244 245 return 246 }