blob: a0fb5272f7c4073af60defc05d33461f13b5e919 [file] [log] [blame]
Rob Pikeaeb43982008-06-21 15:36:23 -07001// 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#include "runtime.h"
Russ Cox851f3012011-12-16 15:33:58 -05006#include "defs_GOOS_GOARCH.h"
7#include "os_GOOS.h"
Russ Cox820dc9f2011-02-24 13:46:44 -08008#include "stack.h"
Russ Coxd28acc42008-08-04 16:43:49 -07009
Russ Cox68b42552010-11-04 14:00:19 -040010extern SigTab runtime·sigtab[];
Russ Cox5963dba2010-04-08 18:15:30 -070011
Russ Cox224f05b2012-02-23 14:44:06 -050012static Sigset sigset_all = ~(Sigset)0;
13static Sigset sigset_none;
Russ Cox6e2ae0a2012-02-28 16:18:24 -050014static Sigset sigset_prof = 1<<(SIGPROF-1);
Russ Cox224f05b2012-02-23 14:44:06 -050015
Russ Coxd28acc42008-08-04 16:43:49 -070016static void
17unimplemented(int8 *name)
18{
Russ Cox68b42552010-11-04 14:00:19 -040019 runtime·prints(name);
20 runtime·prints(" not implemented\n");
Russ Coxd28acc42008-08-04 16:43:49 -070021 *(int32*)1231 = 1231;
22}
23
Russ Cox3b860262011-11-09 15:17:05 -050024int32
25runtime·semasleep(int64 ns)
Russ Coxd28acc42008-08-04 16:43:49 -070026{
Russ Cox6e2ae0a2012-02-28 16:18:24 -050027 int32 v;
28
29 if(m->profilehz > 0)
30 runtime·setprof(false);
31 v = runtime·mach_semacquire(m->waitsema, ns);
32 if(m->profilehz > 0)
33 runtime·setprof(true);
34 return v;
Russ Coxd28acc42008-08-04 16:43:49 -070035}
36
37void
Dmitriy Vyukovee24bfc2011-11-02 16:42:01 +030038runtime·semawakeup(M *mp)
Russ Coxd28acc42008-08-04 16:43:49 -070039{
Dmitriy Vyukovee24bfc2011-11-02 16:42:01 +030040 runtime·mach_semrelease(mp->waitsema);
Russ Coxd28acc42008-08-04 16:43:49 -070041}
42
Dmitriy Vyukovee24bfc2011-11-02 16:42:01 +030043uintptr
44runtime·semacreate(void)
Russ Cox62d627f2010-02-08 21:41:54 -080045{
Dmitriy Vyukovee24bfc2011-11-02 16:42:01 +030046 return runtime·mach_semcreate();
Russ Cox62d627f2010-02-08 21:41:54 -080047}
Russ Cox376898c2008-09-09 11:50:14 -070048
Russ Cox376898c2008-09-09 11:50:14 -070049// BSD interface for threading.
50void
Russ Cox68b42552010-11-04 14:00:19 -040051runtime·osinit(void)
Russ Cox376898c2008-09-09 11:50:14 -070052{
Shenghou Ma44fd1d12012-04-30 15:55:07 -040053 // bsdthread_register delayed until end of goenvs so that we
54 // can look at the environment first.
Russ Coxd324f212011-09-30 09:40:01 -040055
56 // Use sysctl to fetch hw.ncpu.
57 uint32 mib[2];
58 uint32 out;
59 int32 ret;
60 uintptr nout;
61
62 mib[0] = 6;
63 mib[1] = 3;
64 nout = sizeof out;
65 out = 0;
66 ret = runtime·sysctl(mib, 2, (byte*)&out, &nout, nil, 0);
67 if(ret >= 0)
68 runtime·ncpu = out;
Russ Coxd28acc42008-08-04 16:43:49 -070069}
70
71void
Alex Brainmana41d8542011-01-12 11:48:15 +110072runtime·goenvs(void)
73{
74 runtime·goenvs_unix();
Shenghou Ma44fd1d12012-04-30 15:55:07 -040075
76 // Register our thread-creation callback (see sys_darwin_{amd64,386}.s)
77 // but only if we're not using cgo. If we are using cgo we need
78 // to let the C pthread libary install its own thread-creation callback.
79 if(!runtime·iscgo) {
80 if(runtime·bsdthread_register() != 0) {
81 if(runtime·getenv("DYLD_INSERT_LIBRARIES"))
82 runtime·throw("runtime: bsdthread_register error (unset DYLD_INSERT_LIBRARIES)");
83 runtime·throw("runtime: bsdthread_register error");
84 }
85 }
86
Alex Brainmana41d8542011-01-12 11:48:15 +110087}
88
89void
Russ Cox68b42552010-11-04 14:00:19 -040090runtime·newosproc(M *m, G *g, void *stk, void (*fn)(void))
Russ Coxd28acc42008-08-04 16:43:49 -070091{
Russ Cox4608feb2011-01-28 15:03:26 -050092 int32 errno;
Russ Cox224f05b2012-02-23 14:44:06 -050093 Sigset oset;
Russ Cox4608feb2011-01-28 15:03:26 -050094
Russ Cox3a0df4c2009-06-04 11:16:03 -070095 m->tls[0] = m->id; // so 386 asm can find it
Russ Cox8522a472009-06-17 15:15:55 -070096 if(0){
Russ Cox68b42552010-11-04 14:00:19 -040097 runtime·printf("newosproc stk=%p m=%p g=%p fn=%p id=%d/%d ostk=%p\n",
Russ Cox8522a472009-06-17 15:15:55 -070098 stk, m, g, fn, m->id, m->tls[0], &m);
99 }
Russ Cox224f05b2012-02-23 14:44:06 -0500100
101 runtime·sigprocmask(SIG_SETMASK, &sigset_all, &oset);
102 errno = runtime·bsdthread_create(stk, m, g, fn);
103 runtime·sigprocmask(SIG_SETMASK, &oset, nil);
Russ Cox6e2ae0a2012-02-28 16:18:24 -0500104
Russ Cox224f05b2012-02-23 14:44:06 -0500105 if(errno < 0) {
Russ Cox4608feb2011-01-28 15:03:26 -0500106 runtime·printf("runtime: failed to create new OS thread (have %d already; errno=%d)\n", runtime·mcount(), -errno);
107 runtime·throw("runtime.newosproc");
108 }
Russ Coxd28acc42008-08-04 16:43:49 -0700109}
110
Russ Coxa67258f2008-09-18 15:56:46 -0700111// Called to initialize a new m (including the bootstrap m).
112void
Russ Cox68b42552010-11-04 14:00:19 -0400113runtime·minit(void)
Russ Coxa67258f2008-09-18 15:56:46 -0700114{
115 // Initialize signal handling.
Russ Cox68b42552010-11-04 14:00:19 -0400116 m->gsignal = runtime·malg(32*1024); // OS X wants >=8K, Linux >=2K
Russ Cox820dc9f2011-02-24 13:46:44 -0800117 runtime·signalstack(m->gsignal->stackguard - StackGuard, 32*1024);
Russ Cox6e2ae0a2012-02-28 16:18:24 -0500118
119 if(m->profilehz > 0)
120 runtime·sigprocmask(SIG_SETMASK, &sigset_none, nil);
121 else
122 runtime·sigprocmask(SIG_SETMASK, &sigset_prof, nil);
Russ Coxa67258f2008-09-18 15:56:46 -0700123}
124
Russ Cox376898c2008-09-09 11:50:14 -0700125// Mach IPC, to get at semaphores
126// Definitions are in /usr/include/mach on a Mac.
127
128static void
Russ Cox08cfcd12009-03-24 13:51:48 -0700129macherror(int32 r, int8 *fn)
Russ Coxd28acc42008-08-04 16:43:49 -0700130{
Russ Cox68b42552010-11-04 14:00:19 -0400131 runtime·printf("mach error %s: %d\n", fn, r);
132 runtime·throw("mach error");
Russ Cox376898c2008-09-09 11:50:14 -0700133}
134
135enum
136{
137 DebugMach = 0
138};
139
Russ Cox08cfcd12009-03-24 13:51:48 -0700140static MachNDR zerondr;
Russ Cox376898c2008-09-09 11:50:14 -0700141
142#define MACH_MSGH_BITS(a, b) ((a) | ((b)<<8))
143
Russ Cox08cfcd12009-03-24 13:51:48 -0700144static int32
145mach_msg(MachHeader *h,
146 int32 op,
147 uint32 send_size,
148 uint32 rcv_size,
149 uint32 rcv_name,
150 uint32 timeout,
151 uint32 notify)
Russ Cox376898c2008-09-09 11:50:14 -0700152{
153 // TODO: Loop on interrupt.
Russ Cox68b42552010-11-04 14:00:19 -0400154 return runtime·mach_msg_trap(h, op, send_size, rcv_size, rcv_name, timeout, notify);
Russ Cox376898c2008-09-09 11:50:14 -0700155}
156
Russ Cox376898c2008-09-09 11:50:14 -0700157// Mach RPC (MIG)
Russ Cox376898c2008-09-09 11:50:14 -0700158
159enum
160{
161 MinMachMsg = 48,
162 Reply = 100,
163};
164
165#pragma pack on
166typedef struct CodeMsg CodeMsg;
167struct CodeMsg
168{
Russ Cox08cfcd12009-03-24 13:51:48 -0700169 MachHeader h;
170 MachNDR NDR;
171 int32 code;
Russ Cox376898c2008-09-09 11:50:14 -0700172};
173#pragma pack off
174
Russ Cox08cfcd12009-03-24 13:51:48 -0700175static int32
176machcall(MachHeader *h, int32 maxsize, int32 rxsize)
Russ Cox376898c2008-09-09 11:50:14 -0700177{
178 uint32 *p;
179 int32 i, ret, id;
Russ Cox08cfcd12009-03-24 13:51:48 -0700180 uint32 port;
Russ Cox376898c2008-09-09 11:50:14 -0700181 CodeMsg *c;
182
183 if((port = m->machport) == 0){
Russ Cox68b42552010-11-04 14:00:19 -0400184 port = runtime·mach_reply_port();
Russ Cox376898c2008-09-09 11:50:14 -0700185 m->machport = port;
186 }
187
Russ Cox08cfcd12009-03-24 13:51:48 -0700188 h->msgh_bits |= MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND_ONCE);
189 h->msgh_local_port = port;
190 h->msgh_reserved = 0;
191 id = h->msgh_id;
Russ Cox376898c2008-09-09 11:50:14 -0700192
193 if(DebugMach){
194 p = (uint32*)h;
Russ Cox68b42552010-11-04 14:00:19 -0400195 runtime·prints("send:\t");
Russ Cox08cfcd12009-03-24 13:51:48 -0700196 for(i=0; i<h->msgh_size/sizeof(p[0]); i++){
Russ Cox68b42552010-11-04 14:00:19 -0400197 runtime·prints(" ");
198 runtime·printpointer((void*)p[i]);
Russ Cox376898c2008-09-09 11:50:14 -0700199 if(i%8 == 7)
Russ Cox68b42552010-11-04 14:00:19 -0400200 runtime·prints("\n\t");
Russ Cox376898c2008-09-09 11:50:14 -0700201 }
202 if(i%8)
Russ Cox68b42552010-11-04 14:00:19 -0400203 runtime·prints("\n");
Russ Cox376898c2008-09-09 11:50:14 -0700204 }
205
206 ret = mach_msg(h, MACH_SEND_MSG|MACH_RCV_MSG,
Russ Cox08cfcd12009-03-24 13:51:48 -0700207 h->msgh_size, maxsize, port, 0, 0);
Russ Cox376898c2008-09-09 11:50:14 -0700208 if(ret != 0){
209 if(DebugMach){
Russ Cox68b42552010-11-04 14:00:19 -0400210 runtime·prints("mach_msg error ");
211 runtime·printint(ret);
212 runtime·prints("\n");
Russ Cox376898c2008-09-09 11:50:14 -0700213 }
214 return ret;
215 }
216
217 if(DebugMach){
218 p = (uint32*)h;
Russ Cox68b42552010-11-04 14:00:19 -0400219 runtime·prints("recv:\t");
Russ Cox08cfcd12009-03-24 13:51:48 -0700220 for(i=0; i<h->msgh_size/sizeof(p[0]); i++){
Russ Cox68b42552010-11-04 14:00:19 -0400221 runtime·prints(" ");
222 runtime·printpointer((void*)p[i]);
Russ Cox376898c2008-09-09 11:50:14 -0700223 if(i%8 == 7)
Russ Cox68b42552010-11-04 14:00:19 -0400224 runtime·prints("\n\t");
Russ Cox376898c2008-09-09 11:50:14 -0700225 }
226 if(i%8)
Russ Cox68b42552010-11-04 14:00:19 -0400227 runtime·prints("\n");
Russ Cox376898c2008-09-09 11:50:14 -0700228 }
229
Russ Cox08cfcd12009-03-24 13:51:48 -0700230 if(h->msgh_id != id+Reply){
Russ Cox376898c2008-09-09 11:50:14 -0700231 if(DebugMach){
Russ Cox68b42552010-11-04 14:00:19 -0400232 runtime·prints("mach_msg reply id mismatch ");
233 runtime·printint(h->msgh_id);
234 runtime·prints(" != ");
235 runtime·printint(id+Reply);
236 runtime·prints("\n");
Russ Cox376898c2008-09-09 11:50:14 -0700237 }
238 return -303; // MIG_REPLY_MISMATCH
239 }
240
241 // Look for a response giving the return value.
242 // Any call can send this back with an error,
243 // and some calls only have return values so they
244 // send it back on success too. I don't quite see how
245 // you know it's one of these and not the full response
246 // format, so just look if the message is right.
247 c = (CodeMsg*)h;
Russ Cox08cfcd12009-03-24 13:51:48 -0700248 if(h->msgh_size == sizeof(CodeMsg)
249 && !(h->msgh_bits & MACH_MSGH_BITS_COMPLEX)){
Russ Cox376898c2008-09-09 11:50:14 -0700250 if(DebugMach){
Russ Cox68b42552010-11-04 14:00:19 -0400251 runtime·prints("mig result ");
252 runtime·printint(c->code);
253 runtime·prints("\n");
Russ Cox376898c2008-09-09 11:50:14 -0700254 }
255 return c->code;
256 }
257
Russ Cox08cfcd12009-03-24 13:51:48 -0700258 if(h->msgh_size != rxsize){
Russ Cox376898c2008-09-09 11:50:14 -0700259 if(DebugMach){
Russ Cox68b42552010-11-04 14:00:19 -0400260 runtime·prints("mach_msg reply size mismatch ");
261 runtime·printint(h->msgh_size);
262 runtime·prints(" != ");
263 runtime·printint(rxsize);
264 runtime·prints("\n");
Russ Cox376898c2008-09-09 11:50:14 -0700265 }
266 return -307; // MIG_ARRAY_TOO_LARGE
267 }
268
Russ Coxd28acc42008-08-04 16:43:49 -0700269 return 0;
270}
Russ Cox376898c2008-09-09 11:50:14 -0700271
272
273// Semaphores!
274
275enum
276{
Russ Cox1f8a40d2009-01-22 16:23:44 -0800277 Tmach_semcreate = 3418,
278 Rmach_semcreate = Tmach_semcreate + Reply,
Russ Cox376898c2008-09-09 11:50:14 -0700279
Russ Cox1f8a40d2009-01-22 16:23:44 -0800280 Tmach_semdestroy = 3419,
281 Rmach_semdestroy = Tmach_semdestroy + Reply,
Russ Coxcd800002009-06-08 14:03:21 -0700282
Russ Cox925183c2009-06-08 14:09:04 -0700283 // Mach calls that get interrupted by Unix signals
284 // return this error code. We retry them.
Russ Coxcd800002009-06-08 14:03:21 -0700285 KERN_ABORTED = 14,
Russ Cox3b860262011-11-09 15:17:05 -0500286 KERN_OPERATION_TIMED_OUT = 49,
Russ Cox376898c2008-09-09 11:50:14 -0700287};
288
Russ Cox1f8a40d2009-01-22 16:23:44 -0800289typedef struct Tmach_semcreateMsg Tmach_semcreateMsg;
290typedef struct Rmach_semcreateMsg Rmach_semcreateMsg;
291typedef struct Tmach_semdestroyMsg Tmach_semdestroyMsg;
292// Rmach_semdestroyMsg = CodeMsg
Russ Cox376898c2008-09-09 11:50:14 -0700293
294#pragma pack on
Russ Cox1f8a40d2009-01-22 16:23:44 -0800295struct Tmach_semcreateMsg
Russ Cox376898c2008-09-09 11:50:14 -0700296{
Russ Cox08cfcd12009-03-24 13:51:48 -0700297 MachHeader h;
298 MachNDR ndr;
Russ Cox376898c2008-09-09 11:50:14 -0700299 int32 policy;
300 int32 value;
301};
302
Russ Cox1f8a40d2009-01-22 16:23:44 -0800303struct Rmach_semcreateMsg
Russ Cox376898c2008-09-09 11:50:14 -0700304{
Russ Cox08cfcd12009-03-24 13:51:48 -0700305 MachHeader h;
306 MachBody body;
307 MachPort semaphore;
Russ Cox376898c2008-09-09 11:50:14 -0700308};
309
Russ Cox1f8a40d2009-01-22 16:23:44 -0800310struct Tmach_semdestroyMsg
Russ Cox376898c2008-09-09 11:50:14 -0700311{
Russ Cox08cfcd12009-03-24 13:51:48 -0700312 MachHeader h;
313 MachBody body;
314 MachPort semaphore;
Russ Cox376898c2008-09-09 11:50:14 -0700315};
316#pragma pack off
317
Russ Cox08cfcd12009-03-24 13:51:48 -0700318uint32
Russ Cox68b42552010-11-04 14:00:19 -0400319runtime·mach_semcreate(void)
Russ Cox376898c2008-09-09 11:50:14 -0700320{
321 union {
Russ Cox1f8a40d2009-01-22 16:23:44 -0800322 Tmach_semcreateMsg tx;
323 Rmach_semcreateMsg rx;
Russ Cox376898c2008-09-09 11:50:14 -0700324 uint8 pad[MinMachMsg];
325 } m;
Russ Cox08cfcd12009-03-24 13:51:48 -0700326 int32 r;
Russ Cox376898c2008-09-09 11:50:14 -0700327
Russ Cox08cfcd12009-03-24 13:51:48 -0700328 m.tx.h.msgh_bits = 0;
329 m.tx.h.msgh_size = sizeof(m.tx);
Russ Cox68b42552010-11-04 14:00:19 -0400330 m.tx.h.msgh_remote_port = runtime·mach_task_self();
Russ Cox08cfcd12009-03-24 13:51:48 -0700331 m.tx.h.msgh_id = Tmach_semcreate;
Russ Cox376898c2008-09-09 11:50:14 -0700332 m.tx.ndr = zerondr;
333
334 m.tx.policy = 0; // 0 = SYNC_POLICY_FIFO
335 m.tx.value = 0;
336
Russ Coxcd800002009-06-08 14:03:21 -0700337 while((r = machcall(&m.tx.h, sizeof m, sizeof(m.rx))) != 0){
338 if(r == KERN_ABORTED) // interrupted
339 continue;
Russ Cox376898c2008-09-09 11:50:14 -0700340 macherror(r, "semaphore_create");
Russ Coxcd800002009-06-08 14:03:21 -0700341 }
Russ Cox08cfcd12009-03-24 13:51:48 -0700342 if(m.rx.body.msgh_descriptor_count != 1)
Russ Cox1f8a40d2009-01-22 16:23:44 -0800343 unimplemented("mach_semcreate desc count");
Russ Cox376898c2008-09-09 11:50:14 -0700344 return m.rx.semaphore.name;
345}
346
347void
Russ Cox68b42552010-11-04 14:00:19 -0400348runtime·mach_semdestroy(uint32 sem)
Russ Cox376898c2008-09-09 11:50:14 -0700349{
350 union {
Russ Cox1f8a40d2009-01-22 16:23:44 -0800351 Tmach_semdestroyMsg tx;
Russ Cox376898c2008-09-09 11:50:14 -0700352 uint8 pad[MinMachMsg];
353 } m;
Russ Cox08cfcd12009-03-24 13:51:48 -0700354 int32 r;
Russ Cox376898c2008-09-09 11:50:14 -0700355
Russ Cox08cfcd12009-03-24 13:51:48 -0700356 m.tx.h.msgh_bits = MACH_MSGH_BITS_COMPLEX;
357 m.tx.h.msgh_size = sizeof(m.tx);
Russ Cox68b42552010-11-04 14:00:19 -0400358 m.tx.h.msgh_remote_port = runtime·mach_task_self();
Russ Cox08cfcd12009-03-24 13:51:48 -0700359 m.tx.h.msgh_id = Tmach_semdestroy;
360 m.tx.body.msgh_descriptor_count = 1;
Russ Cox376898c2008-09-09 11:50:14 -0700361 m.tx.semaphore.name = sem;
362 m.tx.semaphore.disposition = MACH_MSG_TYPE_MOVE_SEND;
363 m.tx.semaphore.type = 0;
364
Russ Coxcd800002009-06-08 14:03:21 -0700365 while((r = machcall(&m.tx.h, sizeof m, 0)) != 0){
Russ Cox3ff5e722009-07-27 10:59:59 -0700366 if(r == KERN_ABORTED) // interrupted
367 continue;
Russ Cox376898c2008-09-09 11:50:14 -0700368 macherror(r, "semaphore_destroy");
Russ Coxcd800002009-06-08 14:03:21 -0700369 }
Russ Cox376898c2008-09-09 11:50:14 -0700370}
371
Shenghou Mae0213572012-01-22 10:34:17 -0800372// The other calls have simple system call traps in sys_darwin_{amd64,386}.s
Russ Cox68b42552010-11-04 14:00:19 -0400373int32 runtime·mach_semaphore_wait(uint32 sema);
374int32 runtime·mach_semaphore_timedwait(uint32 sema, uint32 sec, uint32 nsec);
375int32 runtime·mach_semaphore_signal(uint32 sema);
376int32 runtime·mach_semaphore_signal_all(uint32 sema);
Russ Cox376898c2008-09-09 11:50:14 -0700377
Russ Cox3b860262011-11-09 15:17:05 -0500378int32
379runtime·mach_semacquire(uint32 sem, int64 ns)
Russ Cox376898c2008-09-09 11:50:14 -0700380{
Russ Cox08cfcd12009-03-24 13:51:48 -0700381 int32 r;
Russ Cox376898c2008-09-09 11:50:14 -0700382
Russ Cox3b860262011-11-09 15:17:05 -0500383 if(ns >= 0) {
384 r = runtime·mach_semaphore_timedwait(sem, ns/1000000000LL, ns%1000000000LL);
385 if(r == KERN_ABORTED || r == KERN_OPERATION_TIMED_OUT)
386 return -1;
387 if(r != 0)
388 macherror(r, "semaphore_wait");
389 return 0;
390 }
Russ Cox68b42552010-11-04 14:00:19 -0400391 while((r = runtime·mach_semaphore_wait(sem)) != 0) {
Russ Coxcd800002009-06-08 14:03:21 -0700392 if(r == KERN_ABORTED) // interrupted
393 continue;
Russ Cox376898c2008-09-09 11:50:14 -0700394 macherror(r, "semaphore_wait");
Russ Coxcd800002009-06-08 14:03:21 -0700395 }
Russ Cox3b860262011-11-09 15:17:05 -0500396 return 0;
Russ Cox376898c2008-09-09 11:50:14 -0700397}
398
399void
Russ Cox68b42552010-11-04 14:00:19 -0400400runtime·mach_semrelease(uint32 sem)
Russ Cox376898c2008-09-09 11:50:14 -0700401{
Russ Cox08cfcd12009-03-24 13:51:48 -0700402 int32 r;
Russ Cox376898c2008-09-09 11:50:14 -0700403
Russ Cox68b42552010-11-04 14:00:19 -0400404 while((r = runtime·mach_semaphore_signal(sem)) != 0) {
Russ Coxcd800002009-06-08 14:03:21 -0700405 if(r == KERN_ABORTED) // interrupted
406 continue;
Russ Cox376898c2008-09-09 11:50:14 -0700407 macherror(r, "semaphore_signal");
Russ Coxcd800002009-06-08 14:03:21 -0700408 }
Russ Cox376898c2008-09-09 11:50:14 -0700409}
410
Russ Cox5963dba2010-04-08 18:15:30 -0700411void
Russ Cox68b42552010-11-04 14:00:19 -0400412runtime·sigpanic(void)
Russ Cox5963dba2010-04-08 18:15:30 -0700413{
414 switch(g->sig) {
415 case SIGBUS:
Russ Cox5032a7d2012-01-10 11:46:57 -0800416 if(g->sigcode0 == BUS_ADRERR && g->sigcode1 < 0x1000) {
417 if(g->sigpc == 0)
418 runtime·panicstring("call of nil func value");
Russ Cox68b42552010-11-04 14:00:19 -0400419 runtime·panicstring("invalid memory address or nil pointer dereference");
Russ Cox5032a7d2012-01-10 11:46:57 -0800420 }
Russ Cox68b42552010-11-04 14:00:19 -0400421 runtime·printf("unexpected fault address %p\n", g->sigcode1);
422 runtime·throw("fault");
Russ Cox5963dba2010-04-08 18:15:30 -0700423 case SIGSEGV:
Russ Cox5032a7d2012-01-10 11:46:57 -0800424 if((g->sigcode0 == 0 || g->sigcode0 == SEGV_MAPERR || g->sigcode0 == SEGV_ACCERR) && g->sigcode1 < 0x1000) {
425 if(g->sigpc == 0)
426 runtime·panicstring("call of nil func value");
Russ Cox68b42552010-11-04 14:00:19 -0400427 runtime·panicstring("invalid memory address or nil pointer dereference");
Russ Cox5032a7d2012-01-10 11:46:57 -0800428 }
Russ Cox68b42552010-11-04 14:00:19 -0400429 runtime·printf("unexpected fault address %p\n", g->sigcode1);
430 runtime·throw("fault");
Russ Cox5963dba2010-04-08 18:15:30 -0700431 case SIGFPE:
432 switch(g->sigcode0) {
433 case FPE_INTDIV:
Russ Cox68b42552010-11-04 14:00:19 -0400434 runtime·panicstring("integer divide by zero");
Russ Cox5963dba2010-04-08 18:15:30 -0700435 case FPE_INTOVF:
Russ Cox68b42552010-11-04 14:00:19 -0400436 runtime·panicstring("integer overflow");
Russ Cox5963dba2010-04-08 18:15:30 -0700437 }
Russ Cox68b42552010-11-04 14:00:19 -0400438 runtime·panicstring("floating point error");
Russ Cox5963dba2010-04-08 18:15:30 -0700439 }
Russ Cox68b42552010-11-04 14:00:19 -0400440 runtime·panicstring(runtime·sigtab[g->sig].name);
Russ Cox5963dba2010-04-08 18:15:30 -0700441}
Rob Pike40c26ff2011-09-30 10:52:36 -0700442
443// TODO(rsc): place holder to fix build.
444void
445runtime·osyield(void)
446{
447}
Russ Cox102274a2012-02-24 15:28:51 -0500448
449uintptr
450runtime·memlimit(void)
451{
452 // NOTE(rsc): Could use getrlimit here,
453 // like on FreeBSD or Linux, but Darwin doesn't enforce
454 // ulimit -v, so it's unclear why we'd try to stay within
455 // the limit.
456 return 0;
457}
Russ Cox6e2ae0a2012-02-28 16:18:24 -0500458
459// NOTE(rsc): On OS X, when the CPU profiling timer expires, the SIGPROF
460// signal is not guaranteed to be sent to the thread that was executing to
461// cause it to expire. It can and often does go to a sleeping thread, which is
462// not interesting for our profile. This is filed Apple Bug Report #9177434,
463// copied to http://code.google.com/p/go/source/detail?r=35b716c94225.
464// To work around this bug, we disable receipt of the profiling signal on
465// a thread while in blocking system calls. This forces the kernel to deliver
466// the profiling signal to an executing thread.
467//
468// The workaround fails on OS X machines using a 64-bit Snow Leopard kernel.
469// In that configuration, the kernel appears to want to deliver SIGPROF to the
470// sleeping threads regardless of signal mask and, worse, does not deliver
471// the signal until the thread wakes up on its own.
472//
473// If necessary, we can switch to using ITIMER_REAL for OS X and handle
474// the kernel-generated SIGALRM by generating our own SIGALRMs to deliver
475// to all the running threads. SIGALRM does not appear to be affected by
476// the 64-bit Snow Leopard bug. However, as of this writing Mountain Lion
477// is in preview, making Snow Leopard two versions old, so it is unclear how
478// much effort we need to spend on one buggy kernel.
479
480// Control whether profiling signal can be delivered to this thread.
481void
482runtime·setprof(bool on)
483{
484 if(on)
485 runtime·sigprocmask(SIG_UNBLOCK, &sigset_prof, nil);
486 else
487 runtime·sigprocmask(SIG_BLOCK, &sigset_prof, nil);
488}
Russ Cox9b732382012-03-08 12:12:40 -0500489
490static int8 badcallback[] = "runtime: cgo callback on thread not created by Go.\n";
491
492// This runs on a foreign stack, without an m or a g. No stack split.
493#pragma textflag 7
494void
495runtime·badcallback(void)
496{
497 runtime·write(2, badcallback, sizeof badcallback - 1);
498}
Russ Coxb2369112012-03-12 15:55:18 -0400499
500static int8 badsignal[] = "runtime: signal received on thread not created by Go.\n";
501
502// This runs on a foreign stack, without an m or a g. No stack split.
503#pragma textflag 7
504void
505runtime·badsignal(void)
506{
507 runtime·write(2, badsignal, sizeof badsignal - 1);
508}