OLD | NEW |
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 #include "race.h" |
15 | 15 |
16 static Timers timers; | 16 static Timers timers; |
17 static void addtimer(Timer*); | 17 static void addtimer(Timer*); |
18 static bool deltimer(Timer*); | 18 static bool deltimer(Timer*); |
| 19 static int64 fakeNanotime = 1257894000000000000ll; // go epoch |
19 | 20 |
20 // Package time APIs. | 21 // Package time APIs. |
21 // Godoc uses the comments in package time, not these. | 22 // Godoc uses the comments in package time, not these. |
22 | 23 |
23 // time.now is implemented in assembly. | 24 // time.now is implemented in assembly. |
24 | 25 |
| 26 func fakeNow() (sec int64, nsec int32) { |
| 27 runtime·lock(&timers); |
| 28 sec = (int32)(fakeNanotime/1000000000); |
| 29 nsec = (int32)(fakeNanotime%1000000000); |
| 30 runtime·unlock(&timers); |
| 31 } |
| 32 |
25 // Sleep puts the current goroutine to sleep for at least ns nanoseconds. | 33 // Sleep puts the current goroutine to sleep for at least ns nanoseconds. |
26 func Sleep(ns int64) { | 34 func Sleep(ns int64) { |
27 runtime·tsleep(ns, "sleep"); | 35 runtime·tsleep(ns, "sleep"); |
28 } | 36 } |
29 | 37 |
30 // startTimer adds t to the timer heap. | 38 // startTimer adds t to the timer heap. |
31 func startTimer(t *Timer) { | 39 func startTimer(t *Timer) { |
32 if(raceenabled) | 40 if(raceenabled) |
33 runtime·racerelease(t); | 41 runtime·racerelease(t); |
34 runtime·lock(&timers); | 42 runtime·lock(&timers); |
(...skipping 24 matching lines...) Expand all Loading... |
59 | 67 |
60 // Put the current goroutine to sleep for ns nanoseconds. | 68 // Put the current goroutine to sleep for ns nanoseconds. |
61 void | 69 void |
62 runtime·tsleep(int64 ns, int8 *reason) | 70 runtime·tsleep(int64 ns, int8 *reason) |
63 { | 71 { |
64 Timer t; | 72 Timer t; |
65 | 73 |
66 if(ns <= 0) | 74 if(ns <= 0) |
67 return; | 75 return; |
68 | 76 |
69 » t.when = runtime·nanotime() + ns; | 77 » t.when = fakeNanotime + ns; |
70 t.period = 0; | 78 t.period = 0; |
71 t.f = ready; | 79 t.f = ready; |
72 t.arg.data = g; | 80 t.arg.data = g; |
73 runtime·lock(&timers); | 81 runtime·lock(&timers); |
74 addtimer(&t); | 82 addtimer(&t); |
75 runtime·park(runtime·unlock, &timers, reason); | 83 runtime·park(runtime·unlock, &timers, reason); |
76 } | 84 } |
77 | 85 |
78 // Add a timer to the heap and start or kick the timer proc | 86 // Add a timer to the heap and start or kick the timer proc |
79 // if the new timer is earlier than any of the others. | 87 // if the new timer is earlier than any of the others. |
(...skipping 12 matching lines...) Expand all Loading... |
92 runtime·memmove(nt, timers.t, timers.len*sizeof nt[0]); | 100 runtime·memmove(nt, timers.t, timers.len*sizeof nt[0]); |
93 runtime·free(timers.t); | 101 runtime·free(timers.t); |
94 timers.t = nt; | 102 timers.t = nt; |
95 timers.cap = n; | 103 timers.cap = n; |
96 } | 104 } |
97 t->i = timers.len++; | 105 t->i = timers.len++; |
98 timers.t[t->i] = t; | 106 timers.t[t->i] = t; |
99 siftup(t->i); | 107 siftup(t->i); |
100 if(t->i == 0) { | 108 if(t->i == 0) { |
101 // siftup moved to top: new earliest deadline. | 109 // siftup moved to top: new earliest deadline. |
102 if(timers.sleeping) { | |
103 timers.sleeping = false; | |
104 runtime·notewakeup(&timers.waitnote); | |
105 } | |
106 if(timers.rescheduling) { | 110 if(timers.rescheduling) { |
107 timers.rescheduling = false; | 111 timers.rescheduling = false; |
108 runtime·ready(timers.timerproc); | 112 runtime·ready(timers.timerproc); |
109 } | 113 } |
110 } | 114 } |
111 if(timers.timerproc == nil) | 115 if(timers.timerproc == nil) |
112 timers.timerproc = runtime·newproc1((byte*)timerproc, nil, 0, 0,
addtimer); | 116 timers.timerproc = runtime·newproc1((byte*)timerproc, nil, 0, 0,
addtimer); |
113 } | 117 } |
114 | 118 |
115 // Delete timer t from the heap. | 119 // Delete timer t from the heap. |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
151 // wakes timerproc early. | 155 // wakes timerproc early. |
152 static void | 156 static void |
153 timerproc(void) | 157 timerproc(void) |
154 { | 158 { |
155 int64 delta, now; | 159 int64 delta, now; |
156 Timer *t; | 160 Timer *t; |
157 void (*f)(int64, Eface); | 161 void (*f)(int64, Eface); |
158 Eface arg; | 162 Eface arg; |
159 | 163 |
160 for(;;) { | 164 for(;;) { |
| 165 // At least one timer pending. Wait until goroutines are idle. |
| 166 runtime·waitidle(); |
161 runtime·lock(&timers); | 167 runtime·lock(&timers); |
162 » » now = runtime·nanotime(); | 168 » » // Update the fake time with the next timer. |
| 169 » » if(timers.len > 0) { |
| 170 » » » fakeNanotime = timers.t[0]->when; |
| 171 » » } |
| 172 » » now = fakeNanotime; |
163 for(;;) { | 173 for(;;) { |
164 if(timers.len == 0) { | 174 if(timers.len == 0) { |
165 delta = -1; | 175 delta = -1; |
166 break; | 176 break; |
167 } | 177 } |
168 t = timers.t[0]; | 178 t = timers.t[0]; |
169 delta = t->when - now; | 179 delta = t->when - now; |
170 if(delta > 0) | 180 if(delta > 0) |
171 break; | 181 break; |
172 if(t->period > 0) { | 182 if(t->period > 0) { |
(...skipping 14 matching lines...) Expand all Loading... |
187 runtime·raceacquire(t); | 197 runtime·raceacquire(t); |
188 f(now, arg); | 198 f(now, arg); |
189 runtime·lock(&timers); | 199 runtime·lock(&timers); |
190 } | 200 } |
191 if(delta < 0) { | 201 if(delta < 0) { |
192 // No timers left - put goroutine to sleep. | 202 // No timers left - put goroutine to sleep. |
193 timers.rescheduling = true; | 203 timers.rescheduling = true; |
194 runtime·park(runtime·unlock, &timers, "timer goroutine (
idle)"); | 204 runtime·park(runtime·unlock, &timers, "timer goroutine (
idle)"); |
195 continue; | 205 continue; |
196 } | 206 } |
197 // At least one timer pending. Sleep until then. | |
198 timers.sleeping = true; | |
199 runtime·noteclear(&timers.waitnote); | |
200 runtime·unlock(&timers); | 207 runtime·unlock(&timers); |
201 runtime·entersyscall(); | |
202 runtime·notetsleep(&timers.waitnote, delta); | |
203 runtime·exitsyscall(); | |
204 } | 208 } |
205 } | 209 } |
206 | 210 |
207 // heap maintenance algorithms. | 211 // heap maintenance algorithms. |
208 | 212 |
209 static void | 213 static void |
210 siftup(int32 i) | 214 siftup(int32 i) |
211 { | 215 { |
212 int32 p; | 216 int32 p; |
213 Timer **t, *tmp; | 217 Timer **t, *tmp; |
(...skipping 30 matching lines...) Expand all Loading... |
244 if(t[c]->when >= t[i]->when) | 248 if(t[c]->when >= t[i]->when) |
245 break; | 249 break; |
246 tmp = t[i]; | 250 tmp = t[i]; |
247 t[i] = t[c]; | 251 t[i] = t[c]; |
248 t[c] = tmp; | 252 t[c] = tmp; |
249 t[i]->i = i; | 253 t[i]->i = i; |
250 t[c]->i = c; | 254 t[c]->i = c; |
251 i = c; | 255 i = c; |
252 } | 256 } |
253 } | 257 } |
OLD | NEW |