github.com/kortschak/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 add runtime.add 33 //go:nosplit 34 func add(p unsafe.Pointer, x uintptr) unsafe.Pointer 35 36 //go:linkname getm runtime.getm 37 //go:nosplit 38 func getm() unsafe.Pointer 39 40 var ( 41 curgoff = offset("*runtime.m", "curg") 42 goidoff = offset("*runtime.g", "goid") 43 ) 44 45 // offset returns the offset into typ for the given field. 46 func offset(typ, field string) uintptr { 47 rt := toType(typesByString(typ)[0]) 48 f, _ := rt.Elem().FieldByName(field) 49 return f.Offset 50 } 51 52 //go:linkname typesByString reflect.typesByString 53 func typesByString(s string) []unsafe.Pointer 54 55 //go:linkname toType reflect.toType 56 func toType(t unsafe.Pointer) reflect.Type