Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(8)

Delta Between Two Patch Sets: src/pkg/runtime/time.goc

Issue 160200044: [dev.power64] code review 160200044: build: merge default into dev.power64 (Closed)
Left Patch Set: diff -r be0c14f62257b42485019e9e1db23cf40d2e249f https://code.google.com/p/go Created 10 years, 4 months ago
Right Patch Set: diff -r be0c14f62257b42485019e9e1db23cf40d2e249f https://code.google.com/p/go Created 10 years, 4 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Right: Side by side diff | Download
« no previous file with change/comment | « src/pkg/runtime/time.go ('k') | src/pkg/runtime/tls_arm.s » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
(no file at all)
1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 // Time-related runtime and pieces of package time.
6
7 package time
8
9 #include "runtime.h"
10 #include "defs_GOOS_GOARCH.h"
11 #include "os_GOOS.h"
12 #include "arch_GOARCH.h"
13 #include "malloc.h"
14 #include "race.h"
15
16 enum {
17 debug = 0,
18 };
19
20 static Timers timers;
21 static void addtimer(Timer*);
22 static void dumptimers(int8*);
23
24 // nacl fake time support.·
25 int64 runtime·timens;
26
27 // Package time APIs.
28 // Godoc uses the comments in package time, not these.
29
30 // time.now is implemented in assembly.
31
32 // runtimeNano returns the current value of the runtime clock in nanoseconds.
33 func runtimeNano() (ns int64) {
34 ns = runtime·nanotime();
35 }
36
37 // Sleep puts the current goroutine to sleep for at least ns nanoseconds.
38 func Sleep(ns int64) {
39 runtime·tsleep(ns, "sleep");
40 }
41
42 // startTimer adds t to the timer heap.
43 func startTimer(t *Timer) {
44 if(raceenabled)
45 runtime·racerelease(t);
46 runtime·addtimer(t);
47 }
48
49 // stopTimer removes t from the timer heap if it is there.
50 // It returns true if t was removed, false if t wasn't even there.
51 func stopTimer(t *Timer) (stopped bool) {
52 stopped = runtime·deltimer(t);
53 }
54
55 // C runtime.
56
57 void runtime·gc_unixnanotime(int64 *now);
58
59 int64 runtime·unixnanotime(void)
60 {
61 int64 now;
62
63 runtime·gc_unixnanotime(&now);
64 return now;
65 }
66
67 static void timerproc(void);
68 static void siftup(int32);
69 static void siftdown(int32);
70
71 // Ready the goroutine e.data.
72 static void
73 ready(int64 now, Eface e)
74 {
75 USED(now);
76
77 runtime·ready(e.data);
78 }
79
80 static FuncVal readyv = {(void(*)(void))ready};
81
82 // Put the current goroutine to sleep for ns nanoseconds.
83 void
84 runtime·tsleep(int64 ns, int8 *reason)
85 {
86 Timer t;
87
88 if(ns <= 0)
89 return;
90
91 t.when = runtime·nanotime() + ns;
92 t.period = 0;
93 t.fv = &readyv;
94 t.arg.data = g;
95 runtime·lock(&timers);
96 addtimer(&t);
97 runtime·parkunlock(&timers, reason);
98 }
99
100 static FuncVal timerprocv = {timerproc};
101
102 void
103 runtime·addtimer(Timer *t)
104 {
105 runtime·lock(&timers);
106 addtimer(t);
107 runtime·unlock(&timers);
108 }
109
110 // Add a timer to the heap and start or kick the timer proc
111 // if the new timer is earlier than any of the others.
112 static void
113 addtimer(Timer *t)
114 {
115 int32 n;
116 Timer **nt;
117
118 // when must never be negative; otherwise timerproc will overflow
119 // during its delta calculation and never expire other timers.
120 if(t->when < 0)
121 t->when = (1LL<<63)-1;
122
123 if(timers.len >= timers.cap) {
124 // Grow slice.
125 n = 16;
126 if(n <= timers.cap)
127 n = timers.cap*3 / 2;
128 nt = runtime·malloc(n*sizeof nt[0]);
129 runtime·memmove(nt, timers.t, timers.len*sizeof nt[0]);
130 timers.t = nt;
131 timers.cap = n;
132 }
133 t->i = timers.len++;
134 timers.t[t->i] = t;
135 siftup(t->i);
136 if(t->i == 0) {
137 // siftup moved to top: new earliest deadline.
138 if(timers.sleeping) {
139 timers.sleeping = false;
140 runtime·notewakeup(&timers.waitnote);
141 }
142 if(timers.rescheduling) {
143 timers.rescheduling = false;
144 runtime·ready(timers.timerproc);
145 }
146 }
147 if(timers.timerproc == nil) {
148 timers.timerproc = runtime·newproc1(&timerprocv, nil, 0, 0, addt imer);
149 timers.timerproc->issystem = true;
150 }
151 if(debug)
152 dumptimers("addtimer");
153 }
154
155 // Delete timer t from the heap.
156 // Do not need to update the timerproc:
157 // if it wakes up early, no big deal.
158 bool
159 runtime·deltimer(Timer *t)
160 {
161 int32 i;
162
163 // Dereference t so that any panic happens before the lock is held.
164 // Discard result, because t might be moving in the heap.
165 i = t->i;
166 USED(i);
167
168 runtime·lock(&timers);
169
170 // t may not be registered anymore and may have
171 // a bogus i (typically 0, if generated by Go).
172 // Verify it before proceeding.
173 i = t->i;
174 if(i < 0 || i >= timers.len || timers.t[i] != t) {
175 runtime·unlock(&timers);
176 return false;
177 }
178
179 timers.len--;
180 if(i == timers.len) {
181 timers.t[i] = nil;
182 } else {
183 timers.t[i] = timers.t[timers.len];
184 timers.t[timers.len] = nil;
185 timers.t[i]->i = i;
186 siftup(i);
187 siftdown(i);
188 }
189 if(debug)
190 dumptimers("deltimer");
191 runtime·unlock(&timers);
192 return true;
193 }
194
195 // Timerproc runs the time-driven events.
196 // It sleeps until the next event in the timers heap.
197 // If addtimer inserts a new earlier event, addtimer
198 // wakes timerproc early.
199 static void
200 timerproc(void)
201 {
202 int64 delta, now;
203 Timer *t;
204 void (*f)(int64, Eface);
205 Eface arg;
206
207 for(;;) {
208 runtime·lock(&timers);
209 timers.sleeping = false;
210 now = runtime·nanotime();
211 for(;;) {
212 if(timers.len == 0) {
213 delta = -1;
214 break;
215 }
216 t = timers.t[0];
217 delta = t->when - now;
218 if(delta > 0)
219 break;
220 if(t->period > 0) {
221 // leave in heap but adjust next time to fire
222 t->when += t->period * (1 + -delta/t->period);
223 siftdown(0);
224 } else {
225 // remove from heap
226 timers.t[0] = timers.t[--timers.len];
227 timers.t[0]->i = 0;
228 siftdown(0);
229 t->i = -1; // mark as removed
230 }
231 f = (void*)t->fv->fn;
232 arg = t->arg;
233 runtime·unlock(&timers);
234 if(raceenabled)
235 runtime·raceacquire(t);
236 f(now, arg);
237
238 // clear f and arg to avoid leak while sleeping for next timer
239 f = nil;
240 USED(f);
241 arg.type = nil;
242 arg.data = nil;
243 USED(&arg);
244
245 runtime·lock(&timers);
246 }
247 if(delta < 0) {
248 // No timers left - put goroutine to sleep.
249 timers.rescheduling = true;
250 g->isbackground = true;
251 runtime·parkunlock(&timers, "timer goroutine (idle)");
252 g->isbackground = false;
253 continue;
254 }
255 // At least one timer pending. Sleep until then.
256 timers.sleeping = true;
257 runtime·noteclear(&timers.waitnote);
258 runtime·unlock(&timers);
259 runtime·notetsleepg(&timers.waitnote, delta);
260 }
261 }
262
263 // heap maintenance algorithms.
264
265 static void
266 siftup(int32 i)
267 {
268 int32 p;
269 int64 when;
270 Timer **t, *tmp;
271
272 t = timers.t;
273 when = t[i]->when;
274 tmp = t[i];
275 while(i > 0) {
276 p = (i-1)/4; // parent
277 if(when >= t[p]->when)
278 break;
279 t[i] = t[p];
280 t[i]->i = i;
281 t[p] = tmp;
282 tmp->i = p;
283 i = p;
284 }
285 }
286
287 static void
288 siftdown(int32 i)
289 {
290 int32 c, c3, len;
291 int64 when, w, w3;
292 Timer **t, *tmp;
293
294 t = timers.t;
295 len = timers.len;
296 when = t[i]->when;
297 tmp = t[i];
298 for(;;) {
299 c = i*4 + 1; // left child
300 c3 = c + 2; // mid child
301 if(c >= len) {
302 break;
303 }
304 w = t[c]->when;
305 if(c+1 < len && t[c+1]->when < w) {
306 w = t[c+1]->when;
307 c++;
308 }
309 if(c3 < len) {
310 w3 = t[c3]->when;
311 if(c3+1 < len && t[c3+1]->when < w3) {
312 w3 = t[c3+1]->when;
313 c3++;
314 }
315 if(w3 < w) {
316 w = w3;
317 c = c3;
318 }
319 }
320 if(w >= when)
321 break;
322 t[i] = t[c];
323 t[i]->i = i;
324 t[c] = tmp;
325 tmp->i = c;
326 i = c;
327 }
328 }
329
330 static void
331 dumptimers(int8 *msg)
332 {
333 Timer *t;
334 int32 i;
335
336 runtime·printf("timers: %s\n", msg);
337 for(i = 0; i < timers.len; i++) {
338 t = timers.t[i];
339 runtime·printf("\t%d\t%p:\ti %d when %D period %D fn %p\n",
340 i, t, t->i, t->when, t->period, t->fv->fn);
341 }
342 runtime·printf("\n");
343 }
LEFTRIGHT

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b