github.com/liangmanlin/routine@v1.1.0/thread.go (about) 1 package routine 2 3 import ( 4 "runtime" 5 "unsafe" 6 ) 7 8 const threadMagic = int64('r')<<48 | 9 int64('o')<<40 | 10 int64('u')<<32 | 11 int64('t')<<24 | 12 int64('i')<<16 | 13 int64('n')<<8 | 14 int64('e') 15 16 type thread struct { 17 labels map[string]string //pprof 18 magic int64 //mark 19 id int64 //goid 20 val unsafe.Pointer 21 } 22 23 // currentThread returns a pointer to the currently executing goroutine's thread struct. 24 //go:norace 25 //go:nocheckptr 26 func currentThread(create bool) *thread { 27 gp := getg() 28 goid := gp.goid 29 label := gp.getLabels() 30 //nothing inherited 31 if label == nil { 32 if create { 33 newt := &thread{labels: nil, magic: threadMagic, id: goid} 34 gp.setLabels(unsafe.Pointer(newt)) 35 runtime.SetFinalizer(newt, threadFinalize) 36 return newt 37 } 38 return nil 39 } 40 //inherited map then create 41 t, magic, id := extractThread(gp, label) 42 if magic != threadMagic { 43 if create { 44 mp := *(*map[string]string)(label) 45 newt := &thread{labels: mp, magic: threadMagic, id: goid} 46 gp.setLabels(unsafe.Pointer(newt)) 47 runtime.SetFinalizer(newt, threadFinalize) 48 return newt 49 } 50 return nil 51 } 52 //inherited thread then recreate 53 if id != goid { 54 if create || t.labels != nil { 55 newt := &thread{labels: t.labels, magic: threadMagic, id: goid} 56 gp.setLabels(unsafe.Pointer(newt)) 57 runtime.SetFinalizer(newt, threadFinalize) 58 return newt 59 } 60 gp.setLabels(nil) 61 return nil 62 } 63 //all is ok 64 return t 65 } 66 67 // extractThread extract thread from unsafe.Pointer and catch fault error. 68 //go:norace 69 //go:nocheckptr 70 func extractThread(gp g, label unsafe.Pointer) (t *thread, magic int64, id int64) { 71 if thread_safe { 72 old := gp.setPanicOnFault(true) 73 defer func() { 74 gp.setPanicOnFault(old) 75 recover() 76 }() 77 } 78 t = (*thread)(label) 79 return t, t.magic, t.id 80 } 81 82 func threadFinalize(t *thread) { 83 t.magic = 0 84 }