Source file
src/runtime/lock_sema.go
1
2
3
4
5
6
7 package runtime
8
9 import (
10 "internal/runtime/atomic"
11 "unsafe"
12 )
13
14 const (
15 locked uintptr = 1
16 )
17
18
19 func noteclear(n *note) {
20 n.key = 0
21 }
22
23 func notewakeup(n *note) {
24 var v uintptr
25 for {
26 v = atomic.Loaduintptr(&n.key)
27 if atomic.Casuintptr(&n.key, v, locked) {
28 break
29 }
30 }
31
32
33
34 switch {
35 case v == 0:
36
37 case v == locked:
38
39 throw("notewakeup - double wakeup")
40 default:
41
42 semawakeup((*m)(unsafe.Pointer(v)))
43 }
44 }
45
46 func notesleep(n *note) {
47 gp := getg()
48 if gp != gp.m.g0 {
49 throw("notesleep not on g0")
50 }
51 semacreate(gp.m)
52 if !atomic.Casuintptr(&n.key, 0, uintptr(unsafe.Pointer(gp.m))) {
53
54 if n.key != locked {
55 throw("notesleep - waitm out of sync")
56 }
57 return
58 }
59
60 gp.m.blocked = true
61 if *cgo_yield == nil {
62 semasleep(-1)
63 } else {
64
65 const ns = 10e6
66 for atomic.Loaduintptr(&n.key) == 0 {
67 semasleep(ns)
68 asmcgocall(*cgo_yield, nil)
69 }
70 }
71 gp.m.blocked = false
72 }
73
74
75 func notetsleep_internal(n *note, ns int64, gp *g, deadline int64) bool {
76
77
78
79
80 gp = getg()
81
82
83 if !atomic.Casuintptr(&n.key, 0, uintptr(unsafe.Pointer(gp.m))) {
84
85 if n.key != locked {
86 throw("notetsleep - waitm out of sync")
87 }
88 return true
89 }
90 if ns < 0 {
91
92 gp.m.blocked = true
93 if *cgo_yield == nil {
94 semasleep(-1)
95 } else {
96
97 const ns = 10e6
98 for semasleep(ns) < 0 {
99 asmcgocall(*cgo_yield, nil)
100 }
101 }
102 gp.m.blocked = false
103 return true
104 }
105
106 deadline = nanotime() + ns
107 for {
108
109 gp.m.blocked = true
110 if *cgo_yield != nil && ns > 10e6 {
111 ns = 10e6
112 }
113 if semasleep(ns) >= 0 {
114 gp.m.blocked = false
115
116
117 return true
118 }
119 if *cgo_yield != nil {
120 asmcgocall(*cgo_yield, nil)
121 }
122 gp.m.blocked = false
123
124 ns = deadline - nanotime()
125 if ns <= 0 {
126 break
127 }
128
129 }
130
131
132
133
134
135 for {
136 v := atomic.Loaduintptr(&n.key)
137 switch v {
138 case uintptr(unsafe.Pointer(gp.m)):
139
140 if atomic.Casuintptr(&n.key, v, 0) {
141 return false
142 }
143 case locked:
144
145
146 gp.m.blocked = true
147 if semasleep(-1) < 0 {
148 throw("runtime: unable to acquire - semaphore out of sync")
149 }
150 gp.m.blocked = false
151 return true
152 default:
153 throw("runtime: unexpected waitm - semaphore out of sync")
154 }
155 }
156 }
157
158 func notetsleep(n *note, ns int64) bool {
159 gp := getg()
160 if gp != gp.m.g0 {
161 throw("notetsleep not on g0")
162 }
163 semacreate(gp.m)
164 return notetsleep_internal(n, ns, nil, 0)
165 }
166
167
168
169 func notetsleepg(n *note, ns int64) bool {
170 gp := getg()
171 if gp == gp.m.g0 {
172 throw("notetsleepg on g0")
173 }
174 semacreate(gp.m)
175 entersyscallblock()
176 ok := notetsleep_internal(n, ns, nil, 0)
177 exitsyscall()
178 return ok
179 }
180
181 func beforeIdle(int64, int64) (*g, bool) {
182 return nil, false
183 }
184
185 func checkTimeouts() {}
186
View as plain text