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 }