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