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
5package runtime_test
6
7import (
8	"fmt"
9	"internal/race"
10	"internal/testenv"
11	"math"
12	"net"
13	"runtime"
14	"runtime/debug"
15	"strings"
16	"sync"
17	"sync/atomic"
18	"syscall"
19	"testing"
20	"time"
21)
22
23var stop = make(chan bool, 1)
24
25func perpetuumMobile() {
26	select {
27	case <-stop:
28	default:
29		go perpetuumMobile()
30	}
31}
32
33func TestStopTheWorldDeadlock(t *testing.T) {
34	if runtime.GOARCH == "wasm" {
35		t.Skip("no preemption on wasm yet")
36	}
37	if testing.Short() {
38		t.Skip("skipping during short test")
39	}
40	maxprocs := runtime.GOMAXPROCS(3)
41	compl := make(chan bool, 2)
42	go func() {
43		for i := 0; i != 1000; i += 1 {
44			runtime.GC()
45		}
46		compl <- true
47	}()
48	go func() {
49		for i := 0; i != 1000; i += 1 {
50			runtime.GOMAXPROCS(3)
51		}
52		compl <- true
53	}()
54	go perpetuumMobile()
55	<-compl
56	<-compl
57	stop <- true
58	runtime.GOMAXPROCS(maxprocs)
59}
60
61func TestYieldProgress(t *testing.T) {
62	testYieldProgress(false)
63}
64
65func TestYieldLockedProgress(t *testing.T) {
66	testYieldProgress(true)
67}
68
69func testYieldProgress(locked bool) {
70	c := make(chan bool)
71	cack := make(chan bool)
72	go func() {
73		if locked {
74			runtime.LockOSThread()
75		}
76		for {
77			select {
78			case <-c:
79				cack <- true
80				return
81			default:
82				runtime.Gosched()
83			}
84		}
85	}()
86	time.Sleep(10 * time.Millisecond)
87	c <- true
88	<-cack
89}
90
91func TestYieldLocked(t *testing.T) {
92	const N = 10
93	c := make(chan bool)
94	go func() {
95		runtime.LockOSThread()
96		for i := 0; i < N; i++ {
97			runtime.Gosched()
98			time.Sleep(time.Millisecond)
99		}
100		c <- true
101		// runtime.UnlockOSThread() is deliberately omitted
102	}()
103	<-c
104}
105
106func TestGoroutineParallelism(t *testing.T) {
107	if runtime.NumCPU() == 1 {
108		// Takes too long, too easy to deadlock, etc.
109		t.Skip("skipping on uniprocessor")
110	}
111	P := 4
112	N := 10
113	if testing.Short() {
114		P = 3
115		N = 3
116	}
117	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(P))
118	// If runtime triggers a forced GC during this test then it will deadlock,
119	// since the goroutines can't be stopped/preempted.
120	// Disable GC for this test (see issue #10958).
121	defer debug.SetGCPercent(debug.SetGCPercent(-1))
122	// SetGCPercent waits until the mark phase is over, but the runtime
123	// also preempts at the start of the sweep phase, so make sure that's
124	// done too. See #45867.
125	runtime.GC()
126	for try := 0; try < N; try++ {
127		done := make(chan bool)
128		x := uint32(0)
129		for p := 0; p < P; p++ {
130			// Test that all P goroutines are scheduled at the same time
131			go func(p int) {
132				for i := 0; i < 3; i++ {
133					expected := uint32(P*i + p)
134					for atomic.LoadUint32(&x) != expected {
135					}
136					atomic.StoreUint32(&x, expected+1)
137				}
138				done <- true
139			}(p)
140		}
141		for p := 0; p < P; p++ {
142			<-done
143		}
144	}
145}
146
147// Test that all runnable goroutines are scheduled at the same time.
148func TestGoroutineParallelism2(t *testing.T) {
149	//testGoroutineParallelism2(t, false, false)
150	testGoroutineParallelism2(t, true, false)
151	testGoroutineParallelism2(t, false, true)
152	testGoroutineParallelism2(t, true, true)
153}
154
155func testGoroutineParallelism2(t *testing.T, load, netpoll bool) {
156	if runtime.NumCPU() == 1 {
157		// Takes too long, too easy to deadlock, etc.
158		t.Skip("skipping on uniprocessor")
159	}
160	P := 4
161	N := 10
162	if testing.Short() {
163		N = 3
164	}
165	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(P))
166	// If runtime triggers a forced GC during this test then it will deadlock,
167	// since the goroutines can't be stopped/preempted.
168	// Disable GC for this test (see issue #10958).
169	defer debug.SetGCPercent(debug.SetGCPercent(-1))
170	// SetGCPercent waits until the mark phase is over, but the runtime
171	// also preempts at the start of the sweep phase, so make sure that's
172	// done too. See #45867.
173	runtime.GC()
174	for try := 0; try < N; try++ {
175		if load {
176			// Create P goroutines and wait until they all run.
177			// When we run the actual test below, worker threads
178			// running the goroutines will start parking.
179			done := make(chan bool)
180			x := uint32(0)
181			for p := 0; p < P; p++ {
182				go func() {
183					if atomic.AddUint32(&x, 1) == uint32(P) {
184						done <- true
185						return
186					}
187					for atomic.LoadUint32(&x) != uint32(P) {
188					}
189				}()
190			}
191			<-done
192		}
193		if netpoll {
194			// Enable netpoller, affects schedler behavior.
195			laddr := "localhost:0"
196			if runtime.GOOS == "android" {
197				// On some Android devices, there are no records for localhost,
198				// see https://golang.org/issues/14486.
199				// Don't use 127.0.0.1 for every case, it won't work on IPv6-only systems.
200				laddr = "127.0.0.1:0"
201			}
202			ln, err := net.Listen("tcp", laddr)
203			if err == nil {
204				defer ln.Close() // yup, defer in a loop
205			}
206		}
207		done := make(chan bool)
208		x := uint32(0)
209		// Spawn P goroutines in a nested fashion just to differ from TestGoroutineParallelism.
210		for p := 0; p < P/2; p++ {
211			go func(p int) {
212				for p2 := 0; p2 < 2; p2++ {
213					go func(p2 int) {
214						for i := 0; i < 3; i++ {
215							expected := uint32(P*i + p*2 + p2)
216							for atomic.LoadUint32(&x) != expected {
217							}
218							atomic.StoreUint32(&x, expected+1)
219						}
220						done <- true
221					}(p2)
222				}
223			}(p)
224		}
225		for p := 0; p < P; p++ {
226			<-done
227		}
228	}
229}
230
231func TestBlockLocked(t *testing.T) {
232	const N = 10
233	c := make(chan bool)
234	go func() {
235		runtime.LockOSThread()
236		for i := 0; i < N; i++ {
237			c <- true
238		}
239		runtime.UnlockOSThread()
240	}()
241	for i := 0; i < N; i++ {
242		<-c
243	}
244}
245
246func TestTimerFairness(t *testing.T) {
247	if runtime.GOARCH == "wasm" {
248		t.Skip("no preemption on wasm yet")
249	}
250
251	done := make(chan bool)
252	c := make(chan bool)
253	for i := 0; i < 2; i++ {
254		go func() {
255			for {
256				select {
257				case c <- true:
258				case <-done:
259					return
260				}
261			}
262		}()
263	}
264
265	timer := time.After(20 * time.Millisecond)
266	for {
267		select {
268		case <-c:
269		case <-timer:
270			close(done)
271			return
272		}
273	}
274}
275
276func TestTimerFairness2(t *testing.T) {
277	if runtime.GOARCH == "wasm" {
278		t.Skip("no preemption on wasm yet")
279	}
280
281	done := make(chan bool)
282	c := make(chan bool)
283	for i := 0; i < 2; i++ {
284		go func() {
285			timer := time.After(20 * time.Millisecond)
286			var buf [1]byte
287			for {
288				syscall.Read(0, buf[0:0])
289				select {
290				case c <- true:
291				case <-c:
292				case <-timer:
293					done <- true
294					return
295				}
296			}
297		}()
298	}
299	<-done
300	<-done
301}
302
303// The function is used to test preemption at split stack checks.
304// Declaring a var avoids inlining at the call site.
305var preempt = func() int {
306	var a [128]int
307	sum := 0
308	for _, v := range a {
309		sum += v
310	}
311	return sum
312}
313
314func TestPreemption(t *testing.T) {
315	if runtime.GOARCH == "wasm" {
316		t.Skip("no preemption on wasm yet")
317	}
318
319	// Test that goroutines are preempted at function calls.
320	N := 5
321	if testing.Short() {
322		N = 2
323	}
324	c := make(chan bool)
325	var x uint32
326	for g := 0; g < 2; g++ {
327		go func(g int) {
328			for i := 0; i < N; i++ {
329				for atomic.LoadUint32(&x) != uint32(g) {
330					preempt()
331				}
332				atomic.StoreUint32(&x, uint32(1-g))
333			}
334			c <- true
335		}(g)
336	}
337	<-c
338	<-c
339}
340
341func TestPreemptionGC(t *testing.T) {
342	if runtime.GOARCH == "wasm" {
343		t.Skip("no preemption on wasm yet")
344	}
345
346	// Test that pending GC preempts running goroutines.
347	P := 5
348	N := 10
349	if testing.Short() {
350		P = 3
351		N = 2
352	}
353	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(P + 1))
354	var stop uint32
355	for i := 0; i < P; i++ {
356		go func() {
357			for atomic.LoadUint32(&stop) == 0 {
358				preempt()
359			}
360		}()
361	}
362	for i := 0; i < N; i++ {
363		runtime.Gosched()
364		runtime.GC()
365	}
366	atomic.StoreUint32(&stop, 1)
367}
368
369func TestAsyncPreempt(t *testing.T) {
370	if !runtime.PreemptMSupported {
371		t.Skip("asynchronous preemption not supported on this platform")
372	}
373	output := runTestProg(t, "testprog", "AsyncPreempt")
374	want := "OK\n"
375	if output != want {
376		t.Fatalf("want %s, got %s\n", want, output)
377	}
378}
379
380func TestGCFairness(t *testing.T) {
381	output := runTestProg(t, "testprog", "GCFairness")
382	want := "OK\n"
383	if output != want {
384		t.Fatalf("want %s, got %s\n", want, output)
385	}
386}
387
388func TestGCFairness2(t *testing.T) {
389	output := runTestProg(t, "testprog", "GCFairness2")
390	want := "OK\n"
391	if output != want {
392		t.Fatalf("want %s, got %s\n", want, output)
393	}
394}
395
396func TestNumGoroutine(t *testing.T) {
397	output := runTestProg(t, "testprog", "NumGoroutine")
398	want := "1\n"
399	if output != want {
400		t.Fatalf("want %q, got %q", want, output)
401	}
402
403	buf := make([]byte, 1<<20)
404
405	// Try up to 10 times for a match before giving up.
406	// This is a fundamentally racy check but it's important
407	// to notice if NumGoroutine and Stack are _always_ out of sync.
408	for i := 0; ; i++ {
409		// Give goroutines about to exit a chance to exit.
410		// The NumGoroutine and Stack below need to see
411		// the same state of the world, so anything we can do
412		// to keep it quiet is good.
413		runtime.Gosched()
414
415		n := runtime.NumGoroutine()
416		buf = buf[:runtime.Stack(buf, true)]
417
418		// To avoid double-counting "goroutine" in "goroutine $m [running]:"
419		// and "created by $func in goroutine $n", remove the latter
420		output := strings.ReplaceAll(string(buf), "in goroutine", "")
421		nstk := strings.Count(output, "goroutine ")
422		if n == nstk {
423			break
424		}
425		if i >= 10 {
426			t.Fatalf("NumGoroutine=%d, but found %d goroutines in stack dump: %s", n, nstk, buf)
427		}
428	}
429}
430
431func TestPingPongHog(t *testing.T) {
432	if runtime.GOARCH == "wasm" {
433		t.Skip("no preemption on wasm yet")
434	}
435	if testing.Short() {
436		t.Skip("skipping in -short mode")
437	}
438	if race.Enabled {
439		// The race detector randomizes the scheduler,
440		// which causes this test to fail (#38266).
441		t.Skip("skipping in -race mode")
442	}
443
444	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(1))
445	done := make(chan bool)
446	hogChan, lightChan := make(chan bool), make(chan bool)
447	hogCount, lightCount := 0, 0
448
449	run := func(limit int, counter *int, wake chan bool) {
450		for {
451			select {
452			case <-done:
453				return
454
455			case <-wake:
456				for i := 0; i < limit; i++ {
457					*counter++
458				}
459				wake <- true
460			}
461		}
462	}
463
464	// Start two co-scheduled hog goroutines.
465	for i := 0; i < 2; i++ {
466		go run(1e6, &hogCount, hogChan)
467	}
468
469	// Start two co-scheduled light goroutines.
470	for i := 0; i < 2; i++ {
471		go run(1e3, &lightCount, lightChan)
472	}
473
474	// Start goroutine pairs and wait for a few preemption rounds.
475	hogChan <- true
476	lightChan <- true
477	time.Sleep(100 * time.Millisecond)
478	close(done)
479	<-hogChan
480	<-lightChan
481
482	// Check that hogCount and lightCount are within a factor of
483	// 20, which indicates that both pairs of goroutines handed off
484	// the P within a time-slice to their buddy. We can use a
485	// fairly large factor here to make this robust: if the
486	// scheduler isn't working right, the gap should be ~1000X
487	// (was 5, increased to 20, see issue 52207).
488	const factor = 20
489	if hogCount/factor > lightCount || lightCount/factor > hogCount {
490		t.Fatalf("want hogCount/lightCount in [%v, %v]; got %d/%d = %g", 1.0/factor, factor, hogCount, lightCount, float64(hogCount)/float64(lightCount))
491	}
492}
493
494func BenchmarkPingPongHog(b *testing.B) {
495	if b.N == 0 {
496		return
497	}
498	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(1))
499
500	// Create a CPU hog
501	stop, done := make(chan bool), make(chan bool)
502	go func() {
503		for {
504			select {
505			case <-stop:
506				done <- true
507				return
508			default:
509			}
510		}
511	}()
512
513	// Ping-pong b.N times
514	ping, pong := make(chan bool), make(chan bool)
515	go func() {
516		for j := 0; j < b.N; j++ {
517			pong <- <-ping
518		}
519		close(stop)
520		done <- true
521	}()
522	go func() {
523		for i := 0; i < b.N; i++ {
524			ping <- <-pong
525		}
526		done <- true
527	}()
528	b.ResetTimer()
529	ping <- true // Start ping-pong
530	<-stop
531	b.StopTimer()
532	<-ping // Let last ponger exit
533	<-done // Make sure goroutines exit
534	<-done
535	<-done
536}
537
538var padData [128]uint64
539
540func stackGrowthRecursive(i int) {
541	var pad [128]uint64
542	pad = padData
543	for j := range pad {
544		if pad[j] != 0 {
545			return
546		}
547	}
548	if i != 0 {
549		stackGrowthRecursive(i - 1)
550	}
551}
552
553func TestPreemptSplitBig(t *testing.T) {
554	if testing.Short() {
555		t.Skip("skipping in -short mode")
556	}
557	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(2))
558	stop := make(chan int)
559	go big(stop)
560	for i := 0; i < 3; i++ {
561		time.Sleep(10 * time.Microsecond) // let big start running
562		runtime.GC()
563	}
564	close(stop)
565}
566
567func big(stop chan int) int {
568	n := 0
569	for {
570		// delay so that gc is sure to have asked for a preemption
571		for i := 0; i < 1e9; i++ {
572			n++
573		}
574
575		// call bigframe, which used to miss the preemption in its prologue.
576		bigframe(stop)
577
578		// check if we've been asked to stop.
579		select {
580		case <-stop:
581			return n
582		}
583	}
584}
585
586func bigframe(stop chan int) int {
587	// not splitting the stack will overflow.
588	// small will notice that it needs a stack split and will
589	// catch the overflow.
590	var x [8192]byte
591	return small(stop, &x)
592}
593
594func small(stop chan int, x *[8192]byte) int {
595	for i := range x {
596		x[i] = byte(i)
597	}
598	sum := 0
599	for i := range x {
600		sum += int(x[i])
601	}
602
603	// keep small from being a leaf function, which might
604	// make it not do any stack check at all.
605	nonleaf(stop)
606
607	return sum
608}
609
610func nonleaf(stop chan int) bool {
611	// do something that won't be inlined:
612	select {
613	case <-stop:
614		return true
615	default:
616		return false
617	}
618}
619
620func TestSchedLocalQueue(t *testing.T) {
621	runtime.RunSchedLocalQueueTest()
622}
623
624func TestSchedLocalQueueSteal(t *testing.T) {
625	runtime.RunSchedLocalQueueStealTest()
626}
627
628func TestSchedLocalQueueEmpty(t *testing.T) {
629	if runtime.NumCPU() == 1 {
630		// Takes too long and does not trigger the race.
631		t.Skip("skipping on uniprocessor")
632	}
633	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
634
635	// If runtime triggers a forced GC during this test then it will deadlock,
636	// since the goroutines can't be stopped/preempted during spin wait.
637	defer debug.SetGCPercent(debug.SetGCPercent(-1))
638	// SetGCPercent waits until the mark phase is over, but the runtime
639	// also preempts at the start of the sweep phase, so make sure that's
640	// done too. See #45867.
641	runtime.GC()
642
643	iters := int(1e5)
644	if testing.Short() {
645		iters = 1e2
646	}
647	runtime.RunSchedLocalQueueEmptyTest(iters)
648}
649
650func benchmarkStackGrowth(b *testing.B, rec int) {
651	b.RunParallel(func(pb *testing.PB) {
652		for pb.Next() {
653			stackGrowthRecursive(rec)
654		}
655	})
656}
657
658func BenchmarkStackGrowth(b *testing.B) {
659	benchmarkStackGrowth(b, 10)
660}
661
662func BenchmarkStackGrowthDeep(b *testing.B) {
663	benchmarkStackGrowth(b, 1024)
664}
665
666func BenchmarkCreateGoroutines(b *testing.B) {
667	benchmarkCreateGoroutines(b, 1)
668}
669
670func BenchmarkCreateGoroutinesParallel(b *testing.B) {
671	benchmarkCreateGoroutines(b, runtime.GOMAXPROCS(-1))
672}
673
674func benchmarkCreateGoroutines(b *testing.B, procs int) {
675	c := make(chan bool)
676	var f func(n int)
677	f = func(n int) {
678		if n == 0 {
679			c <- true
680			return
681		}
682		go f(n - 1)
683	}
684	for i := 0; i < procs; i++ {
685		go f(b.N / procs)
686	}
687	for i := 0; i < procs; i++ {
688		<-c
689	}
690}
691
692func BenchmarkCreateGoroutinesCapture(b *testing.B) {
693	b.ReportAllocs()
694	for i := 0; i < b.N; i++ {
695		const N = 4
696		var wg sync.WaitGroup
697		wg.Add(N)
698		for i := 0; i < N; i++ {
699			i := i
700			go func() {
701				if i >= N {
702					b.Logf("bad") // just to capture b
703				}
704				wg.Done()
705			}()
706		}
707		wg.Wait()
708	}
709}
710
711// warmupScheduler ensures the scheduler has at least targetThreadCount threads
712// in its thread pool.
713func warmupScheduler(targetThreadCount int) {
714	var wg sync.WaitGroup
715	var count int32
716	for i := 0; i < targetThreadCount; i++ {
717		wg.Add(1)
718		go func() {
719			atomic.AddInt32(&count, 1)
720			for atomic.LoadInt32(&count) < int32(targetThreadCount) {
721				// spin until all threads started
722			}
723
724			// spin a bit more to ensure they are all running on separate CPUs.
725			doWork(time.Millisecond)
726			wg.Done()
727		}()
728	}
729	wg.Wait()
730}
731
732func doWork(dur time.Duration) {
733	start := time.Now()
734	for time.Since(start) < dur {
735	}
736}
737
738// BenchmarkCreateGoroutinesSingle creates many goroutines, all from a single
739// producer (the main benchmark goroutine).
740//
741// Compared to BenchmarkCreateGoroutines, this causes different behavior in the
742// scheduler because Ms are much more likely to need to steal work from the
743// main P rather than having work in the local run queue.
744func BenchmarkCreateGoroutinesSingle(b *testing.B) {
745	// Since we are interested in stealing behavior, warm the scheduler to
746	// get all the Ps running first.
747	warmupScheduler(runtime.GOMAXPROCS(0))
748	b.ResetTimer()
749
750	var wg sync.WaitGroup
751	wg.Add(b.N)
752	for i := 0; i < b.N; i++ {
753		go func() {
754			wg.Done()
755		}()
756	}
757	wg.Wait()
758}
759
760func BenchmarkClosureCall(b *testing.B) {
761	sum := 0
762	off1 := 1
763	for i := 0; i < b.N; i++ {
764		off2 := 2
765		func() {
766			sum += i + off1 + off2
767		}()
768	}
769	_ = sum
770}
771
772func benchmarkWakeupParallel(b *testing.B, spin func(time.Duration)) {
773	if runtime.GOMAXPROCS(0) == 1 {
774		b.Skip("skipping: GOMAXPROCS=1")
775	}
776
777	wakeDelay := 5 * time.Microsecond
778	for _, delay := range []time.Duration{
779		0,
780		1 * time.Microsecond,
781		2 * time.Microsecond,
782		5 * time.Microsecond,
783		10 * time.Microsecond,
784		20 * time.Microsecond,
785		50 * time.Microsecond,
786		100 * time.Microsecond,
787	} {
788		b.Run(delay.String(), func(b *testing.B) {
789			if b.N == 0 {
790				return
791			}
792			// Start two goroutines, which alternate between being
793			// sender and receiver in the following protocol:
794			//
795			// - The receiver spins for `delay` and then does a
796			// blocking receive on a channel.
797			//
798			// - The sender spins for `delay+wakeDelay` and then
799			// sends to the same channel. (The addition of
800			// `wakeDelay` improves the probability that the
801			// receiver will be blocking when the send occurs when
802			// the goroutines execute in parallel.)
803			//
804			// In each iteration of the benchmark, each goroutine
805			// acts once as sender and once as receiver, so each
806			// goroutine spins for delay twice.
807			//
808			// BenchmarkWakeupParallel is used to estimate how
809			// efficiently the scheduler parallelizes goroutines in
810			// the presence of blocking:
811			//
812			// - If both goroutines are executed on the same core,
813			// an increase in delay by N will increase the time per
814			// iteration by 4*N, because all 4 delays are
815			// serialized.
816			//
817			// - Otherwise, an increase in delay by N will increase
818			// the time per iteration by 2*N, and the time per
819			// iteration is 2 * (runtime overhead + chan
820			// send/receive pair + delay + wakeDelay). This allows
821			// the runtime overhead, including the time it takes
822			// for the unblocked goroutine to be scheduled, to be
823			// estimated.
824			ping, pong := make(chan struct{}), make(chan struct{})
825			start := make(chan struct{})
826			done := make(chan struct{})
827			go func() {
828				<-start
829				for i := 0; i < b.N; i++ {
830					// sender
831					spin(delay + wakeDelay)
832					ping <- struct{}{}
833					// receiver
834					spin(delay)
835					<-pong
836				}
837				done <- struct{}{}
838			}()
839			go func() {
840				for i := 0; i < b.N; i++ {
841					// receiver
842					spin(delay)
843					<-ping
844					// sender
845					spin(delay + wakeDelay)
846					pong <- struct{}{}
847				}
848				done <- struct{}{}
849			}()
850			b.ResetTimer()
851			start <- struct{}{}
852			<-done
853			<-done
854		})
855	}
856}
857
858func BenchmarkWakeupParallelSpinning(b *testing.B) {
859	benchmarkWakeupParallel(b, func(d time.Duration) {
860		end := time.Now().Add(d)
861		for time.Now().Before(end) {
862			// do nothing
863		}
864	})
865}
866
867// sysNanosleep is defined by OS-specific files (such as runtime_linux_test.go)
868// to sleep for the given duration. If nil, dependent tests are skipped.
869// The implementation should invoke a blocking system call and not
870// call time.Sleep, which would deschedule the goroutine.
871var sysNanosleep func(d time.Duration)
872
873func BenchmarkWakeupParallelSyscall(b *testing.B) {
874	if sysNanosleep == nil {
875		b.Skipf("skipping on %v; sysNanosleep not defined", runtime.GOOS)
876	}
877	benchmarkWakeupParallel(b, func(d time.Duration) {
878		sysNanosleep(d)
879	})
880}
881
882type Matrix [][]float64
883
884func BenchmarkMatmult(b *testing.B) {
885	b.StopTimer()
886	// matmult is O(N**3) but testing expects O(b.N),
887	// so we need to take cube root of b.N
888	n := int(math.Cbrt(float64(b.N))) + 1
889	A := makeMatrix(n)
890	B := makeMatrix(n)
891	C := makeMatrix(n)
892	b.StartTimer()
893	matmult(nil, A, B, C, 0, n, 0, n, 0, n, 8)
894}
895
896func makeMatrix(n int) Matrix {
897	m := make(Matrix, n)
898	for i := 0; i < n; i++ {
899		m[i] = make([]float64, n)
900		for j := 0; j < n; j++ {
901			m[i][j] = float64(i*n + j)
902		}
903	}
904	return m
905}
906
907func matmult(done chan<- struct{}, A, B, C Matrix, i0, i1, j0, j1, k0, k1, threshold int) {
908	di := i1 - i0
909	dj := j1 - j0
910	dk := k1 - k0
911	if di >= dj && di >= dk && di >= threshold {
912		// divide in two by y axis
913		mi := i0 + di/2
914		done1 := make(chan struct{}, 1)
915		go matmult(done1, A, B, C, i0, mi, j0, j1, k0, k1, threshold)
916		matmult(nil, A, B, C, mi, i1, j0, j1, k0, k1, threshold)
917		<-done1
918	} else if dj >= dk && dj >= threshold {
919		// divide in two by x axis
920		mj := j0 + dj/2
921		done1 := make(chan struct{}, 1)
922		go matmult(done1, A, B, C, i0, i1, j0, mj, k0, k1, threshold)
923		matmult(nil, A, B, C, i0, i1, mj, j1, k0, k1, threshold)
924		<-done1
925	} else if dk >= threshold {
926		// divide in two by "k" axis
927		// deliberately not parallel because of data races
928		mk := k0 + dk/2
929		matmult(nil, A, B, C, i0, i1, j0, j1, k0, mk, threshold)
930		matmult(nil, A, B, C, i0, i1, j0, j1, mk, k1, threshold)
931	} else {
932		// the matrices are small enough, compute directly
933		for i := i0; i < i1; i++ {
934			for j := j0; j < j1; j++ {
935				for k := k0; k < k1; k++ {
936					C[i][j] += A[i][k] * B[k][j]
937				}
938			}
939		}
940	}
941	if done != nil {
942		done <- struct{}{}
943	}
944}
945
946func TestStealOrder(t *testing.T) {
947	runtime.RunStealOrderTest()
948}
949
950func TestLockOSThreadNesting(t *testing.T) {
951	if runtime.GOARCH == "wasm" {
952		t.Skip("no threads on wasm yet")
953	}
954
955	go func() {
956		e, i := runtime.LockOSCounts()
957		if e != 0 || i != 0 {
958			t.Errorf("want locked counts 0, 0; got %d, %d", e, i)
959			return
960		}
961		runtime.LockOSThread()
962		runtime.LockOSThread()
963		runtime.UnlockOSThread()
964		e, i = runtime.LockOSCounts()
965		if e != 1 || i != 0 {
966			t.Errorf("want locked counts 1, 0; got %d, %d", e, i)
967			return
968		}
969		runtime.UnlockOSThread()
970		e, i = runtime.LockOSCounts()
971		if e != 0 || i != 0 {
972			t.Errorf("want locked counts 0, 0; got %d, %d", e, i)
973			return
974		}
975	}()
976}
977
978func TestLockOSThreadExit(t *testing.T) {
979	testLockOSThreadExit(t, "testprog")
980}
981
982func testLockOSThreadExit(t *testing.T, prog string) {
983	output := runTestProg(t, prog, "LockOSThreadMain", "GOMAXPROCS=1")
984	want := "OK\n"
985	if output != want {
986		t.Errorf("want %q, got %q", want, output)
987	}
988
989	output = runTestProg(t, prog, "LockOSThreadAlt")
990	if output != want {
991		t.Errorf("want %q, got %q", want, output)
992	}
993}
994
995func TestLockOSThreadAvoidsStatePropagation(t *testing.T) {
996	want := "OK\n"
997	skip := "unshare not permitted\n"
998	output := runTestProg(t, "testprog", "LockOSThreadAvoidsStatePropagation", "GOMAXPROCS=1")
999	if output == skip {
1000		t.Skip("unshare syscall not permitted on this system")
1001	} else if output != want {
1002		t.Errorf("want %q, got %q", want, output)
1003	}
1004}
1005
1006func TestLockOSThreadTemplateThreadRace(t *testing.T) {
1007	testenv.MustHaveGoRun(t)
1008
1009	exe, err := buildTestProg(t, "testprog")
1010	if err != nil {
1011		t.Fatal(err)
1012	}
1013
1014	iterations := 100
1015	if testing.Short() {
1016		// Reduce run time to ~100ms, with much lower probability of
1017		// catching issues.
1018		iterations = 5
1019	}
1020	for i := 0; i < iterations; i++ {
1021		want := "OK\n"
1022		output := runBuiltTestProg(t, exe, "LockOSThreadTemplateThreadRace")
1023		if output != want {
1024			t.Fatalf("run %d: want %q, got %q", i, want, output)
1025		}
1026	}
1027}
1028
1029// fakeSyscall emulates a system call.
1030//
1031//go:nosplit
1032func fakeSyscall(duration time.Duration) {
1033	runtime.Entersyscall()
1034	for start := runtime.Nanotime(); runtime.Nanotime()-start < int64(duration); {
1035	}
1036	runtime.Exitsyscall()
1037}
1038
1039// Check that a goroutine will be preempted if it is calling short system calls.
1040func testPreemptionAfterSyscall(t *testing.T, syscallDuration time.Duration) {
1041	if runtime.GOARCH == "wasm" {
1042		t.Skip("no preemption on wasm yet")
1043	}
1044
1045	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(2))
1046
1047	iterations := 10
1048	if testing.Short() {
1049		iterations = 1
1050	}
1051	const (
1052		maxDuration = 5 * time.Second
1053		nroutines   = 8
1054	)
1055
1056	for i := 0; i < iterations; i++ {
1057		c := make(chan bool, nroutines)
1058		stop := uint32(0)
1059
1060		start := time.Now()
1061		for g := 0; g < nroutines; g++ {
1062			go func(stop *uint32) {
1063				c <- true
1064				for atomic.LoadUint32(stop) == 0 {
1065					fakeSyscall(syscallDuration)
1066				}
1067				c <- true
1068			}(&stop)
1069		}
1070		// wait until all goroutines have started.
1071		for g := 0; g < nroutines; g++ {
1072			<-c
1073		}
1074		atomic.StoreUint32(&stop, 1)
1075		// wait until all goroutines have finished.
1076		for g := 0; g < nroutines; g++ {
1077			<-c
1078		}
1079		duration := time.Since(start)
1080
1081		if duration > maxDuration {
1082			t.Errorf("timeout exceeded: %v (%v)", duration, maxDuration)
1083		}
1084	}
1085}
1086
1087func TestPreemptionAfterSyscall(t *testing.T) {
1088	if runtime.GOOS == "plan9" {
1089		testenv.SkipFlaky(t, 41015)
1090	}
1091
1092	for _, i := range []time.Duration{10, 100, 1000} {
1093		d := i * time.Microsecond
1094		t.Run(fmt.Sprint(d), func(t *testing.T) {
1095			testPreemptionAfterSyscall(t, d)
1096		})
1097	}
1098}
1099
1100func TestGetgThreadSwitch(t *testing.T) {
1101	runtime.RunGetgThreadSwitchTest()
1102}
1103
1104// TestNetpollBreak tests that netpollBreak can break a netpoll.
1105// This test is not particularly safe since the call to netpoll
1106// will pick up any stray files that are ready, but it should work
1107// OK as long it is not run in parallel.
1108func TestNetpollBreak(t *testing.T) {
1109	if runtime.GOMAXPROCS(0) == 1 {
1110		t.Skip("skipping: GOMAXPROCS=1")
1111	}
1112
1113	// Make sure that netpoll is initialized.
1114	runtime.NetpollGenericInit()
1115
1116	start := time.Now()
1117	c := make(chan bool, 2)
1118	go func() {
1119		c <- true
1120		runtime.Netpoll(10 * time.Second.Nanoseconds())
1121		c <- true
1122	}()
1123	<-c
1124	// Loop because the break might get eaten by the scheduler.
1125	// Break twice to break both the netpoll we started and the
1126	// scheduler netpoll.
1127loop:
1128	for {
1129		runtime.Usleep(100)
1130		runtime.NetpollBreak()
1131		runtime.NetpollBreak()
1132		select {
1133		case <-c:
1134			break loop
1135		default:
1136		}
1137	}
1138	if dur := time.Since(start); dur > 5*time.Second {
1139		t.Errorf("netpollBreak did not interrupt netpoll: slept for: %v", dur)
1140	}
1141}
1142
1143// TestBigGOMAXPROCS tests that setting GOMAXPROCS to a large value
1144// doesn't cause a crash at startup. See issue 38474.
1145func TestBigGOMAXPROCS(t *testing.T) {
1146	t.Parallel()
1147	output := runTestProg(t, "testprog", "NonexistentTest", "GOMAXPROCS=1024")
1148	// Ignore error conditions on small machines.
1149	for _, errstr := range []string{
1150		"failed to create new OS thread",
1151		"cannot allocate memory",
1152	} {
1153		if strings.Contains(output, errstr) {
1154			t.Skipf("failed to create 1024 threads")
1155		}
1156	}
1157	if !strings.Contains(output, "unknown function: NonexistentTest") {
1158		t.Errorf("output:\n%s\nwanted:\nunknown function: NonexistentTest", output)
1159	}
1160}
1161