OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgo/] [runtime/] [time.goc] - Blame information for rev 747

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 747 jeremybenn
// 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.h"
11
#include "arch.h"
12
#include "malloc.h"
13
 
14
static Timers timers;
15
static void addtimer(Timer*);
16
static bool deltimer(Timer*);
17
 
18
// Package time APIs.
19
// Godoc uses the comments in package time, not these.
20
 
21
// time.now is implemented in assembly.
22
 
23
// Sleep puts the current goroutine to sleep for at least ns nanoseconds.
24
func Sleep(ns int64) {
25
        G *g;
26
 
27
        g = runtime_g();
28
        g->status = Gwaiting;
29
        g->waitreason = "sleep";
30
        runtime_tsleep(ns);
31
}
32
 
33
// startTimer adds t to the timer heap.
34
func startTimer(t *Timer) {
35
        addtimer(t);
36
}
37
 
38
// stopTimer removes t from the timer heap if it is there.
39
// It returns true if t was removed, false if t wasn't even there.
40
func stopTimer(t *Timer) (stopped bool) {
41
        stopped = deltimer(t);
42
}
43
 
44
// C runtime.
45
 
46
static void timerproc(void*);
47
static void siftup(int32);
48
static void siftdown(int32);
49
 
50
// Ready the goroutine e.data.
51
static void
52
ready(int64 now, Eface e)
53
{
54
        USED(now);
55
 
56
        runtime_ready(e.__object);
57
}
58
 
59
// Put the current goroutine to sleep for ns nanoseconds.
60
// The caller must have set g->status and g->waitreason.
61
void
62
runtime_tsleep(int64 ns)
63
{
64
        Timer t;
65
 
66
        if(ns <= 0)
67
                return;
68
 
69
        t.when = runtime_nanotime() + ns;
70
        t.period = 0;
71
        t.f = ready;
72
        t.arg.__object = runtime_g();
73
        addtimer(&t);
74
        runtime_gosched();
75
}
76
 
77
// Add a timer to the heap and start or kick the timer proc
78
// if the new timer is earlier than any of the others.
79
static void
80
addtimer(Timer *t)
81
{
82
        int32 n;
83
        Timer **nt;
84
 
85
        runtime_lock(&timers);
86
        if(timers.len >= timers.cap) {
87
                // Grow slice.
88
                n = 16;
89
                if(n <= timers.cap)
90
                        n = timers.cap*3 / 2;
91
                nt = runtime_malloc(n*sizeof nt[0]);
92
                runtime_memmove(nt, timers.t, timers.len*sizeof nt[0]);
93
                runtime_free(timers.t);
94
                timers.t = nt;
95
                timers.cap = n;
96
        }
97
        t->i = timers.len++;
98
        timers.t[t->i] = t;
99
        siftup(t->i);
100
        if(t->i == 0) {
101
                // 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) {
107
                        timers.rescheduling = false;
108
                        runtime_ready(timers.timerproc);
109
                }
110
        }
111
        if(timers.timerproc == nil)
112
                timers.timerproc = __go_go(timerproc, nil);
113
        runtime_unlock(&timers);
114
}
115
 
116
// Delete timer t from the heap.
117
// Do not need to update the timerproc:
118
// if it wakes up early, no big deal.
119
static bool
120
deltimer(Timer *t)
121
{
122
        int32 i;
123
 
124
        runtime_lock(&timers);
125
 
126
        // t may not be registered anymore and may have
127
        // a bogus i (typically 0, if generated by Go).
128
        // Verify it before proceeding.
129
        i = t->i;
130
        if(i < 0 || i >= timers.len || timers.t[i] != t) {
131
                runtime_unlock(&timers);
132
                return false;
133
        }
134
 
135
        timers.len--;
136
        if(i == timers.len) {
137
                timers.t[i] = nil;
138
        } else {
139
                timers.t[i] = timers.t[timers.len];
140
                timers.t[timers.len] = nil;
141
                timers.t[i]->i = i;
142
                siftup(i);
143
                siftdown(i);
144
        }
145
        runtime_unlock(&timers);
146
        return true;
147
}
148
 
149
// Timerproc runs the time-driven events.
150
// It sleeps until the next event in the timers heap.
151
// If addtimer inserts a new earlier event, addtimer
152
// wakes timerproc early.
153
static void
154
timerproc(void* dummy __attribute__ ((unused)))
155
{
156
        G *g;
157
        int64 delta, now;
158
        Timer *t;
159
        void (*f)(int64, Eface);
160
        Eface arg;
161
 
162
        g = runtime_g();
163
        for(;;) {
164
                runtime_lock(&timers);
165
                now = runtime_nanotime();
166
                for(;;) {
167
                        if(timers.len == 0) {
168
                                delta = -1;
169
                                break;
170
                        }
171
                        t = timers.t[0];
172
                        delta = t->when - now;
173
                        if(delta > 0)
174
                                break;
175
                        if(t->period > 0) {
176
                                // leave in heap but adjust next time to fire
177
                                t->when += t->period * (1 + -delta/t->period);
178
                                siftdown(0);
179
                        } else {
180
                                // remove from heap
181
                                timers.t[0] = timers.t[--timers.len];
182
                                timers.t[0]->i = 0;
183
                                siftdown(0);
184
                                t->i = -1;  // mark as removed
185
                        }
186
                        f = t->f;
187
                        arg = t->arg;
188
                        runtime_unlock(&timers);
189
                        f(now, arg);
190
                        runtime_lock(&timers);
191
                }
192
                if(delta < 0) {
193
                        // No timers left - put goroutine to sleep.
194
                        timers.rescheduling = true;
195
                        g->status = Gwaiting;
196
                        g->waitreason = "timer goroutine (idle)";
197
                        runtime_unlock(&timers);
198
                        runtime_gosched();
199
                        continue;
200
                }
201
                // At least one timer pending.  Sleep until then.
202
                timers.sleeping = true;
203
                runtime_noteclear(&timers.waitnote);
204
                runtime_unlock(&timers);
205
                runtime_entersyscall();
206
                runtime_notetsleep(&timers.waitnote, delta);
207
                runtime_exitsyscall();
208
        }
209
}
210
 
211
// heap maintenance algorithms.
212
 
213
static void
214
siftup(int32 i)
215
{
216
        int32 p;
217
        Timer **t, *tmp;
218
 
219
        t = timers.t;
220
        while(i > 0) {
221
                p = (i-1)/2;  // parent
222
                if(t[i]->when >= t[p]->when)
223
                        break;
224
                tmp = t[i];
225
                t[i] = t[p];
226
                t[p] = tmp;
227
                t[i]->i = i;
228
                t[p]->i = p;
229
                i = p;
230
        }
231
}
232
 
233
static void
234
siftdown(int32 i)
235
{
236
        int32 c, len;
237
        Timer **t, *tmp;
238
 
239
        t = timers.t;
240
        len = timers.len;
241
        for(;;) {
242
                c = i*2 + 1;  // left child
243
                if(c >= len) {
244
                        break;
245
                }
246
                if(c+1 < len && t[c+1]->when < t[c]->when)
247
                        c++;
248
                if(t[c]->when >= t[i]->when)
249
                        break;
250
                tmp = t[i];
251
                t[i] = t[c];
252
                t[c] = tmp;
253
                t[i]->i = i;
254
                t[c]->i = c;
255
                i = c;
256
        }
257
}
258
 
259
void
260
runtime_time_scan(void (*scan)(byte*, int64))
261
{
262
        scan((byte*)&timers, sizeof timers);
263
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.