LEFT | RIGHT |
1 // Copyright 2010 The Go Authors. All rights reserved. | 1 // Copyright 2010 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 #include "runtime.h" | 5 #include "runtime.h" |
6 #include "os.h" | 6 #include "os.h" |
7 #include "arch.h" | 7 #include "arch.h" |
8 | 8 |
9 int8 *goos = "plan9"; | 9 int8 *goos = "plan9"; |
10 | 10 |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
62 runtime·usleep(uint32 µs) | 62 runtime·usleep(uint32 µs) |
63 { | 63 { |
64 uint32 ms; | 64 uint32 ms; |
65 | 65 |
66 ms = µs/1000; | 66 ms = µs/1000; |
67 if(ms == 0) | 67 if(ms == 0) |
68 ms = 1; | 68 ms = 1; |
69 runtime·sleep(ms); | 69 runtime·sleep(ms); |
70 } | 70 } |
71 | 71 |
72 void | 72 int64 |
73 runtime·gettime(int64 *sec, int32 *usec) | 73 runtime·nanotime(void) |
74 { | 74 { |
| 75 » static int32 fd = -1; |
75 byte b[8]; | 76 byte b[8]; |
76 » int32 fd, n; | 77 » uint32 hi, lo; |
77 » int64 t; | 78 |
78 | 79 » // As long as all goroutines share the same file |
79 » fd = runtime·open((byte*)"/dev/bintime", OREAD|OCEXEC); | 80 » // descriptor table we can get away with using |
80 » if(fd < 0) | 81 » // just a static fd. Without a lock the file can |
81 » » return; | 82 » // be opened twice but that's okay. |
82 » n = runtime·pread(fd, b, sizeof b, 0); | 83 » // |
83 » runtime·close(fd); | 84 » // Using /dev/bintime gives us a latency on the |
84 » if(n != sizeof b) | 85 » // order of ten microseconds between two calls. |
85 » » return; | 86 » // |
86 » t = ((int64)b[0])<<56 | | 87 » // The naïve implementation (without the cached |
87 » » ((int64)b[1])<<48 | | 88 » // file descriptor) is roughly four times slower |
88 » » ((int64)b[2])<<40 | | 89 » // in 9vx on a 2.16 GHz Intel Core 2 Duo. |
89 » » ((int64)b[3])<<32 | | 90 »······· |
90 » » ((int64)b[4])<<24 | | 91 » if(fd < 0 && (fd = runtime·open((byte*)"/dev/bintime", OREAD|OCEXEC)) <
0) |
91 » » ((int64)b[5])<<16 | | 92 » » return 0; |
92 » » ((int64)b[6])<<8 | | 93 » if(runtime·pread(fd, b, sizeof b, 0) != sizeof b) |
93 » » ((int64)b[7]); | 94 » » return 0; |
94 » *sec = t/1000000000; | 95 » hi = b[0]<<24 | b[1]<<16 | b[2]<<8 | b[3]; |
95 » *usec = t%1000000000 / 1000; | 96 » lo = b[4]<<24 | b[5]<<16 | b[6]<<8 | b[7]; |
96 » return; | 97 » return (int64)hi<<32 | (int64)lo; |
97 } | 98 } |
98 | 99 |
99 extern Tos *_tos; | 100 extern Tos *_tos; |
100 void | 101 void |
101 runtime·exit(int32) | 102 runtime·exit(int32) |
102 { | 103 { |
103 int32 fd; | 104 int32 fd; |
104 uint8 buf[128]; | 105 uint8 buf[128]; |
105 uint8 tmp[16]; | 106 uint8 tmp[16]; |
106 uint8 *p, *q; | 107 uint8 *p, *q; |
107 int32 pid; | 108 int32 pid; |
108 » | 109 |
109 runtime·memclr(buf, sizeof buf); | 110 runtime·memclr(buf, sizeof buf); |
110 runtime·memclr(tmp, sizeof tmp); | 111 runtime·memclr(tmp, sizeof tmp); |
111 pid = _tos->pid; | 112 pid = _tos->pid; |
112 | 113 |
113 /* build path string /proc/pid/notepg */ | 114 /* build path string /proc/pid/notepg */ |
114 for(q=tmp; pid > 0;) { | 115 for(q=tmp; pid > 0;) { |
115 *q++ = '0' + (pid%10); | 116 *q++ = '0' + (pid%10); |
116 pid = pid/10; | 117 pid = pid/10; |
117 } | 118 } |
118 p = buf; | 119 p = buf; |
119 runtime·memmove((void*)p, (void*)"/proc/", 6); | 120 runtime·memmove((void*)p, (void*)"/proc/", 6); |
120 p += 6; | 121 p += 6; |
121 for(q--; q >= tmp;) | 122 for(q--; q >= tmp;) |
122 *p++ = *q--; | 123 *p++ = *q--; |
123 runtime·memmove((void*)p, (void*)"/notepg", 7); | 124 runtime·memmove((void*)p, (void*)"/notepg", 7); |
124 » | 125 |
125 /* post interrupt note */ | 126 /* post interrupt note */ |
126 fd = runtime·open(buf, OWRITE); | 127 fd = runtime·open(buf, OWRITE); |
127 runtime·write(fd, "interrupt", 9); | 128 runtime·write(fd, "interrupt", 9); |
128 runtime·exits(nil); | 129 runtime·exits(nil); |
129 } | 130 } |
130 | 131 |
131 void | 132 void |
132 runtime·newosproc(M *m, G *g, void *stk, void (*fn)(void)) | 133 runtime·newosproc(M *m, G *g, void *stk, void (*fn)(void)) |
133 { | 134 { |
134 m->tls[0] = m->id; // so 386 asm can find it | 135 m->tls[0] = m->id; // so 386 asm can find it |
135 if(0){ | 136 if(0){ |
136 runtime·printf("newosproc stk=%p m=%p g=%p fn=%p rfork=%p id=%d/
%d ostk=%p\n", | 137 runtime·printf("newosproc stk=%p m=%p g=%p fn=%p rfork=%p id=%d/
%d ostk=%p\n", |
137 stk, m, g, fn, runtime·rfork, m->id, m->tls[0], &m); | 138 stk, m, g, fn, runtime·rfork, m->id, m->tls[0], &m); |
138 » }········ | 139 » } |
139 »······· | 140 |
140 if(runtime·rfork(RFPROC|RFMEM|RFNOWAIT, stk, m, g, fn) < 0) | 141 if(runtime·rfork(RFPROC|RFMEM|RFNOWAIT, stk, m, g, fn) < 0) |
141 runtime·throw("newosproc: rfork failed"); | 142 runtime·throw("newosproc: rfork failed"); |
142 } | 143 } |
143 | 144 |
144 uintptr | 145 uintptr |
145 runtime·semacreate(void) | 146 runtime·semacreate(void) |
146 { | 147 { |
147 return 1; | 148 return 1; |
148 } | 149 } |
149 | 150 |
150 void | 151 int32 |
151 runtime·semasleep(void) | 152 runtime·semasleep(int64 ns) |
152 { | 153 { |
| 154 » int32 ret; |
| 155 » int32 ms; |
| 156 |
| 157 » if(ns >= 0) { |
| 158 » » // TODO: Plan 9 needs a new system call, tsemacquire. |
| 159 » » // The kernel implementation is the same as semacquire |
| 160 » » // except with a tsleep and check for timeout. |
| 161 » » // It would be great if the implementation returned the |
| 162 » » // value that was added to the semaphore, so that on |
| 163 » » // timeout the return value would be 0, on success 1. |
| 164 » » // Then the error string does not have to be parsed |
| 165 » » // to detect timeout. |
| 166 » » // |
| 167 » » // If a negative time indicates no timeout, then |
| 168 » » // semacquire can be implemented (in the kernel) |
| 169 » » // as tsemacquire(p, v, -1). |
| 170 » » runtime·throw("semasleep: timed sleep not implemented on Plan 9"
); |
| 171 |
| 172 » » /* |
| 173 » » if(ns < 0) |
| 174 » » » ms = -1; |
| 175 » » else if(ns/1000 > 0x7fffffffll) |
| 176 » » » ms = 0x7fffffff; |
| 177 » » else |
| 178 » » » ms = ns/1000; |
| 179 » » ret = runtime·plan9_tsemacquire(&m->waitsemacount, 1, ms); |
| 180 » » if(ret == 1) |
| 181 » » » return 0; // success |
| 182 » » return -1; // timeout or interrupted |
| 183 » » */ |
| 184 » } |
| 185 |
153 while(runtime·plan9_semacquire(&m->waitsemacount, 1) < 0) { | 186 while(runtime·plan9_semacquire(&m->waitsemacount, 1) < 0) { |
154 /* interrupted; try again */ | 187 /* interrupted; try again */ |
155 } | 188 } |
| 189 return 0; // success |
156 } | 190 } |
157 | 191 |
158 void | 192 void |
159 runtime·semawakeup(M *mp) | 193 runtime·semawakeup(M *mp) |
160 { | 194 { |
161 runtime·plan9_semrelease(&mp->waitsemacount, 1); | 195 runtime·plan9_semrelease(&mp->waitsemacount, 1); |
162 } | 196 } |
163 | 197 |
164 void | 198 void |
165 os·sigpipe(void) | 199 os·sigpipe(void) |
(...skipping 16 matching lines...) Expand all Loading... |
182 runtime·read(int32 fd, void *buf, int32 nbytes) | 216 runtime·read(int32 fd, void *buf, int32 nbytes) |
183 { | 217 { |
184 return runtime·pread(fd, buf, nbytes, -1LL); | 218 return runtime·pread(fd, buf, nbytes, -1LL); |
185 } | 219 } |
186 | 220 |
187 int32 | 221 int32 |
188 runtime·write(int32 fd, void *buf, int32 nbytes) | 222 runtime·write(int32 fd, void *buf, int32 nbytes) |
189 { | 223 { |
190 return runtime·pwrite(fd, buf, nbytes, -1LL); | 224 return runtime·pwrite(fd, buf, nbytes, -1LL); |
191 } | 225 } |
192 | |
LEFT | RIGHT |