blob: db64b01c8da817a3bc8d719daf5eed35d5f2a08c [file] [log] [blame]
Mikio Hara4aeb0fc2013-03-20 02:40:29 +09001// Copyright 2011 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.
Christopher Nielsen26089cf2011-12-12 18:10:11 -05004
5#include "runtime.h"
Russ Cox851f3012011-12-16 15:33:58 -05006#include "defs_GOOS_GOARCH.h"
7#include "os_GOOS.h"
Russ Coxe9d62a62013-03-14 11:35:13 -07008#include "signal_unix.h"
Christopher Nielsen26089cf2011-12-12 18:10:11 -05009#include "stack.h"
Russ Coxcb040d52014-09-04 23:05:18 -040010#include "textflag.h"
Christopher Nielsen26089cf2011-12-12 18:10:11 -050011
12enum
13{
14 ESRCH = 3,
15 ENOTSUP = 91,
16
Joel Sing5a043de2012-05-24 11:33:11 +100017 // From NetBSD's <sys/time.h>
Christopher Nielsen26089cf2011-12-12 18:10:11 -050018 CLOCK_REALTIME = 0,
19 CLOCK_VIRTUAL = 1,
20 CLOCK_PROF = 2,
21 CLOCK_MONOTONIC = 3
22};
23
24extern SigTab runtime·sigtab[];
25
Russ Coxc7f7bbb2013-02-15 12:18:33 -050026static Sigset sigset_none;
Joel Sing5a043de2012-05-24 11:33:11 +100027static Sigset sigset_all = { ~(uint32)0, ~(uint32)0, ~(uint32)0, ~(uint32)0, };
Joel Sing5a043de2012-05-24 11:33:11 +100028
29extern void runtime·getcontext(UcontextT *context);
30extern int32 runtime·lwp_create(UcontextT *context, uintptr flags, void *lwpid);
Jingcheng Zhang70e967b2012-12-19 00:30:29 +080031extern void runtime·lwp_mcontext_init(void *mc, void *stack, M *mp, G *gp, void (*fn)(void));
Joel Sing5a043de2012-05-24 11:33:11 +100032extern int32 runtime·lwp_park(Timespec *abstime, int32 unpark, void *hint, void *unparkhint);
33extern int32 runtime·lwp_unpark(int32 lwp, void *hint);
Joel Singdeb93b02012-05-31 03:27:04 +100034extern int32 runtime·lwp_self(void);
Christopher Nielsen26089cf2011-12-12 18:10:11 -050035
36// From NetBSD's <sys/sysctl.h>
37#define CTL_HW 6
38#define HW_NCPU 3
39
40static int32
41getncpu(void)
42{
43 uint32 mib[2];
44 uint32 out;
45 int32 ret;
46 uintptr nout;
47
48 // Fetch hw.ncpu via sysctl.
49 mib[0] = CTL_HW;
50 mib[1] = HW_NCPU;
51 nout = sizeof out;
52 out = 0;
53 ret = runtime·sysctl(mib, 2, (byte*)&out, &nout, nil, 0);
54 if(ret >= 0)
55 return out;
56 else
57 return 1;
58}
59
Russ Coxdb58ab92014-09-04 21:12:31 -040060#pragma textflag NOSPLIT
Christopher Nielsen26089cf2011-12-12 18:10:11 -050061uintptr
62runtime·semacreate(void)
63{
64 return 1;
65}
66
Russ Coxdb58ab92014-09-04 21:12:31 -040067static void
68semasleep(void)
Christopher Nielsen26089cf2011-12-12 18:10:11 -050069{
Russ Coxdb58ab92014-09-04 21:12:31 -040070 int64 ns;
Christopher Nielsen26089cf2011-12-12 18:10:11 -050071 Timespec ts;
72
Russ Coxdb58ab92014-09-04 21:12:31 -040073 ns = (int64)(uint32)g->m->scalararg[0] | (int64)(uint32)g->m->scalararg[1]<<32;
74 g->m->scalararg[0] = 0;
75 g->m->scalararg[1] = 0;
76
Christopher Nielsen26089cf2011-12-12 18:10:11 -050077 // spin-mutex lock
Russ Cox89f185f2014-06-26 11:54:39 -040078 while(runtime·xchg(&g->m->waitsemalock, 1))
Christopher Nielsen26089cf2011-12-12 18:10:11 -050079 runtime·osyield();
80
81 for(;;) {
82 // lock held
Russ Cox89f185f2014-06-26 11:54:39 -040083 if(g->m->waitsemacount == 0) {
Christopher Nielsen26089cf2011-12-12 18:10:11 -050084 // sleep until semaphore != 0 or timeout.
85 // thrsleep unlocks m->waitsemalock.
Joel Sing5a043de2012-05-24 11:33:11 +100086 if(ns < 0) {
87 // TODO(jsing) - potential deadlock!
88 //
89 // There is a potential deadlock here since we
90 // have to release the waitsemalock mutex
91 // before we call lwp_park() to suspend the
92 // thread. This allows another thread to
93 // release the lock and call lwp_unpark()
94 // before the thread is actually suspended.
95 // If this occurs the current thread will end
96 // up sleeping indefinitely. Unfortunately
97 // the NetBSD kernel does not appear to provide
98 // a mechanism for unlocking the userspace
99 // mutex once the thread is actually parked.
Russ Cox89f185f2014-06-26 11:54:39 -0400100 runtime·atomicstore(&g->m->waitsemalock, 0);
101 runtime·lwp_park(nil, 0, &g->m->waitsemacount, nil);
Joel Sing5a043de2012-05-24 11:33:11 +1000102 } else {
Dmitriy Vyukov21315c342013-08-01 15:19:45 +0400103 ns = ns + runtime·nanotime();
Russ Cox98cc58e2013-07-29 16:31:42 -0400104 // NOTE: tv_nsec is int64 on amd64, so this assumes a little-endian system.
Dmitriy Vyukove84d9e12013-07-29 22:22:34 +0400105 ts.tv_nsec = 0;
Russ Cox98cc58e2013-07-29 16:31:42 -0400106 ts.tv_sec = runtime·timediv(ns, 1000000000, (int32*)&ts.tv_nsec);
Joel Sing5a043de2012-05-24 11:33:11 +1000107 // TODO(jsing) - potential deadlock!
108 // See above for details.
Russ Cox89f185f2014-06-26 11:54:39 -0400109 runtime·atomicstore(&g->m->waitsemalock, 0);
110 runtime·lwp_park(&ts, 0, &g->m->waitsemacount, nil);
Christopher Nielsen26089cf2011-12-12 18:10:11 -0500111 }
112 // reacquire lock
Russ Cox89f185f2014-06-26 11:54:39 -0400113 while(runtime·xchg(&g->m->waitsemalock, 1))
Christopher Nielsen26089cf2011-12-12 18:10:11 -0500114 runtime·osyield();
115 }
116
117 // lock held (again)
Russ Cox89f185f2014-06-26 11:54:39 -0400118 if(g->m->waitsemacount != 0) {
Christopher Nielsen26089cf2011-12-12 18:10:11 -0500119 // semaphore is available.
Russ Cox89f185f2014-06-26 11:54:39 -0400120 g->m->waitsemacount--;
Christopher Nielsen26089cf2011-12-12 18:10:11 -0500121 // spin-mutex unlock
Russ Cox89f185f2014-06-26 11:54:39 -0400122 runtime·atomicstore(&g->m->waitsemalock, 0);
Russ Coxdb58ab92014-09-04 21:12:31 -0400123 g->m->scalararg[0] = 0; // semaphore acquired
124 return;
Christopher Nielsen26089cf2011-12-12 18:10:11 -0500125 }
126
127 // semaphore not available.
128 // if there is a timeout, stop now.
129 // otherwise keep trying.
130 if(ns >= 0)
131 break;
132 }
133
134 // lock held but giving up
135 // spin-mutex unlock
Russ Cox89f185f2014-06-26 11:54:39 -0400136 runtime·atomicstore(&g->m->waitsemalock, 0);
Russ Coxdb58ab92014-09-04 21:12:31 -0400137 g->m->scalararg[0] = -1;
138 return;
Christopher Nielsen26089cf2011-12-12 18:10:11 -0500139}
140
Russ Coxdb58ab92014-09-04 21:12:31 -0400141#pragma textflag NOSPLIT
142int32
143runtime·semasleep(int64 ns)
144{
145 int32 r;
146 void (*fn)(void);
147
148 g->m->scalararg[0] = (uint32)ns;
149 g->m->scalararg[1] = (uint32)(ns>>32);
150 fn = semasleep;
151 runtime·onM(&fn);
152 r = g->m->scalararg[0];
153 g->m->scalararg[0] = 0;
154 return r;
155}
156
157static void badsemawakeup(void);
158
159#pragma textflag NOSPLIT
Christopher Nielsen26089cf2011-12-12 18:10:11 -0500160void
161runtime·semawakeup(M *mp)
162{
163 uint32 ret;
Russ Coxdb58ab92014-09-04 21:12:31 -0400164 void (*fn)(void);
165 void *oldptr;
166 uintptr oldscalar;
Christopher Nielsen26089cf2011-12-12 18:10:11 -0500167
168 // spin-mutex lock
169 while(runtime·xchg(&mp->waitsemalock, 1))
170 runtime·osyield();
171 mp->waitsemacount++;
Joel Sing5a043de2012-05-24 11:33:11 +1000172 // TODO(jsing) - potential deadlock, see semasleep() for details.
173 // Confirm that LWP is parked before unparking...
174 ret = runtime·lwp_unpark(mp->procid, &mp->waitsemacount);
Russ Coxdb58ab92014-09-04 21:12:31 -0400175 if(ret != 0 && ret != ESRCH) {
176 // semawakeup can be called on signal stack.
177 // Save old ptrarg/scalararg so we can restore them.
178 oldptr = g->m->ptrarg[0];
179 oldscalar = g->m->scalararg[0];
180 g->m->ptrarg[0] = mp;
181 g->m->scalararg[0] = ret;
182 fn = badsemawakeup;
183 if(g == g->m->gsignal)
184 fn();
185 else
186 runtime·onM(&fn);
187 g->m->ptrarg[0] = oldptr;
188 g->m->scalararg[0] = oldscalar;
189 }
Christopher Nielsen26089cf2011-12-12 18:10:11 -0500190 // spin-mutex unlock
191 runtime·atomicstore(&mp->waitsemalock, 0);
192}
193
Russ Coxdb58ab92014-09-04 21:12:31 -0400194static void
195badsemawakeup(void)
196{
197 M *mp;
198 int32 ret;
199
200 mp = g->m->ptrarg[0];
201 g->m->ptrarg[0] = nil;
202 ret = g->m->scalararg[0];
203 g->m->scalararg[0] = 0;
204
205 runtime·printf("thrwakeup addr=%p sem=%d ret=%d\n", &mp->waitsemacount, mp->waitsemacount, ret);
206}
207
Christopher Nielsen26089cf2011-12-12 18:10:11 -0500208void
Russ Coxe6a3e222013-03-01 11:44:43 -0500209runtime·newosproc(M *mp, void *stk)
Christopher Nielsen26089cf2011-12-12 18:10:11 -0500210{
Joel Sing5a043de2012-05-24 11:33:11 +1000211 UcontextT uc;
Christopher Nielsen26089cf2011-12-12 18:10:11 -0500212 int32 ret;
213
Joel Sing5a043de2012-05-24 11:33:11 +1000214 if(0) {
Christopher Nielsen26089cf2011-12-12 18:10:11 -0500215 runtime·printf(
Russ Coxe6a3e222013-03-01 11:44:43 -0500216 "newosproc stk=%p m=%p g=%p id=%d/%d ostk=%p\n",
217 stk, mp, mp->g0, mp->id, (int32)mp->tls[0], &mp);
Christopher Nielsen26089cf2011-12-12 18:10:11 -0500218 }
219
Jingcheng Zhang70e967b2012-12-19 00:30:29 +0800220 mp->tls[0] = mp->id; // so 386 asm can find it
Christopher Nielsen26089cf2011-12-12 18:10:11 -0500221
Joel Sing5a043de2012-05-24 11:33:11 +1000222 runtime·getcontext(&uc);
223
224 uc.uc_flags = _UC_SIGMASK | _UC_CPU;
225 uc.uc_link = nil;
226 uc.uc_sigmask = sigset_all;
227
Russ Coxe6a3e222013-03-01 11:44:43 -0500228 runtime·lwp_mcontext_init(&uc.uc_mcontext, stk, mp, mp->g0, runtime·mstart);
Joel Sing5a043de2012-05-24 11:33:11 +1000229
Jingcheng Zhang70e967b2012-12-19 00:30:29 +0800230 ret = runtime·lwp_create(&uc, 0, &mp->procid);
Joel Sing5a043de2012-05-24 11:33:11 +1000231
232 if(ret < 0) {
Christopher Nielsen26089cf2011-12-12 18:10:11 -0500233 runtime·printf("runtime: failed to create new OS thread (have %d already; errno=%d)\n", runtime·mcount() - 1, -ret);
Christopher Nielsen26089cf2011-12-12 18:10:11 -0500234 runtime·throw("runtime.newosproc");
235 }
236}
237
238void
239runtime·osinit(void)
240{
241 runtime·ncpu = getncpu();
242}
243
Russ Coxf545b052014-09-04 15:53:45 -0400244#pragma textflag NOSPLIT
Christopher Nielsen26089cf2011-12-12 18:10:11 -0500245void
Keith Randalla5d40242013-03-12 10:47:44 -0700246runtime·get_random_data(byte **rnd, int32 *rnd_len)
247{
Keith Randall548b15d2014-05-31 19:21:17 -0400248 #pragma dataflag NOPTR
Keith Randalla5d40242013-03-12 10:47:44 -0700249 static byte urandom_data[HashRandomBytes];
250 int32 fd;
251 fd = runtime·open("/dev/urandom", 0 /* O_RDONLY */, 0);
252 if(runtime·read(fd, urandom_data, HashRandomBytes) == HashRandomBytes) {
253 *rnd = urandom_data;
254 *rnd_len = HashRandomBytes;
255 } else {
256 *rnd = nil;
257 *rnd_len = 0;
258 }
259 runtime·close(fd);
260}
261
262void
Christopher Nielsen26089cf2011-12-12 18:10:11 -0500263runtime·goenvs(void)
264{
265 runtime·goenvs_unix();
266}
267
268// Called to initialize a new m (including the bootstrap m).
Dmitriy Vyukova0955a22013-02-21 16:24:38 +0400269// Called on the parent thread (main thread in case of bootstrap), can allocate memory.
270void
271runtime·mpreinit(M *mp)
272{
273 mp->gsignal = runtime·malg(32*1024);
Russ Cox89f185f2014-06-26 11:54:39 -0400274 mp->gsignal->m = mp;
Dmitriy Vyukova0955a22013-02-21 16:24:38 +0400275}
276
277// Called to initialize a new m (including the bootstrap m).
278// Called on the new thread, can not allocate memory.
Christopher Nielsen26089cf2011-12-12 18:10:11 -0500279void
280runtime·minit(void)
281{
Russ Cox89f185f2014-06-26 11:54:39 -0400282 g->m->procid = runtime·lwp_self();
Joel Singdeb93b02012-05-31 03:27:04 +1000283
Christopher Nielsen26089cf2011-12-12 18:10:11 -0500284 // Initialize signal handling
Russ Cox89f185f2014-06-26 11:54:39 -0400285 runtime·signalstack((byte*)g->m->gsignal->stackguard - StackGuard, 32*1024);
Russ Coxc7f7bbb2013-02-15 12:18:33 -0500286 runtime·sigprocmask(SIG_SETMASK, &sigset_none, nil);
Christopher Nielsen26089cf2011-12-12 18:10:11 -0500287}
288
Russ Cox6c976392013-02-20 17:48:23 -0500289// Called from dropm to undo the effect of an minit.
290void
291runtime·unminit(void)
292{
293 runtime·signalstack(nil, 0);
294}
295
Russ Cox102274a2012-02-24 15:28:51 -0500296uintptr
297runtime·memlimit(void)
298{
299 return 0;
300}
Russ Cox6e2ae0a2012-02-28 16:18:24 -0500301
Russ Coxe9d62a62013-03-14 11:35:13 -0700302extern void runtime·sigtramp(void);
303
304typedef struct sigaction {
305 union {
306 void (*_sa_handler)(int32);
307 void (*_sa_sigaction)(int32, Siginfo*, void *);
308 } _sa_u; /* signal handler */
309 uint32 sa_mask[4]; /* signal mask to apply */
310 int32 sa_flags; /* see signal options below */
Russ Cox9a75c742014-08-29 16:00:31 -0400311} SigactionT;
Russ Coxe9d62a62013-03-14 11:35:13 -0700312
313void
314runtime·setsig(int32 i, GoSighandler *fn, bool restart)
315{
Russ Cox9a75c742014-08-29 16:00:31 -0400316 SigactionT sa;
Russ Coxe9d62a62013-03-14 11:35:13 -0700317
318 runtime·memclr((byte*)&sa, sizeof sa);
319 sa.sa_flags = SA_SIGINFO|SA_ONSTACK;
320 if(restart)
321 sa.sa_flags |= SA_RESTART;
322 sa.sa_mask[0] = ~0U;
323 sa.sa_mask[1] = ~0U;
324 sa.sa_mask[2] = ~0U;
325 sa.sa_mask[3] = ~0U;
326 if (fn == runtime·sighandler)
327 fn = (void*)runtime·sigtramp;
328 sa._sa_u._sa_sigaction = (void*)fn;
329 runtime·sigaction(i, &sa, nil);
330}
331
332GoSighandler*
333runtime·getsig(int32 i)
334{
Russ Cox9a75c742014-08-29 16:00:31 -0400335 SigactionT sa;
Russ Coxe9d62a62013-03-14 11:35:13 -0700336
337 runtime·memclr((byte*)&sa, sizeof sa);
338 runtime·sigaction(i, nil, &sa);
339 if((void*)sa._sa_u._sa_sigaction == runtime·sigtramp)
340 return runtime·sighandler;
341 return (void*)sa._sa_u._sa_sigaction;
342}
343
344void
345runtime·signalstack(byte *p, int32 n)
346{
347 StackT st;
348
349 st.ss_sp = (void*)p;
350 st.ss_size = n;
351 st.ss_flags = 0;
352 if(p == nil)
353 st.ss_flags = SS_DISABLE;
354 runtime·sigaltstack(&st, nil);
355}
Shenghou Ma0097d302013-12-19 20:45:05 -0500356
357void
358runtime·unblocksignals(void)
359{
360 runtime·sigprocmask(SIG_SETMASK, &sigset_none, nil);
361}
Russ Coxc81a0ed2014-09-08 14:05:23 -0400362
363#pragma textflag NOSPLIT
364int8*
365runtime·signame(int32 sig)
366{
367 return runtime·sigtab[sig].name;
368}