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