github.com/timandy/routine@v1.1.4-0.20240507073150-e4a3e1fe2ba5/goid.go (about)

     1  package routine
     2  
     3  import (
     4  	"fmt"
     5  	"reflect"
     6  	"unsafe"
     7  )
     8  
     9  var (
    10  	offsetGoid         uintptr
    11  	offsetPaniconfault uintptr
    12  	offsetGopc         uintptr
    13  	offsetLabels       uintptr
    14  )
    15  
    16  func init() {
    17  	gt := getgt()
    18  	offsetGoid = offset(gt, "goid")
    19  	offsetPaniconfault = offset(gt, "paniconfault")
    20  	offsetGopc = offset(gt, "gopc")
    21  	offsetLabels = offset(gt, "labels")
    22  }
    23  
    24  type g struct {
    25  	goid         int64
    26  	paniconfault *bool
    27  	gopc         *uintptr
    28  	labels       *unsafe.Pointer
    29  }
    30  
    31  //go:norace
    32  func (gp g) getPanicOnFault() bool {
    33  	return *gp.paniconfault
    34  }
    35  
    36  //go:norace
    37  func (gp g) setPanicOnFault(new bool) (old bool) {
    38  	old = *gp.paniconfault
    39  	*gp.paniconfault = new
    40  	return old
    41  }
    42  
    43  //go:norace
    44  func (gp g) getLabels() unsafe.Pointer {
    45  	return *gp.labels
    46  }
    47  
    48  //go:norace
    49  func (gp g) setLabels(labels unsafe.Pointer) {
    50  	*gp.labels = labels
    51  }
    52  
    53  // getg returns current coroutine struct.
    54  func getg() g {
    55  	gp := getgp()
    56  	if gp == nil {
    57  		panic("Failed to get gp from runtime natively.")
    58  	}
    59  	return g{
    60  		goid:         *(*int64)(add(gp, offsetGoid)),
    61  		paniconfault: (*bool)(add(gp, offsetPaniconfault)),
    62  		gopc:         (*uintptr)(add(gp, offsetGopc)),
    63  		labels:       (*unsafe.Pointer)(add(gp, offsetLabels)),
    64  	}
    65  }
    66  
    67  // offset returns the offset of the specified field.
    68  func offset(t reflect.Type, f string) uintptr {
    69  	field, found := t.FieldByName(f)
    70  	if found {
    71  		return field.Offset
    72  	}
    73  	panic(fmt.Sprintf("No such field '%v' of struct '%v.%v'.", f, t.PkgPath(), t.Name()))
    74  }
    75  
    76  // add pointer addition operation.
    77  func add(p unsafe.Pointer, x uintptr) unsafe.Pointer {
    78  	return unsafe.Pointer(uintptr(p) + x)
    79  }