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 }