github.com/smallnest/goroutine@v1.1.1/gid.go (about) 1 // Copyright ©2020 Dan Kortschak. 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 goroutine provides functions that will return the runtime's 6 // ID number for the calling goroutine or its creator. 7 // 8 // The implementation is derived from Laevus Dexter's comment in Gophers' Slack #darkarts, 9 // https://gophers.slack.com/archives/C1C1YSQBT/p1593885226448300 post which linked to 10 // this playground snippet https://play.golang.org/p/CSOp9wyzydP. 11 package goroutine 12 13 import ( 14 "reflect" 15 "unsafe" 16 ) 17 18 // ID returns the runtime ID of the calling goroutine. 19 func ID() int64 { 20 return idOf(getg(), goidoff) 21 } 22 23 func idOf(g unsafe.Pointer, off uintptr) int64 { 24 return *(*int64)(add(g, off)) 25 } 26 27 //go:nosplit 28 func getg() unsafe.Pointer { 29 return *(*unsafe.Pointer)(add(getm(), curgoff)) 30 } 31 32 //go:linkname runtime_procPin runtime.procPin 33 func runtime_procPin() int 34 35 //go:linkname runtime_procUnpin runtime.procUnpin 36 func runtime_procUnpin() int 37 38 // PID returns the "P" ID of the calling goroutine. 39 func PID() int { 40 pid := runtime_procPin() 41 runtime_procUnpin() 42 return pid 43 } 44 45 //go:linkname add runtime.add 46 //go:nosplit 47 func add(p unsafe.Pointer, x uintptr) unsafe.Pointer 48 49 //go:linkname getm runtime.getm 50 //go:nosplit 51 func getm() unsafe.Pointer 52 53 var ( 54 curgoff = offset("*runtime.m", "curg") 55 goidoff = offset("*runtime.g", "goid") 56 ) 57 58 // offset returns the offset into typ for the given field. 59 func offset(typ, field string) uintptr { 60 rt := toType(typesByString(typ)[0]) 61 f, _ := rt.Elem().FieldByName(field) 62 return f.Offset 63 } 64 65 //go:linkname typesByString reflect.typesByString 66 func typesByString(s string) []unsafe.Pointer 67 68 //go:linkname toType reflect.toType 69 func toType(t unsafe.Pointer) reflect.Type