github.com/likebike/go--@v0.0.0-20190911215757-0bd925d16e96/go/src/runtime/testdata/testprog/lockosthread.go (about) 1 // Copyright 2017 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 main 6 7 import ( 8 "os" 9 "runtime" 10 "time" 11 ) 12 13 var mainTID int 14 15 func init() { 16 registerInit("LockOSThreadMain", func() { 17 // init is guaranteed to run on the main thread. 18 mainTID = gettid() 19 }) 20 register("LockOSThreadMain", LockOSThreadMain) 21 22 registerInit("LockOSThreadAlt", func() { 23 // Lock the OS thread now so main runs on the main thread. 24 runtime.LockOSThread() 25 }) 26 register("LockOSThreadAlt", LockOSThreadAlt) 27 } 28 29 func LockOSThreadMain() { 30 // gettid only works on Linux, so on other platforms this just 31 // checks that the runtime doesn't do anything terrible. 32 33 // This requires GOMAXPROCS=1 from the beginning to reliably 34 // start a goroutine on the main thread. 35 if runtime.GOMAXPROCS(-1) != 1 { 36 println("requires GOMAXPROCS=1") 37 os.Exit(1) 38 } 39 40 ready := make(chan bool, 1) 41 go func() { 42 // Because GOMAXPROCS=1, this *should* be on the main 43 // thread. Stay there. 44 runtime.LockOSThread() 45 if mainTID != 0 && gettid() != mainTID { 46 println("failed to start goroutine on main thread") 47 os.Exit(1) 48 } 49 // Exit with the thread locked, which should exit the 50 // main thread. 51 ready <- true 52 }() 53 <-ready 54 time.Sleep(1 * time.Millisecond) 55 // Check that this goroutine is still running on a different 56 // thread. 57 if mainTID != 0 && gettid() == mainTID { 58 println("goroutine migrated to locked thread") 59 os.Exit(1) 60 } 61 println("OK") 62 } 63 64 func LockOSThreadAlt() { 65 // This is running locked to the main OS thread. 66 67 var subTID int 68 ready := make(chan bool, 1) 69 go func() { 70 // This goroutine must be running on a new thread. 71 runtime.LockOSThread() 72 subTID = gettid() 73 ready <- true 74 // Exit with the thread locked. 75 }() 76 <-ready 77 runtime.UnlockOSThread() 78 for i := 0; i < 100; i++ { 79 time.Sleep(1 * time.Millisecond) 80 // Check that this goroutine is running on a different thread. 81 if subTID != 0 && gettid() == subTID { 82 println("locked thread reused") 83 os.Exit(1) 84 } 85 exists, supported := tidExists(subTID) 86 if !supported || !exists { 87 goto ok 88 } 89 } 90 println("sub thread", subTID, "still running") 91 return 92 ok: 93 println("OK") 94 }