1// Copyright 2023 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// Tests a many interesting cases (network, syscalls, a little GC, busy goroutines, 6// blocked goroutines, LockOSThread, pipes, and GOMAXPROCS). 7 8//go:build ignore 9 10package main 11 12import ( 13 "bytes" 14 "io" 15 "log" 16 "net" 17 "os" 18 "runtime" 19 "runtime/trace" 20 "sync" 21 "time" 22) 23 24func main() { 25 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(8)) 26 outerDone := make(chan bool) 27 28 go func() { 29 defer func() { 30 outerDone <- true 31 }() 32 33 var wg sync.WaitGroup 34 done := make(chan bool) 35 36 wg.Add(1) 37 go func() { 38 <-done 39 wg.Done() 40 }() 41 42 rp, wp, err := os.Pipe() 43 if err != nil { 44 log.Fatalf("failed to create pipe: %v", err) 45 return 46 } 47 defer func() { 48 rp.Close() 49 wp.Close() 50 }() 51 wg.Add(1) 52 go func() { 53 var tmp [1]byte 54 rp.Read(tmp[:]) 55 <-done 56 wg.Done() 57 }() 58 time.Sleep(time.Millisecond) 59 60 go func() { 61 runtime.LockOSThread() 62 for { 63 select { 64 case <-done: 65 return 66 default: 67 runtime.Gosched() 68 } 69 } 70 }() 71 72 runtime.GC() 73 // Trigger GC from malloc. 74 n := 512 75 for i := 0; i < n; i++ { 76 _ = make([]byte, 1<<20) 77 } 78 79 // Create a bunch of busy goroutines to load all Ps. 80 for p := 0; p < 10; p++ { 81 wg.Add(1) 82 go func() { 83 // Do something useful. 84 tmp := make([]byte, 1<<16) 85 for i := range tmp { 86 tmp[i]++ 87 } 88 _ = tmp 89 <-done 90 wg.Done() 91 }() 92 } 93 94 // Block in syscall. 95 wg.Add(1) 96 go func() { 97 var tmp [1]byte 98 rp.Read(tmp[:]) 99 <-done 100 wg.Done() 101 }() 102 103 runtime.GOMAXPROCS(runtime.GOMAXPROCS(1)) 104 105 // Test timers. 106 timerDone := make(chan bool) 107 go func() { 108 time.Sleep(time.Millisecond) 109 timerDone <- true 110 }() 111 <-timerDone 112 113 // A bit of network. 114 ln, err := net.Listen("tcp", "127.0.0.1:0") 115 if err != nil { 116 log.Fatalf("listen failed: %v", err) 117 return 118 } 119 defer ln.Close() 120 go func() { 121 c, err := ln.Accept() 122 if err != nil { 123 return 124 } 125 time.Sleep(time.Millisecond) 126 var buf [1]byte 127 c.Write(buf[:]) 128 c.Close() 129 }() 130 c, err := net.Dial("tcp", ln.Addr().String()) 131 if err != nil { 132 log.Fatalf("dial failed: %v", err) 133 return 134 } 135 var tmp [1]byte 136 c.Read(tmp[:]) 137 c.Close() 138 139 go func() { 140 runtime.Gosched() 141 select {} 142 }() 143 144 // Unblock helper goroutines and wait them to finish. 145 wp.Write(tmp[:]) 146 wp.Write(tmp[:]) 147 close(done) 148 wg.Wait() 149 }() 150 151 const iters = 5 152 for i := 0; i < iters; i++ { 153 var w io.Writer 154 if i == iters-1 { 155 w = os.Stdout 156 } else { 157 w = new(bytes.Buffer) 158 } 159 if err := trace.Start(w); err != nil { 160 log.Fatalf("failed to start tracing: %v", err) 161 } 162 time.Sleep(time.Millisecond) 163 trace.Stop() 164 } 165 <-outerDone 166} 167