blob: f8c543f6f6ad0bbc2c1e375cda5afc4b110700a1 [file] [log] [blame]
Brent Austinba3052e2015-04-21 16:08:23 -07001// Copyright 2010 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#include "runtime.h"
6#include "os_GOOS.h"
7#include "arch_GOARCH.h"
8#include "textflag.h"
9#include "malloc.h"
10
11int8 *goos = "plan9";
12extern SigTab runtime·sigtab[];
13
14int32 runtime·postnote(int32, int8*);
15
16// Called to initialize a new m (including the bootstrap m).
17// Called on the parent thread (main thread in case of bootstrap), can allocate memory.
18void
19runtime·mpreinit(M *mp)
20{
21 // Initialize stack and goroutine for note handling.
22 mp->gsignal = runtime·malg(32*1024);
23 mp->gsignal->m = mp;
24 mp->notesig = (int8*)runtime·mallocgc(ERRMAX*sizeof(int8), nil, FlagNoScan);
25
26 // Initialize stack for handling strings from the
27 // errstr system call, as used in package syscall.
28 mp->errstr = (byte*)runtime·mallocgc(ERRMAX*sizeof(byte), nil, FlagNoScan);
29}
30
31// Called to initialize a new m (including the bootstrap m).
32// Called on the new thread, can not allocate memory.
33void
34runtime·minit(void)
35{
36 // Mask all SSE floating-point exceptions
37 // when running on the 64-bit kernel.
38 runtime·setfpmasks();
39}
40
41// Called from dropm to undo the effect of an minit.
42void
43runtime·unminit(void)
44{
45}
46
47
48static int32
49getproccount(void)
50{
51 int32 fd, i, n, ncpu;
52 byte buf[2048];
53
54 fd = runtime·open("/dev/sysstat", OREAD, 0);
55 if(fd < 0)
56 return 1;
57 ncpu = 0;
58 for(;;) {
59 n = runtime·read(fd, buf, sizeof buf);
60 if(n <= 0)
61 break;
62 for(i = 0; i < n; i++) {
63 if(buf[i] == '\n')
64 ncpu++;
65 }
66 }
67 runtime·close(fd);
68 return ncpu > 0 ? ncpu : 1;
69}
70
71static int32
72getpid(void)
73{
74 byte b[20], *c;
75 int32 fd;
76
77 runtime·memclr(b, sizeof(b));
78 fd = runtime·open("#c/pid", 0, 0);
79 if(fd >= 0) {
80 runtime·read(fd, b, sizeof(b));
81 runtime·close(fd);
82 }
83 c = b;
84 while(*c == ' ' || *c == '\t')
85 c++;
86 return runtime·atoi(c);
87}
88
89void
90runtime·osinit(void)
91{
92 runtime·ncpu = getproccount();
93 g->m->procid = getpid();
94 runtime·notify(runtime·sigtramp);
95}
96
97void
98runtime·crash(void)
99{
100 runtime·notify(nil);
101 *(int32*)0 = 0;
102}
103
104#pragma textflag NOSPLIT
105void
106runtime·get_random_data(byte **rnd, int32 *rnd_len)
107{
108 static byte random_data[HashRandomBytes];
109 int32 fd;
110
111 fd = runtime·open("/dev/random", 0 /* O_RDONLY */, 0);
112 if(runtime·read(fd, random_data, HashRandomBytes) == HashRandomBytes) {
113 *rnd = random_data;
114 *rnd_len = HashRandomBytes;
115 } else {
116 *rnd = nil;
117 *rnd_len = 0;
118 }
119 runtime·close(fd);
120}
121
122void
123runtime·goenvs(void)
124{
125}
126
127void
128runtime·initsig(void)
129{
130}
131
132#pragma textflag NOSPLIT
133void
134runtime·osyield(void)
135{
136 runtime·sleep(0);
137}
138
139#pragma textflag NOSPLIT
140void
141runtime·usleep(uint32 µs)
142{
143 uint32 ms;
144
145 ms = µs/1000;
146 if(ms == 0)
147 ms = 1;
148 runtime·sleep(ms);
149}
150
151#pragma textflag NOSPLIT
152int64
153runtime·nanotime(void)
154{
155 int64 ns, scratch;
156
157 ns = runtime·nsec(&scratch);
158 // TODO(aram): remove hack after I fix _nsec in the pc64 kernel.
159 if(ns == 0)
160 return scratch;
161 return ns;
162}
163
164#pragma textflag NOSPLIT
165void
166runtime·itoa(int32 n, byte *p, uint32 len)
167{
168 byte *q, c;
169 uint32 i;
170
171 if(len <= 1)
172 return;
173
174 runtime·memclr(p, len);
175 q = p;
176
177 if(n==0) {
178 *q++ = '0';
179 USED(q);
180 return;
181 }
182 if(n < 0) {
183 *q++ = '-';
184 p++;
185 n = -n;
186 }
187 for(i=0; n > 0 && i < len; i++) {
188 *q++ = '0' + (n%10);
189 n = n/10;
190 }
191 for(q--; q >= p; ) {
192 c = *p;
193 *p++ = *q;
194 *q-- = c;
195 }
196}
197
198void
199runtime·goexitsall(int8 *status)
200{
201 int8 buf[ERRMAX];
202 M *mp;
203 int32 pid;
204
205 runtime·snprintf((byte*)buf, sizeof buf, "go: exit %s", status);
206 pid = getpid();
207 for(mp=runtime·atomicloadp(&runtime·allm); mp; mp=mp->alllink)
208 if(mp->procid != pid)
209 runtime·postnote(mp->procid, buf);
210}
211
212int32
213runtime·postnote(int32 pid, int8* msg)
214{
215 int32 fd;
216 intgo len;
217 uint8 buf[128];
218 uint8 tmp[16];
219 uint8 *p, *q;
220
221 runtime·memclr(buf, sizeof buf);
222
223 /* build path string /proc/pid/note */
224 q = tmp;
225 p = buf;
226 runtime·itoa(pid, tmp, sizeof tmp);
227 runtime·memmove((void*)p, (void*)"/proc/", 6);
228 for(p += 6; *p++ = *q++; );
229 p--;
230 runtime·memmove((void*)p, (void*)"/note", 5);
231
232 fd = runtime·open((int8*)buf, OWRITE, 0);
233 if(fd < 0)
234 return -1;
235
236 len = runtime·findnull((byte*)msg);
237 if(runtime·write(fd, msg, len) != len) {
238 runtime·close(fd);
239 return -1;
240 }
241 runtime·close(fd);
242 return 0;
243}
244
245static void exit(void);
246
247#pragma textflag NOSPLIT
248void
249runtime·exit(int32 e)
250{
251 void (*fn)(void);
252
253 g->m->scalararg[0] = e;
254 fn = exit;
255 runtime·onM(&fn);
256}
257
258static void
259exit(void)
260{
261 int32 e;
262 byte tmp[16];
263 int8 *status;
264
265 e = g->m->scalararg[0];
266 g->m->scalararg[0] = 0;
267
268 if(e == 0)
269 status = "";
270 else {
271 /* build error string */
272 runtime·itoa(e, tmp, sizeof tmp);
273 status = (int8*)tmp;
274 }
275
276 runtime·goexitsall(status);
277 runtime·exits(status);
278}
279
280void
281runtime·newosproc(M *mp, void *stk)
282{
283 int32 pid;
284
285 if(0)
286 runtime·printf("newosproc mp=%p ostk=%p\n", mp, &mp);
287
288 USED(stk);
289 if((pid = runtime·rfork(RFPROC|RFMEM|RFNOWAIT)) < 0)
290 runtime·throw("newosproc: rfork failed\n");
291 if(pid == 0)
292 runtime·tstart_plan9(mp);
293}
294
295#pragma textflag NOSPLIT
296uintptr
297runtime·semacreate(void)
298{
299 return 1;
300}
301
302#pragma textflag NOSPLIT
303int32
304runtime·semasleep(int64 ns)
305{
306 int32 ret;
307 int32 ms;
308
309 if(ns >= 0) {
310 ms = runtime·timediv(ns, 1000000, nil);
311 if(ms == 0)
312 ms = 1;
313 ret = runtime·plan9_tsemacquire(&g->m->waitsemacount, ms);
314 if(ret == 1)
315 return 0; // success
316 return -1; // timeout or interrupted
317 }
318
319 while(runtime·plan9_semacquire(&g->m->waitsemacount, 1) < 0) {
320 /* interrupted; try again (c.f. lock_sema.c) */
321 }
322 return 0; // success
323}
324
325#pragma textflag NOSPLIT
326void
327runtime·semawakeup(M *mp)
328{
329 runtime·plan9_semrelease(&mp->waitsemacount, 1);
330}
331
332#pragma textflag NOSPLIT
333int32
334runtime·read(int32 fd, void *buf, int32 nbytes)
335{
336 return runtime·pread(fd, buf, nbytes, -1LL);
337}
338
339#pragma textflag NOSPLIT
340int32
341runtime·write(uintptr fd, void *buf, int32 nbytes)
342{
343 return runtime·pwrite((int32)fd, buf, nbytes, -1LL);
344}
345
346uintptr
347runtime·memlimit(void)
348{
349 return 0;
350}
351
352#pragma dataflag NOPTR
353static int8 badsignal[] = "runtime: signal received on thread not created by Go.\n";
354
355// This runs on a foreign stack, without an m or a g. No stack split.
356#pragma textflag NOSPLIT
357void
358runtime·badsignal2(void)
359{
360 runtime·pwrite(2, badsignal, sizeof badsignal - 1, -1LL);
361 runtime·exits(badsignal);
362}