LEFT | RIGHT |
1 // Copyright 2009 The Go Authors. All rights reserved. | 1 // Copyright 2009 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 // Time-related runtime and pieces of package time. | 5 // Time-related runtime and pieces of package time. |
6 | 6 |
7 package time | 7 package time |
8 | 8 |
9 #include "runtime.h" | 9 #include "runtime.h" |
10 #include "defs_GOOS_GOARCH.h" | 10 #include "defs_GOOS_GOARCH.h" |
11 #include "os_GOOS.h" | 11 #include "os_GOOS.h" |
12 #include "arch_GOARCH.h" | 12 #include "arch_GOARCH.h" |
13 #include "malloc.h" | 13 #include "malloc.h" |
| 14 #include "race.h" |
14 | 15 |
15 static Timers timers; | 16 static Timers timers; |
16 static void addtimer(Timer*); | 17 static void addtimer(Timer *t); |
17 static bool deltimer(Timer*); | |
18 | 18 |
19 // Package time APIs. | 19 // Package time APIs. |
20 // Godoc uses the comments in package time, not these. | 20 // Godoc uses the comments in package time, not these. |
21 | 21 |
22 // time.now is implemented in assembly. | 22 // time.now is implemented in assembly. |
23 | 23 |
24 // Sleep puts the current goroutine to sleep for at least ns nanoseconds. | 24 // Sleep puts the current goroutine to sleep for at least ns nanoseconds. |
25 func Sleep(ns int64) { | 25 func Sleep(ns int64) { |
26 runtime·tsleep(ns, "sleep"); | 26 runtime·tsleep(ns, "sleep"); |
27 } | 27 } |
28 | 28 |
29 // startTimer adds t to the timer heap. | 29 // startTimer adds t to the timer heap. |
30 func startTimer(t *Timer) { | 30 func startTimer(t *Timer) { |
| 31 if(raceenabled) |
| 32 runtime·racerelease(t); |
31 runtime·lock(&timers); | 33 runtime·lock(&timers); |
32 addtimer(t); | 34 addtimer(t); |
33 runtime·unlock(&timers); | 35 runtime·unlock(&timers); |
34 } | 36 } |
35 | 37 |
36 // stopTimer removes t from the timer heap if it is there. | 38 // stopTimer removes t from the timer heap if it is there. |
37 // It returns true if t was removed, false if t wasn't even there. | 39 // It returns true if t was removed, false if t wasn't even there. |
38 func stopTimer(t *Timer) (stopped bool) { | 40 func stopTimer(t *Timer) (stopped bool) { |
39 » stopped = deltimer(t); | 41 » stopped = runtime·deltimer(t); |
40 } | 42 } |
41 | 43 |
42 // C runtime. | 44 // C runtime. |
43 | 45 |
44 static void timerproc(void); | 46 static void timerproc(void); |
45 static void siftup(int32); | 47 static void siftup(int32); |
46 static void siftdown(int32); | 48 static void siftdown(int32); |
47 | 49 |
48 // Ready the goroutine e.data. | 50 // Ready the goroutine e.data. |
49 static void | 51 static void |
(...skipping 12 matching lines...) Expand all Loading... |
62 | 64 |
63 if(ns <= 0) | 65 if(ns <= 0) |
64 return; | 66 return; |
65 | 67 |
66 t.when = runtime·nanotime() + ns; | 68 t.when = runtime·nanotime() + ns; |
67 t.period = 0; | 69 t.period = 0; |
68 t.f = ready; | 70 t.f = ready; |
69 t.arg.data = g; | 71 t.arg.data = g; |
70 runtime·lock(&timers); | 72 runtime·lock(&timers); |
71 addtimer(&t); | 73 addtimer(&t); |
72 » runtime·park(&timers.Lock, (void(*)(void*))runtime·unlock, reason); | 74 » runtime·park(runtime·unlock, &timers, reason); |
73 } | 75 } |
74 | 76 |
75 // Add a timer to the heap and start or kick the timer proc | 77 // Add a timer to the heap and start or kick the timer proc |
76 // if the new timer is earlier than any of the others. | 78 // if the new timer is earlier than any of the others. |
77 static void | 79 static void |
78 addtimer(Timer *t) | 80 addtimer(Timer *t) |
79 { | 81 { |
80 int32 n; | 82 int32 n; |
81 Timer **nt; | 83 Timer **nt; |
82 | 84 |
(...skipping 19 matching lines...) Expand all Loading... |
102 } | 104 } |
103 if(timers.rescheduling) { | 105 if(timers.rescheduling) { |
104 timers.rescheduling = false; | 106 timers.rescheduling = false; |
105 runtime·ready(timers.timerproc); | 107 runtime·ready(timers.timerproc); |
106 } | 108 } |
107 } | 109 } |
108 if(timers.timerproc == nil) | 110 if(timers.timerproc == nil) |
109 timers.timerproc = runtime·newproc1((byte*)timerproc, nil, 0, 0,
addtimer); | 111 timers.timerproc = runtime·newproc1((byte*)timerproc, nil, 0, 0,
addtimer); |
110 } | 112 } |
111 | 113 |
| 114 bool |
| 115 runtime·addtimer(Timer *t) |
| 116 { |
| 117 runtime·lock(&timers); |
| 118 addtimer(t); |
| 119 runtime·unlock(&timers); |
| 120 return true; |
| 121 } |
| 122 |
112 // Delete timer t from the heap. | 123 // Delete timer t from the heap. |
113 // Do not need to update the timerproc: | 124 // Do not need to update the timerproc: |
114 // if it wakes up early, no big deal. | 125 // if it wakes up early, no big deal. |
115 static bool | 126 bool |
116 deltimer(Timer *t) | 127 runtime·deltimer(Timer *t) |
117 { | 128 { |
118 int32 i; | 129 int32 i; |
119 | 130 |
120 runtime·lock(&timers); | 131 runtime·lock(&timers); |
121 | 132 |
122 // t may not be registered anymore and may have | 133 // t may not be registered anymore and may have |
123 // a bogus i (typically 0, if generated by Go). | 134 // a bogus i (typically 0, if generated by Go). |
124 // Verify it before proceeding. | 135 // Verify it before proceeding. |
125 i = t->i; | 136 i = t->i; |
126 if(i < 0 || i >= timers.len || timers.t[i] != t) { | 137 if(i < 0 || i >= timers.len || timers.t[i] != t) { |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
173 } else { | 184 } else { |
174 // remove from heap | 185 // remove from heap |
175 timers.t[0] = timers.t[--timers.len]; | 186 timers.t[0] = timers.t[--timers.len]; |
176 timers.t[0]->i = 0; | 187 timers.t[0]->i = 0; |
177 siftdown(0); | 188 siftdown(0); |
178 t->i = -1; // mark as removed | 189 t->i = -1; // mark as removed |
179 } | 190 } |
180 f = t->f; | 191 f = t->f; |
181 arg = t->arg; | 192 arg = t->arg; |
182 runtime·unlock(&timers); | 193 runtime·unlock(&timers); |
| 194 if(raceenabled) |
| 195 runtime·raceacquire(t); |
183 f(now, arg); | 196 f(now, arg); |
184 runtime·lock(&timers); | 197 runtime·lock(&timers); |
185 } | 198 } |
186 if(delta < 0) { | 199 if(delta < 0) { |
187 // No timers left - put goroutine to sleep. | 200 // No timers left - put goroutine to sleep. |
188 timers.rescheduling = true; | 201 timers.rescheduling = true; |
189 » » » runtime·park(&timers.Lock, (void(*)(void*))runtime·unloc
k, "timer goroutine (idle)"); | 202 » » » runtime·park(runtime·unlock, &timers, "timer goroutine (
idle)"); |
190 continue; | 203 continue; |
191 } | 204 } |
192 // At least one timer pending. Sleep until then. | 205 // At least one timer pending. Sleep until then. |
193 timers.sleeping = true; | 206 timers.sleeping = true; |
194 runtime·noteclear(&timers.waitnote); | 207 runtime·noteclear(&timers.waitnote); |
195 runtime·unlock(&timers); | 208 runtime·unlock(&timers); |
196 » » runtime·entersyscall(); | 209 » » runtime·entersyscallblock(); |
197 runtime·notetsleep(&timers.waitnote, delta); | 210 runtime·notetsleep(&timers.waitnote, delta); |
198 runtime·exitsyscall(); | 211 runtime·exitsyscall(); |
199 } | 212 } |
200 } | 213 } |
201 | 214 |
202 // heap maintenance algorithms. | 215 // heap maintenance algorithms. |
203 | 216 |
204 static void | 217 static void |
205 siftup(int32 i) | 218 siftup(int32 i) |
206 { | 219 { |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
239 if(t[c]->when >= t[i]->when) | 252 if(t[c]->when >= t[i]->when) |
240 break; | 253 break; |
241 tmp = t[i]; | 254 tmp = t[i]; |
242 t[i] = t[c]; | 255 t[i] = t[c]; |
243 t[c] = tmp; | 256 t[c] = tmp; |
244 t[i]->i = i; | 257 t[i]->i = i; |
245 t[c]->i = c; | 258 t[c]->i = c; |
246 i = c; | 259 i = c; |
247 } | 260 } |
248 } | 261 } |
LEFT | RIGHT |