| // Copyright 2023 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. |
| |
| // Tests a many interesting cases (network, syscalls, a little GC, busy goroutines, |
| // blocked goroutines, LockOSThread, pipes, and GOMAXPROCS). |
| |
| //go:build ignore |
| |
| package main |
| |
| import ( |
| "log" |
| "net" |
| "os" |
| "runtime" |
| "runtime/trace" |
| "sync" |
| "time" |
| ) |
| |
| func main() { |
| var wg sync.WaitGroup |
| done := make(chan bool) |
| |
| // Create a goroutine blocked before tracing. |
| wg.Add(1) |
| go func() { |
| <-done |
| wg.Done() |
| }() |
| |
| // Create a goroutine blocked in syscall before tracing. |
| rp, wp, err := os.Pipe() |
| if err != nil { |
| log.Fatalf("failed to create pipe: %v", err) |
| } |
| defer func() { |
| rp.Close() |
| wp.Close() |
| }() |
| wg.Add(1) |
| go func() { |
| var tmp [1]byte |
| rp.Read(tmp[:]) |
| <-done |
| wg.Done() |
| }() |
| time.Sleep(time.Millisecond) // give the goroutine above time to block |
| |
| if err := trace.Start(os.Stdout); err != nil { |
| log.Fatalf("failed to start tracing: %v", err) |
| } |
| defer trace.Stop() |
| |
| procs := runtime.GOMAXPROCS(10) |
| time.Sleep(50 * time.Millisecond) // test proc stop/start events |
| |
| go func() { |
| runtime.LockOSThread() |
| for { |
| select { |
| case <-done: |
| return |
| default: |
| runtime.Gosched() |
| } |
| } |
| }() |
| |
| runtime.GC() |
| // Trigger GC from malloc. |
| n := 512 |
| for i := 0; i < n; i++ { |
| _ = make([]byte, 1<<20) |
| } |
| |
| // Create a bunch of busy goroutines to load all Ps. |
| for p := 0; p < 10; p++ { |
| wg.Add(1) |
| go func() { |
| // Do something useful. |
| tmp := make([]byte, 1<<16) |
| for i := range tmp { |
| tmp[i]++ |
| } |
| _ = tmp |
| <-done |
| wg.Done() |
| }() |
| } |
| |
| // Block in syscall. |
| wg.Add(1) |
| go func() { |
| var tmp [1]byte |
| rp.Read(tmp[:]) |
| <-done |
| wg.Done() |
| }() |
| |
| // Test timers. |
| timerDone := make(chan bool) |
| go func() { |
| time.Sleep(time.Millisecond) |
| timerDone <- true |
| }() |
| <-timerDone |
| |
| // A bit of network. |
| ln, err := net.Listen("tcp", "127.0.0.1:0") |
| if err != nil { |
| log.Fatalf("listen failed: %v", err) |
| } |
| defer ln.Close() |
| go func() { |
| c, err := ln.Accept() |
| if err != nil { |
| return |
| } |
| time.Sleep(time.Millisecond) |
| var buf [1]byte |
| c.Write(buf[:]) |
| c.Close() |
| }() |
| c, err := net.Dial("tcp", ln.Addr().String()) |
| if err != nil { |
| log.Fatalf("dial failed: %v", err) |
| } |
| var tmp [1]byte |
| c.Read(tmp[:]) |
| c.Close() |
| |
| go func() { |
| runtime.Gosched() |
| select {} |
| }() |
| |
| // Unblock helper goroutines and wait them to finish. |
| wp.Write(tmp[:]) |
| wp.Write(tmp[:]) |
| close(done) |
| wg.Wait() |
| |
| runtime.GOMAXPROCS(procs) |
| } |