fortio.org/log@v1.12.2/goroutine/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 a single function that will return the runtime's
     6  // ID number for the calling goroutine.
     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 *(*int64)(add(getg(), goidoff))
    21  }
    22  
    23  //go:nosplit
    24  func getg() unsafe.Pointer {
    25  	return *(*unsafe.Pointer)(add(getm(), curgoff))
    26  }
    27  
    28  //go:linkname add runtime.add
    29  //go:nosplit
    30  func add(p unsafe.Pointer, x uintptr) unsafe.Pointer
    31  
    32  //go:linkname getm runtime.getm
    33  //go:nosplit
    34  func getm() unsafe.Pointer
    35  
    36  var (
    37  	curgoff = offset("*runtime.m", "curg")
    38  	goidoff = offset("*runtime.g", "goid")
    39  )
    40  
    41  // offset returns the offset into typ for the given field.
    42  func offset(typ, field string) uintptr {
    43  	rt := toType(typesByString(typ)[0])
    44  	f, _ := rt.Elem().FieldByName(field)
    45  	return f.Offset
    46  }
    47  
    48  //go:linkname typesByString reflect.typesByString
    49  func typesByString(s string) []unsafe.Pointer
    50  
    51  //go:linkname toType reflect.toType
    52  func toType(t unsafe.Pointer) reflect.Type