Home | History | Annotate | Download | only in runtime
      1 // Copyright 2011 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 package runtime_test
      6 
      7 import (
      8 	"math"
      9 	"net"
     10 	"runtime"
     11 	"runtime/debug"
     12 	"strings"
     13 	"sync"
     14 	"sync/atomic"
     15 	"syscall"
     16 	"testing"
     17 	"time"
     18 )
     19 
     20 var stop = make(chan bool, 1)
     21 
     22 func perpetuumMobile() {
     23 	select {
     24 	case <-stop:
     25 	default:
     26 		go perpetuumMobile()
     27 	}
     28 }
     29 
     30 func TestStopTheWorldDeadlock(t *testing.T) {
     31 	if testing.Short() {
     32 		t.Skip("skipping during short test")
     33 	}
     34 	maxprocs := runtime.GOMAXPROCS(3)
     35 	compl := make(chan bool, 2)
     36 	go func() {
     37 		for i := 0; i != 1000; i += 1 {
     38 			runtime.GC()
     39 		}
     40 		compl <- true
     41 	}()
     42 	go func() {
     43 		for i := 0; i != 1000; i += 1 {
     44 			runtime.GOMAXPROCS(3)
     45 		}
     46 		compl <- true
     47 	}()
     48 	go perpetuumMobile()
     49 	<-compl
     50 	<-compl
     51 	stop <- true
     52 	runtime.GOMAXPROCS(maxprocs)
     53 }
     54 
     55 func TestYieldProgress(t *testing.T) {
     56 	testYieldProgress(false)
     57 }
     58 
     59 func TestYieldLockedProgress(t *testing.T) {
     60 	testYieldProgress(true)
     61 }
     62 
     63 func testYieldProgress(locked bool) {
     64 	c := make(chan bool)
     65 	cack := make(chan bool)
     66 	go func() {
     67 		if locked {
     68 			runtime.LockOSThread()
     69 		}
     70 		for {
     71 			select {
     72 			case <-c:
     73 				cack <- true
     74 				return
     75 			default:
     76 				runtime.Gosched()
     77 			}
     78 		}
     79 	}()
     80 	time.Sleep(10 * time.Millisecond)
     81 	c <- true
     82 	<-cack
     83 }
     84 
     85 func TestYieldLocked(t *testing.T) {
     86 	const N = 10
     87 	c := make(chan bool)
     88 	go func() {
     89 		runtime.LockOSThread()
     90 		for i := 0; i < N; i++ {
     91 			runtime.Gosched()
     92 			time.Sleep(time.Millisecond)
     93 		}
     94 		c <- true
     95 		// runtime.UnlockOSThread() is deliberately omitted
     96 	}()
     97 	<-c
     98 }
     99 
    100 func TestGoroutineParallelism(t *testing.T) {
    101 	if runtime.NumCPU() == 1 {
    102 		// Takes too long, too easy to deadlock, etc.
    103 		t.Skip("skipping on uniprocessor")
    104 	}
    105 	P := 4
    106 	N := 10
    107 	if testing.Short() {
    108 		P = 3
    109 		N = 3
    110 	}
    111 	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(P))
    112 	// If runtime triggers a forced GC during this test then it will deadlock,
    113 	// since the goroutines can't be stopped/preempted.
    114 	// Disable GC for this test (see issue #10958).
    115 	defer debug.SetGCPercent(debug.SetGCPercent(-1))
    116 	for try := 0; try < N; try++ {
    117 		done := make(chan bool)
    118 		x := uint32(0)
    119 		for p := 0; p < P; p++ {
    120 			// Test that all P goroutines are scheduled at the same time
    121 			go func(p int) {
    122 				for i := 0; i < 3; i++ {
    123 					expected := uint32(P*i + p)
    124 					for atomic.LoadUint32(&x) != expected {
    125 					}
    126 					atomic.StoreUint32(&x, expected+1)
    127 				}
    128 				done <- true
    129 			}(p)
    130 		}
    131 		for p := 0; p < P; p++ {
    132 			<-done
    133 		}
    134 	}
    135 }
    136 
    137 // Test that all runnable goroutines are scheduled at the same time.
    138 func TestGoroutineParallelism2(t *testing.T) {
    139 	//testGoroutineParallelism2(t, false, false)
    140 	testGoroutineParallelism2(t, true, false)
    141 	testGoroutineParallelism2(t, false, true)
    142 	testGoroutineParallelism2(t, true, true)
    143 }
    144 
    145 func testGoroutineParallelism2(t *testing.T, load, netpoll bool) {
    146 	if runtime.NumCPU() == 1 {
    147 		// Takes too long, too easy to deadlock, etc.
    148 		t.Skip("skipping on uniprocessor")
    149 	}
    150 	P := 4
    151 	N := 10
    152 	if testing.Short() {
    153 		N = 3
    154 	}
    155 	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(P))
    156 	// If runtime triggers a forced GC during this test then it will deadlock,
    157 	// since the goroutines can't be stopped/preempted.
    158 	// Disable GC for this test (see issue #10958).
    159 	defer debug.SetGCPercent(debug.SetGCPercent(-1))
    160 	for try := 0; try < N; try++ {
    161 		if load {
    162 			// Create P goroutines and wait until they all run.
    163 			// When we run the actual test below, worker threads
    164 			// running the goroutines will start parking.
    165 			done := make(chan bool)
    166 			x := uint32(0)
    167 			for p := 0; p < P; p++ {
    168 				go func() {
    169 					if atomic.AddUint32(&x, 1) == uint32(P) {
    170 						done <- true
    171 						return
    172 					}
    173 					for atomic.LoadUint32(&x) != uint32(P) {
    174 					}
    175 				}()
    176 			}
    177 			<-done
    178 		}
    179 		if netpoll {
    180 			// Enable netpoller, affects schedler behavior.
    181 			laddr := "localhost:0"
    182 			if runtime.GOOS == "android" {
    183 				// On some Android devices, there are no records for localhost,
    184 				// see https://golang.org/issues/14486.
    185 				// Don't use 127.0.0.1 for every case, it won't work on IPv6-only systems.
    186 				laddr = "127.0.0.1:0"
    187 			}
    188 			ln, err := net.Listen("tcp", laddr)
    189 			if err != nil {
    190 				defer ln.Close() // yup, defer in a loop
    191 			}
    192 		}
    193 		done := make(chan bool)
    194 		x := uint32(0)
    195 		// Spawn P goroutines in a nested fashion just to differ from TestGoroutineParallelism.
    196 		for p := 0; p < P/2; p++ {
    197 			go func(p int) {
    198 				for p2 := 0; p2 < 2; p2++ {
    199 					go func(p2 int) {
    200 						for i := 0; i < 3; i++ {
    201 							expected := uint32(P*i + p*2 + p2)
    202 							for atomic.LoadUint32(&x) != expected {
    203 							}
    204 							atomic.StoreUint32(&x, expected+1)
    205 						}
    206 						done <- true
    207 					}(p2)
    208 				}
    209 			}(p)
    210 		}
    211 		for p := 0; p < P; p++ {
    212 			<-done
    213 		}
    214 	}
    215 }
    216 
    217 func TestBlockLocked(t *testing.T) {
    218 	const N = 10
    219 	c := make(chan bool)
    220 	go func() {
    221 		runtime.LockOSThread()
    222 		for i := 0; i < N; i++ {
    223 			c <- true
    224 		}
    225 		runtime.UnlockOSThread()
    226 	}()
    227 	for i := 0; i < N; i++ {
    228 		<-c
    229 	}
    230 }
    231 
    232 func TestTimerFairness(t *testing.T) {
    233 	done := make(chan bool)
    234 	c := make(chan bool)
    235 	for i := 0; i < 2; i++ {
    236 		go func() {
    237 			for {
    238 				select {
    239 				case c <- true:
    240 				case <-done:
    241 					return
    242 				}
    243 			}
    244 		}()
    245 	}
    246 
    247 	timer := time.After(20 * time.Millisecond)
    248 	for {
    249 		select {
    250 		case <-c:
    251 		case <-timer:
    252 			close(done)
    253 			return
    254 		}
    255 	}
    256 }
    257 
    258 func TestTimerFairness2(t *testing.T) {
    259 	done := make(chan bool)
    260 	c := make(chan bool)
    261 	for i := 0; i < 2; i++ {
    262 		go func() {
    263 			timer := time.After(20 * time.Millisecond)
    264 			var buf [1]byte
    265 			for {
    266 				syscall.Read(0, buf[0:0])
    267 				select {
    268 				case c <- true:
    269 				case <-c:
    270 				case <-timer:
    271 					done <- true
    272 					return
    273 				}
    274 			}
    275 		}()
    276 	}
    277 	<-done
    278 	<-done
    279 }
    280 
    281 // The function is used to test preemption at split stack checks.
    282 // Declaring a var avoids inlining at the call site.
    283 var preempt = func() int {
    284 	var a [128]int
    285 	sum := 0
    286 	for _, v := range a {
    287 		sum += v
    288 	}
    289 	return sum
    290 }
    291 
    292 func TestPreemption(t *testing.T) {
    293 	// Test that goroutines are preempted at function calls.
    294 	N := 5
    295 	if testing.Short() {
    296 		N = 2
    297 	}
    298 	c := make(chan bool)
    299 	var x uint32
    300 	for g := 0; g < 2; g++ {
    301 		go func(g int) {
    302 			for i := 0; i < N; i++ {
    303 				for atomic.LoadUint32(&x) != uint32(g) {
    304 					preempt()
    305 				}
    306 				atomic.StoreUint32(&x, uint32(1-g))
    307 			}
    308 			c <- true
    309 		}(g)
    310 	}
    311 	<-c
    312 	<-c
    313 }
    314 
    315 func TestPreemptionGC(t *testing.T) {
    316 	// Test that pending GC preempts running goroutines.
    317 	P := 5
    318 	N := 10
    319 	if testing.Short() {
    320 		P = 3
    321 		N = 2
    322 	}
    323 	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(P + 1))
    324 	var stop uint32
    325 	for i := 0; i < P; i++ {
    326 		go func() {
    327 			for atomic.LoadUint32(&stop) == 0 {
    328 				preempt()
    329 			}
    330 		}()
    331 	}
    332 	for i := 0; i < N; i++ {
    333 		runtime.Gosched()
    334 		runtime.GC()
    335 	}
    336 	atomic.StoreUint32(&stop, 1)
    337 }
    338 
    339 func TestGCFairness(t *testing.T) {
    340 	output := runTestProg(t, "testprog", "GCFairness")
    341 	want := "OK\n"
    342 	if output != want {
    343 		t.Fatalf("want %s, got %s\n", want, output)
    344 	}
    345 }
    346 
    347 func TestGCFairness2(t *testing.T) {
    348 	output := runTestProg(t, "testprog", "GCFairness2")
    349 	want := "OK\n"
    350 	if output != want {
    351 		t.Fatalf("want %s, got %s\n", want, output)
    352 	}
    353 }
    354 
    355 func TestNumGoroutine(t *testing.T) {
    356 	output := runTestProg(t, "testprog", "NumGoroutine")
    357 	want := "1\n"
    358 	if output != want {
    359 		t.Fatalf("want %q, got %q", want, output)
    360 	}
    361 
    362 	buf := make([]byte, 1<<20)
    363 
    364 	// Try up to 10 times for a match before giving up.
    365 	// This is a fundamentally racy check but it's important
    366 	// to notice if NumGoroutine and Stack are _always_ out of sync.
    367 	for i := 0; ; i++ {
    368 		// Give goroutines about to exit a chance to exit.
    369 		// The NumGoroutine and Stack below need to see
    370 		// the same state of the world, so anything we can do
    371 		// to keep it quiet is good.
    372 		runtime.Gosched()
    373 
    374 		n := runtime.NumGoroutine()
    375 		buf = buf[:runtime.Stack(buf, true)]
    376 
    377 		nstk := strings.Count(string(buf), "goroutine ")
    378 		if n == nstk {
    379 			break
    380 		}
    381 		if i >= 10 {
    382 			t.Fatalf("NumGoroutine=%d, but found %d goroutines in stack dump: %s", n, nstk, buf)
    383 		}
    384 	}
    385 }
    386 
    387 func TestPingPongHog(t *testing.T) {
    388 	if testing.Short() {
    389 		t.Skip("skipping in -short mode")
    390 	}
    391 
    392 	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(1))
    393 	done := make(chan bool)
    394 	hogChan, lightChan := make(chan bool), make(chan bool)
    395 	hogCount, lightCount := 0, 0
    396 
    397 	run := func(limit int, counter *int, wake chan bool) {
    398 		for {
    399 			select {
    400 			case <-done:
    401 				return
    402 
    403 			case <-wake:
    404 				for i := 0; i < limit; i++ {
    405 					*counter++
    406 				}
    407 				wake <- true
    408 			}
    409 		}
    410 	}
    411 
    412 	// Start two co-scheduled hog goroutines.
    413 	for i := 0; i < 2; i++ {
    414 		go run(1e6, &hogCount, hogChan)
    415 	}
    416 
    417 	// Start two co-scheduled light goroutines.
    418 	for i := 0; i < 2; i++ {
    419 		go run(1e3, &lightCount, lightChan)
    420 	}
    421 
    422 	// Start goroutine pairs and wait for a few preemption rounds.
    423 	hogChan <- true
    424 	lightChan <- true
    425 	time.Sleep(100 * time.Millisecond)
    426 	close(done)
    427 	<-hogChan
    428 	<-lightChan
    429 
    430 	// Check that hogCount and lightCount are within a factor of
    431 	// 5, which indicates that both pairs of goroutines handed off
    432 	// the P within a time-slice to their buddy. We can use a
    433 	// fairly large factor here to make this robust: if the
    434 	// scheduler isn't working right, the gap should be ~1000X.
    435 	const factor = 5
    436 	if hogCount > lightCount*factor || lightCount > hogCount*factor {
    437 		t.Fatalf("want hogCount/lightCount in [%v, %v]; got %d/%d = %g", 1.0/factor, factor, hogCount, lightCount, float64(hogCount)/float64(lightCount))
    438 	}
    439 }
    440 
    441 func BenchmarkPingPongHog(b *testing.B) {
    442 	if b.N == 0 {
    443 		return
    444 	}
    445 	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(1))
    446 
    447 	// Create a CPU hog
    448 	stop, done := make(chan bool), make(chan bool)
    449 	go func() {
    450 		for {
    451 			select {
    452 			case <-stop:
    453 				done <- true
    454 				return
    455 			default:
    456 			}
    457 		}
    458 	}()
    459 
    460 	// Ping-pong b.N times
    461 	ping, pong := make(chan bool), make(chan bool)
    462 	go func() {
    463 		for j := 0; j < b.N; j++ {
    464 			pong <- <-ping
    465 		}
    466 		close(stop)
    467 		done <- true
    468 	}()
    469 	go func() {
    470 		for i := 0; i < b.N; i++ {
    471 			ping <- <-pong
    472 		}
    473 		done <- true
    474 	}()
    475 	b.ResetTimer()
    476 	ping <- true // Start ping-pong
    477 	<-stop
    478 	b.StopTimer()
    479 	<-ping // Let last ponger exit
    480 	<-done // Make sure goroutines exit
    481 	<-done
    482 	<-done
    483 }
    484 
    485 func stackGrowthRecursive(i int) {
    486 	var pad [128]uint64
    487 	if i != 0 && pad[0] == 0 {
    488 		stackGrowthRecursive(i - 1)
    489 	}
    490 }
    491 
    492 func TestPreemptSplitBig(t *testing.T) {
    493 	if testing.Short() {
    494 		t.Skip("skipping in -short mode")
    495 	}
    496 	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(2))
    497 	stop := make(chan int)
    498 	go big(stop)
    499 	for i := 0; i < 3; i++ {
    500 		time.Sleep(10 * time.Microsecond) // let big start running
    501 		runtime.GC()
    502 	}
    503 	close(stop)
    504 }
    505 
    506 func big(stop chan int) int {
    507 	n := 0
    508 	for {
    509 		// delay so that gc is sure to have asked for a preemption
    510 		for i := 0; i < 1e9; i++ {
    511 			n++
    512 		}
    513 
    514 		// call bigframe, which used to miss the preemption in its prologue.
    515 		bigframe(stop)
    516 
    517 		// check if we've been asked to stop.
    518 		select {
    519 		case <-stop:
    520 			return n
    521 		}
    522 	}
    523 }
    524 
    525 func bigframe(stop chan int) int {
    526 	// not splitting the stack will overflow.
    527 	// small will notice that it needs a stack split and will
    528 	// catch the overflow.
    529 	var x [8192]byte
    530 	return small(stop, &x)
    531 }
    532 
    533 func small(stop chan int, x *[8192]byte) int {
    534 	for i := range x {
    535 		x[i] = byte(i)
    536 	}
    537 	sum := 0
    538 	for i := range x {
    539 		sum += int(x[i])
    540 	}
    541 
    542 	// keep small from being a leaf function, which might
    543 	// make it not do any stack check at all.
    544 	nonleaf(stop)
    545 
    546 	return sum
    547 }
    548 
    549 func nonleaf(stop chan int) bool {
    550 	// do something that won't be inlined:
    551 	select {
    552 	case <-stop:
    553 		return true
    554 	default:
    555 		return false
    556 	}
    557 }
    558 
    559 func TestSchedLocalQueue(t *testing.T) {
    560 	runtime.RunSchedLocalQueueTest()
    561 }
    562 
    563 func TestSchedLocalQueueSteal(t *testing.T) {
    564 	runtime.RunSchedLocalQueueStealTest()
    565 }
    566 
    567 func TestSchedLocalQueueEmpty(t *testing.T) {
    568 	if runtime.NumCPU() == 1 {
    569 		// Takes too long and does not trigger the race.
    570 		t.Skip("skipping on uniprocessor")
    571 	}
    572 	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
    573 
    574 	// If runtime triggers a forced GC during this test then it will deadlock,
    575 	// since the goroutines can't be stopped/preempted during spin wait.
    576 	defer debug.SetGCPercent(debug.SetGCPercent(-1))
    577 
    578 	iters := int(1e5)
    579 	if testing.Short() {
    580 		iters = 1e2
    581 	}
    582 	runtime.RunSchedLocalQueueEmptyTest(iters)
    583 }
    584 
    585 func benchmarkStackGrowth(b *testing.B, rec int) {
    586 	b.RunParallel(func(pb *testing.PB) {
    587 		for pb.Next() {
    588 			stackGrowthRecursive(rec)
    589 		}
    590 	})
    591 }
    592 
    593 func BenchmarkStackGrowth(b *testing.B) {
    594 	benchmarkStackGrowth(b, 10)
    595 }
    596 
    597 func BenchmarkStackGrowthDeep(b *testing.B) {
    598 	benchmarkStackGrowth(b, 1024)
    599 }
    600 
    601 func BenchmarkCreateGoroutines(b *testing.B) {
    602 	benchmarkCreateGoroutines(b, 1)
    603 }
    604 
    605 func BenchmarkCreateGoroutinesParallel(b *testing.B) {
    606 	benchmarkCreateGoroutines(b, runtime.GOMAXPROCS(-1))
    607 }
    608 
    609 func benchmarkCreateGoroutines(b *testing.B, procs int) {
    610 	c := make(chan bool)
    611 	var f func(n int)
    612 	f = func(n int) {
    613 		if n == 0 {
    614 			c <- true
    615 			return
    616 		}
    617 		go f(n - 1)
    618 	}
    619 	for i := 0; i < procs; i++ {
    620 		go f(b.N / procs)
    621 	}
    622 	for i := 0; i < procs; i++ {
    623 		<-c
    624 	}
    625 }
    626 
    627 func BenchmarkCreateGoroutinesCapture(b *testing.B) {
    628 	b.ReportAllocs()
    629 	for i := 0; i < b.N; i++ {
    630 		const N = 4
    631 		var wg sync.WaitGroup
    632 		wg.Add(N)
    633 		for i := 0; i < N; i++ {
    634 			i := i
    635 			go func() {
    636 				if i >= N {
    637 					b.Logf("bad") // just to capture b
    638 				}
    639 				wg.Done()
    640 			}()
    641 		}
    642 		wg.Wait()
    643 	}
    644 }
    645 
    646 func BenchmarkClosureCall(b *testing.B) {
    647 	sum := 0
    648 	off1 := 1
    649 	for i := 0; i < b.N; i++ {
    650 		off2 := 2
    651 		func() {
    652 			sum += i + off1 + off2
    653 		}()
    654 	}
    655 	_ = sum
    656 }
    657 
    658 func benchmarkWakeupParallel(b *testing.B, spin func(time.Duration)) {
    659 	if runtime.GOMAXPROCS(0) == 1 {
    660 		b.Skip("skipping: GOMAXPROCS=1")
    661 	}
    662 
    663 	wakeDelay := 5 * time.Microsecond
    664 	for _, delay := range []time.Duration{
    665 		0,
    666 		1 * time.Microsecond,
    667 		2 * time.Microsecond,
    668 		5 * time.Microsecond,
    669 		10 * time.Microsecond,
    670 		20 * time.Microsecond,
    671 		50 * time.Microsecond,
    672 		100 * time.Microsecond,
    673 	} {
    674 		b.Run(delay.String(), func(b *testing.B) {
    675 			if b.N == 0 {
    676 				return
    677 			}
    678 			// Start two goroutines, which alternate between being
    679 			// sender and receiver in the following protocol:
    680 			//
    681 			// - The receiver spins for `delay` and then does a
    682 			// blocking receive on a channel.
    683 			//
    684 			// - The sender spins for `delay+wakeDelay` and then
    685 			// sends to the same channel. (The addition of
    686 			// `wakeDelay` improves the probability that the
    687 			// receiver will be blocking when the send occurs when
    688 			// the goroutines execute in parallel.)
    689 			//
    690 			// In each iteration of the benchmark, each goroutine
    691 			// acts once as sender and once as receiver, so each
    692 			// goroutine spins for delay twice.
    693 			//
    694 			// BenchmarkWakeupParallel is used to estimate how
    695 			// efficiently the scheduler parallelizes goroutines in
    696 			// the presence of blocking:
    697 			//
    698 			// - If both goroutines are executed on the same core,
    699 			// an increase in delay by N will increase the time per
    700 			// iteration by 4*N, because all 4 delays are
    701 			// serialized.
    702 			//
    703 			// - Otherwise, an increase in delay by N will increase
    704 			// the time per iteration by 2*N, and the time per
    705 			// iteration is 2 * (runtime overhead + chan
    706 			// send/receive pair + delay + wakeDelay). This allows
    707 			// the runtime overhead, including the time it takes
    708 			// for the unblocked goroutine to be scheduled, to be
    709 			// estimated.
    710 			ping, pong := make(chan struct{}), make(chan struct{})
    711 			start := make(chan struct{})
    712 			done := make(chan struct{})
    713 			go func() {
    714 				<-start
    715 				for i := 0; i < b.N; i++ {
    716 					// sender
    717 					spin(delay + wakeDelay)
    718 					ping <- struct{}{}
    719 					// receiver
    720 					spin(delay)
    721 					<-pong
    722 				}
    723 				done <- struct{}{}
    724 			}()
    725 			go func() {
    726 				for i := 0; i < b.N; i++ {
    727 					// receiver
    728 					spin(delay)
    729 					<-ping
    730 					// sender
    731 					spin(delay + wakeDelay)
    732 					pong <- struct{}{}
    733 				}
    734 				done <- struct{}{}
    735 			}()
    736 			b.ResetTimer()
    737 			start <- struct{}{}
    738 			<-done
    739 			<-done
    740 		})
    741 	}
    742 }
    743 
    744 func BenchmarkWakeupParallelSpinning(b *testing.B) {
    745 	benchmarkWakeupParallel(b, func(d time.Duration) {
    746 		end := time.Now().Add(d)
    747 		for time.Now().Before(end) {
    748 			// do nothing
    749 		}
    750 	})
    751 }
    752 
    753 // sysNanosleep is defined by OS-specific files (such as runtime_linux_test.go)
    754 // to sleep for the given duration. If nil, dependent tests are skipped.
    755 // The implementation should invoke a blocking system call and not
    756 // call time.Sleep, which would deschedule the goroutine.
    757 var sysNanosleep func(d time.Duration)
    758 
    759 func BenchmarkWakeupParallelSyscall(b *testing.B) {
    760 	if sysNanosleep == nil {
    761 		b.Skipf("skipping on %v; sysNanosleep not defined", runtime.GOOS)
    762 	}
    763 	benchmarkWakeupParallel(b, func(d time.Duration) {
    764 		sysNanosleep(d)
    765 	})
    766 }
    767 
    768 type Matrix [][]float64
    769 
    770 func BenchmarkMatmult(b *testing.B) {
    771 	b.StopTimer()
    772 	// matmult is O(N**3) but testing expects O(b.N),
    773 	// so we need to take cube root of b.N
    774 	n := int(math.Cbrt(float64(b.N))) + 1
    775 	A := makeMatrix(n)
    776 	B := makeMatrix(n)
    777 	C := makeMatrix(n)
    778 	b.StartTimer()
    779 	matmult(nil, A, B, C, 0, n, 0, n, 0, n, 8)
    780 }
    781 
    782 func makeMatrix(n int) Matrix {
    783 	m := make(Matrix, n)
    784 	for i := 0; i < n; i++ {
    785 		m[i] = make([]float64, n)
    786 		for j := 0; j < n; j++ {
    787 			m[i][j] = float64(i*n + j)
    788 		}
    789 	}
    790 	return m
    791 }
    792 
    793 func matmult(done chan<- struct{}, A, B, C Matrix, i0, i1, j0, j1, k0, k1, threshold int) {
    794 	di := i1 - i0
    795 	dj := j1 - j0
    796 	dk := k1 - k0
    797 	if di >= dj && di >= dk && di >= threshold {
    798 		// divide in two by y axis
    799 		mi := i0 + di/2
    800 		done1 := make(chan struct{}, 1)
    801 		go matmult(done1, A, B, C, i0, mi, j0, j1, k0, k1, threshold)
    802 		matmult(nil, A, B, C, mi, i1, j0, j1, k0, k1, threshold)
    803 		<-done1
    804 	} else if dj >= dk && dj >= threshold {
    805 		// divide in two by x axis
    806 		mj := j0 + dj/2
    807 		done1 := make(chan struct{}, 1)
    808 		go matmult(done1, A, B, C, i0, i1, j0, mj, k0, k1, threshold)
    809 		matmult(nil, A, B, C, i0, i1, mj, j1, k0, k1, threshold)
    810 		<-done1
    811 	} else if dk >= threshold {
    812 		// divide in two by "k" axis
    813 		// deliberately not parallel because of data races
    814 		mk := k0 + dk/2
    815 		matmult(nil, A, B, C, i0, i1, j0, j1, k0, mk, threshold)
    816 		matmult(nil, A, B, C, i0, i1, j0, j1, mk, k1, threshold)
    817 	} else {
    818 		// the matrices are small enough, compute directly
    819 		for i := i0; i < i1; i++ {
    820 			for j := j0; j < j1; j++ {
    821 				for k := k0; k < k1; k++ {
    822 					C[i][j] += A[i][k] * B[k][j]
    823 				}
    824 			}
    825 		}
    826 	}
    827 	if done != nil {
    828 		done <- struct{}{}
    829 	}
    830 }
    831 
    832 func TestStealOrder(t *testing.T) {
    833 	runtime.RunStealOrderTest()
    834 }
    835 
    836 func TestLockOSThreadNesting(t *testing.T) {
    837 	go func() {
    838 		e, i := runtime.LockOSCounts()
    839 		if e != 0 || i != 0 {
    840 			t.Errorf("want locked counts 0, 0; got %d, %d", e, i)
    841 			return
    842 		}
    843 		runtime.LockOSThread()
    844 		runtime.LockOSThread()
    845 		runtime.UnlockOSThread()
    846 		e, i = runtime.LockOSCounts()
    847 		if e != 1 || i != 0 {
    848 			t.Errorf("want locked counts 1, 0; got %d, %d", e, i)
    849 			return
    850 		}
    851 		runtime.UnlockOSThread()
    852 		e, i = runtime.LockOSCounts()
    853 		if e != 0 || i != 0 {
    854 			t.Errorf("want locked counts 0, 0; got %d, %d", e, i)
    855 			return
    856 		}
    857 	}()
    858 }
    859 
    860 func TestLockOSThreadExit(t *testing.T) {
    861 	testLockOSThreadExit(t, "testprog")
    862 }
    863 
    864 func testLockOSThreadExit(t *testing.T, prog string) {
    865 	output := runTestProg(t, prog, "LockOSThreadMain", "GOMAXPROCS=1")
    866 	want := "OK\n"
    867 	if output != want {
    868 		t.Errorf("want %s, got %s\n", want, output)
    869 	}
    870 
    871 	output = runTestProg(t, prog, "LockOSThreadAlt")
    872 	if output != want {
    873 		t.Errorf("want %s, got %s\n", want, output)
    874 	}
    875 }
    876