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