1
// 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.
6
#include "defs_GOOS_GOARCH.h"
8
#include "signal_unix.h"
10
#include "../../cmd/ld/textflag.h"
17
// From NetBSD's <sys/time.h>
24
extern SigTab runtime·sigtab[];
26
static Sigset sigset_none;
27
static Sigset sigset_all = { ~(uint32)0, ~(uint32)0, ~(uint32)0, ~(uint32)0, };
29
extern void runtime·getcontext(UcontextT *context);
30
extern int32 runtime·lwp_create(UcontextT *context, uintptr flags, void *lwpid);
31
extern void runtime·lwp_mcontext_init(void *mc, void *stack, M *mp, G *gp, void (*fn)(void));
32
extern int32 runtime·lwp_park(Timespec *abstime, int32 unpark, void *hint, void *unparkhint);
33
extern int32 runtime·lwp_unpark(int32 lwp, void *hint);
34
extern int32 runtime·lwp_self(void);
36
// From NetBSD's <sys/sysctl.h>
48
// Fetch hw.ncpu via sysctl.
53
ret = runtime·sysctl(mib, 2, (byte*)&out, &nout, nil, 0);
61
runtime·semacreate(void)
66
#pragma textflag NOSPLIT
68
runtime·semasleep(int64 ns)
73
while(runtime·xchg(&m->waitsemalock, 1))
78
if(m->waitsemacount == 0) {
79
// sleep until semaphore != 0 or timeout.
80
// thrsleep unlocks m->waitsemalock.
82
// TODO(jsing) - potential deadlock!
84
// There is a potential deadlock here since we
85
// have to release the waitsemalock mutex
86
// before we call lwp_park() to suspend the
87
// thread. This allows another thread to
88
// release the lock and call lwp_unpark()
89
// before the thread is actually suspended.
90
// If this occurs the current thread will end
91
// up sleeping indefinitely. Unfortunately
92
// the NetBSD kernel does not appear to provide
93
// a mechanism for unlocking the userspace
94
// mutex once the thread is actually parked.
95
runtime·atomicstore(&m->waitsemalock, 0);
96
runtime·lwp_park(nil, 0, &m->waitsemacount, nil);
98
ns = ns + runtime·nanotime();
99
// NOTE: tv_nsec is int64 on amd64, so this assumes a little-endian system.
101
ts.tv_sec = runtime·timediv(ns, 1000000000, (int32*)&ts.tv_nsec);
102
// TODO(jsing) - potential deadlock!
103
// See above for details.
104
runtime·atomicstore(&m->waitsemalock, 0);
105
runtime·lwp_park(&ts, 0, &m->waitsemacount, nil);
108
while(runtime·xchg(&m->waitsemalock, 1))
113
if(m->waitsemacount != 0) {
114
// semaphore is available.
117
runtime·atomicstore(&m->waitsemalock, 0);
118
return 0; // semaphore acquired
121
// semaphore not available.
122
// if there is a timeout, stop now.
123
// otherwise keep trying.
128
// lock held but giving up
130
runtime·atomicstore(&m->waitsemalock, 0);
135
runtime·semawakeup(M *mp)
140
while(runtime·xchg(&mp->waitsemalock, 1))
143
// TODO(jsing) - potential deadlock, see semasleep() for details.
144
// Confirm that LWP is parked before unparking...
145
ret = runtime·lwp_unpark(mp->procid, &mp->waitsemacount);
146
if(ret != 0 && ret != ESRCH)
147
runtime·printf("thrwakeup addr=%p sem=%d ret=%d\n", &mp->waitsemacount, mp->waitsemacount, ret);
149
runtime·atomicstore(&mp->waitsemalock, 0);
153
runtime·newosproc(M *mp, void *stk)
160
"newosproc stk=%p m=%p g=%p id=%d/%d ostk=%p\n",
161
stk, mp, mp->g0, mp->id, (int32)mp->tls[0], &mp);
164
mp->tls[0] = mp->id; // so 386 asm can find it
166
runtime·getcontext(&uc);
168
uc.uc_flags = _UC_SIGMASK | _UC_CPU;
170
uc.uc_sigmask = sigset_all;
172
runtime·lwp_mcontext_init(&uc.uc_mcontext, stk, mp, mp->g0, runtime·mstart);
174
ret = runtime·lwp_create(&uc, 0, &mp->procid);
177
runtime·printf("runtime: failed to create new OS thread (have %d already; errno=%d)\n", runtime·mcount() - 1, -ret);
178
runtime·throw("runtime.newosproc");
185
runtime·ncpu = getncpu();
189
runtime·get_random_data(byte **rnd, int32 *rnd_len)
191
static byte urandom_data[HashRandomBytes];
193
fd = runtime·open("/dev/urandom", 0 /* O_RDONLY */, 0);
194
if(runtime·read(fd, urandom_data, HashRandomBytes) == HashRandomBytes) {
196
*rnd_len = HashRandomBytes;
207
runtime·goenvs_unix();
210
// Called to initialize a new m (including the bootstrap m).
211
// Called on the parent thread (main thread in case of bootstrap), can allocate memory.
213
runtime·mpreinit(M *mp)
215
mp->gsignal = runtime·malg(32*1024);
218
// Called to initialize a new m (including the bootstrap m).
219
// Called on the new thread, can not allocate memory.
223
m->procid = runtime·lwp_self();
225
// Initialize signal handling
226
runtime·signalstack((byte*)m->gsignal->stackguard - StackGuard, 32*1024);
227
runtime·sigprocmask(SIG_SETMASK, &sigset_none, nil);
230
// Called from dropm to undo the effect of an minit.
232
runtime·unminit(void)
234
runtime·signalstack(nil, 0);
238
runtime·sigpanic(void)
242
if(g->sigcode0 == BUS_ADRERR && g->sigcode1 < 0x1000) {
244
runtime·panicstring("call of nil func value");
245
runtime·panicstring("invalid memory address or nil pointer dereference");
247
runtime·printf("unexpected fault address %p\n", g->sigcode1);
248
runtime·throw("fault");
250
if((g->sigcode0 == 0 || g->sigcode0 == SEGV_MAPERR || g->sigcode0 == SEGV_ACCERR) && g->sigcode1 < 0x1000) {
252
runtime·panicstring("call of nil func value");
253
runtime·panicstring("invalid memory address or nil pointer dereference");
255
runtime·printf("unexpected fault address %p\n", g->sigcode1);
256
runtime·throw("fault");
258
switch(g->sigcode0) {
260
runtime·panicstring("integer divide by zero");
262
runtime·panicstring("integer overflow");
264
runtime·panicstring("floating point error");
266
runtime·panicstring(runtime·sigtab[g->sig].name);
270
runtime·memlimit(void)
275
extern void runtime·sigtramp(void);
277
typedef struct sigaction {
279
void (*_sa_handler)(int32);
280
void (*_sa_sigaction)(int32, Siginfo*, void *);
281
} _sa_u; /* signal handler */
282
uint32 sa_mask[4]; /* signal mask to apply */
283
int32 sa_flags; /* see signal options below */
287
runtime·setsig(int32 i, GoSighandler *fn, bool restart)
291
runtime·memclr((byte*)&sa, sizeof sa);
292
sa.sa_flags = SA_SIGINFO|SA_ONSTACK;
294
sa.sa_flags |= SA_RESTART;
299
if (fn == runtime·sighandler)
300
fn = (void*)runtime·sigtramp;
301
sa._sa_u._sa_sigaction = (void*)fn;
302
runtime·sigaction(i, &sa, nil);
306
runtime·getsig(int32 i)
310
runtime·memclr((byte*)&sa, sizeof sa);
311
runtime·sigaction(i, nil, &sa);
312
if((void*)sa._sa_u._sa_sigaction == runtime·sigtramp)
313
return runtime·sighandler;
314
return (void*)sa._sa_u._sa_sigaction;
318
runtime·signalstack(byte *p, int32 n)
326
st.ss_flags = SS_DISABLE;
327
runtime·sigaltstack(&st, nil);