OLD | NEW |
1 // Copyright 2011 The Go Authors. All rights reserved. | 1 // Copyright 2011 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 "defs_GOOS_GOARCH.h" | 6 #include "defs_GOOS_GOARCH.h" |
7 #include "os_GOOS.h" | 7 #include "os_GOOS.h" |
8 #include "signal_unix.h" | 8 #include "signal_unix.h" |
9 #include "stack.h" | 9 #include "stack.h" |
10 #include "textflag.h" | 10 #include "textflag.h" |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
114 runtime·ncpu = getncpu();· | 114 runtime·ncpu = getncpu();· |
115 } | 115 } |
116 | 116 |
117 void | 117 void |
118 runtime·newosproc(M *mp, void *stk) | 118 runtime·newosproc(M *mp, void *stk) |
119 { | 119 { |
120 PthreadAttr attr; | 120 PthreadAttr attr; |
121 Sigset oset; | 121 Sigset oset; |
122 Pthread tid; | 122 Pthread tid; |
123 int32 ret; | 123 int32 ret; |
| 124 uint64 size; |
124 | 125 |
125 USED(stk); | 126 USED(stk); |
126 if(runtime·pthread_attr_init(&attr) != 0) | 127 if(runtime·pthread_attr_init(&attr) != 0) |
127 runtime·throw("pthread_attr_init"); | 128 runtime·throw("pthread_attr_init"); |
128 if(runtime·pthread_attr_setstack(&attr, 0, 0x200000) != 0) | 129 if(runtime·pthread_attr_setstack(&attr, 0, 0x200000) != 0) |
129 runtime·throw("pthread_attr_setstack"); | 130 runtime·throw("pthread_attr_setstack"); |
130 » if(runtime·pthread_attr_getstack(&attr, (void**)&mp->g0->stackbase, &mp-
>g0->stacksize) != 0) | 131 » size = 0; |
| 132 » if(runtime·pthread_attr_getstack(&attr, (void**)&mp->g0->stack.hi, &size
) != 0) |
131 runtime·throw("pthread_attr_getstack");· | 133 runtime·throw("pthread_attr_getstack");· |
| 134 mp->g0->stack.lo = mp->g0->stack.hi - size; |
132 if(runtime·pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) !
= 0) | 135 if(runtime·pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) !
= 0) |
133 runtime·throw("pthread_attr_setdetachstate"); | 136 runtime·throw("pthread_attr_setdetachstate"); |
134 | 137 |
135 // Disable signals during create, so that the new thread starts | 138 // Disable signals during create, so that the new thread starts |
136 // with signals disabled. It will enable them in minit. | 139 // with signals disabled. It will enable them in minit. |
137 runtime·sigprocmask(SIG_SETMASK, &sigset_all, &oset); | 140 runtime·sigprocmask(SIG_SETMASK, &sigset_all, &oset); |
138 ret = runtime·pthread_create(&tid, &attr, (void (*)(void))runtime·tstart
_sysvicall, mp); | 141 ret = runtime·pthread_create(&tid, &attr, (void (*)(void))runtime·tstart
_sysvicall, mp); |
139 runtime·sigprocmask(SIG_SETMASK, &oset, nil); | 142 runtime·sigprocmask(SIG_SETMASK, &oset, nil); |
140 if(ret != 0) { | 143 if(ret != 0) { |
141 runtime·printf("runtime: failed to create new OS thread (have %d
already; errno=%d)\n", runtime·mcount(), ret); | 144 runtime·printf("runtime: failed to create new OS thread (have %d
already; errno=%d)\n", runtime·mcount(), ret); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
176 mp->gsignal->m = mp; | 179 mp->gsignal->m = mp; |
177 } | 180 } |
178 | 181 |
179 // Called to initialize a new m (including the bootstrap m). | 182 // Called to initialize a new m (including the bootstrap m). |
180 // Called on the new thread, can not allocate memory. | 183 // Called on the new thread, can not allocate memory. |
181 void | 184 void |
182 runtime·minit(void) | 185 runtime·minit(void) |
183 { | 186 { |
184 runtime·asmcgocall(runtime·miniterrno, (void *)libc·___errno); | 187 runtime·asmcgocall(runtime·miniterrno, (void *)libc·___errno); |
185 // Initialize signal handling | 188 // Initialize signal handling |
186 » runtime·signalstack((byte*)g->m->gsignal->stackguard - StackGuard, 32*10
24); | 189 » runtime·signalstack((byte*)g->m->gsignal->stack.lo, 32*1024); |
187 runtime·sigprocmask(SIG_SETMASK, &sigset_none, nil); | 190 runtime·sigprocmask(SIG_SETMASK, &sigset_none, nil); |
188 } | 191 } |
189 | 192 |
190 // Called from dropm to undo the effect of an minit. | 193 // Called from dropm to undo the effect of an minit. |
191 void | 194 void |
192 runtime·unminit(void) | 195 runtime·unminit(void) |
193 { | 196 { |
194 runtime·signalstack(nil, 0); | 197 runtime·signalstack(nil, 0); |
195 } | 198 } |
196 | 199 |
197 void | |
198 runtime·sigpanic(void) | |
199 { | |
200 if(!runtime·canpanic(g)) | |
201 runtime·throw("unexpected signal during runtime execution"); | |
202 | |
203 switch(g->sig) { | |
204 case SIGBUS: | |
205 if(g->sigcode0 == BUS_ADRERR && g->sigcode1 < 0x1000 || g->panic
onfault) { | |
206 if(g->sigpc == 0) | |
207 runtime·panicstring("call of nil func value"); | |
208 runtime·panicstring("invalid memory address or nil point
er dereference"); | |
209 } | |
210 runtime·printf("unexpected fault address %p\n", g->sigcode1); | |
211 runtime·throw("fault"); | |
212 case SIGSEGV: | |
213 if((g->sigcode0 == 0 || g->sigcode0 == SEGV_MAPERR || g->sigcode
0 == SEGV_ACCERR) && g->sigcode1 < 0x1000 || g->paniconfault) { | |
214 if(g->sigpc == 0) | |
215 runtime·panicstring("call of nil func value"); | |
216 runtime·panicstring("invalid memory address or nil point
er dereference"); | |
217 } | |
218 runtime·printf("unexpected fault address %p\n", g->sigcode1); | |
219 runtime·throw("fault"); | |
220 case SIGFPE: | |
221 switch(g->sigcode0) { | |
222 case FPE_INTDIV: | |
223 runtime·panicstring("integer divide by zero"); | |
224 case FPE_INTOVF: | |
225 runtime·panicstring("integer overflow"); | |
226 } | |
227 runtime·panicstring("floating point error"); | |
228 } | |
229 runtime·panicstring(runtime·sigtab[g->sig].name); | |
230 } | |
231 | |
232 uintptr | 200 uintptr |
233 runtime·memlimit(void) | 201 runtime·memlimit(void) |
234 { | 202 { |
235 Rlimit rl; | 203 Rlimit rl; |
236 extern byte runtime·text[], runtime·end[]; | 204 extern byte runtime·text[], runtime·end[]; |
237 uintptr used; | 205 uintptr used; |
238 ········ | 206 ········ |
239 if(runtime·getrlimit(RLIMIT_AS, &rl) != 0) | 207 if(runtime·getrlimit(RLIMIT_AS, &rl) != 0) |
240 return 0; | 208 return 0; |
241 if(rl.rlim_cur >= 0x7fffffff) | 209 if(rl.rlim_cur >= 0x7fffffff) |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
317 | 285 |
318 #pragma textflag NOSPLIT | 286 #pragma textflag NOSPLIT |
319 uintptr | 287 uintptr |
320 runtime·semacreate(void) | 288 runtime·semacreate(void) |
321 { | 289 { |
322 SemT* sem; | 290 SemT* sem; |
323 | 291 |
324 // Call libc's malloc rather than runtime·malloc. This will | 292 // Call libc's malloc rather than runtime·malloc. This will |
325 // allocate space on the C heap. We can't call runtime·malloc | 293 // allocate space on the C heap. We can't call runtime·malloc |
326 // here because it could cause a deadlock. | 294 // here because it could cause a deadlock. |
327 » g->m->libcall.fn = (void*)libc·malloc; | 295 » g->m->libcall.fn = (uintptr)(void*)libc·malloc; |
328 g->m->libcall.n = 1; | 296 g->m->libcall.n = 1; |
329 runtime·memclr((byte*)&g->m->scratch, sizeof(g->m->scratch)); | 297 runtime·memclr((byte*)&g->m->scratch, sizeof(g->m->scratch)); |
330 g->m->scratch.v[0] = (uintptr)sizeof(*sem); | 298 g->m->scratch.v[0] = (uintptr)sizeof(*sem); |
331 » g->m->libcall.args = (uintptr*)&g->m->scratch; | 299 » g->m->libcall.args = (uintptr)(uintptr*)&g->m->scratch; |
332 runtime·asmcgocall(runtime·asmsysvicall6, &g->m->libcall); | 300 runtime·asmcgocall(runtime·asmsysvicall6, &g->m->libcall); |
333 sem = (void*)g->m->libcall.r1; | 301 sem = (void*)g->m->libcall.r1; |
334 if(runtime·sem_init(sem, 0, 0) != 0) | 302 if(runtime·sem_init(sem, 0, 0) != 0) |
335 runtime·throw("sem_init"); | 303 runtime·throw("sem_init"); |
336 return (uintptr)sem; | 304 return (uintptr)sem; |
337 } | 305 } |
338 | 306 |
339 #pragma textflag NOSPLIT | 307 #pragma textflag NOSPLIT |
340 int32 | 308 int32 |
341 runtime·semasleep(int64 ns) | 309 runtime·semasleep(int64 ns) |
342 { | 310 { |
343 M *m; | 311 M *m; |
344 | 312 |
345 m = g->m; | 313 m = g->m; |
346 if(ns >= 0) { | 314 if(ns >= 0) { |
347 m->ts.tv_sec = ns / 1000000000LL; | 315 m->ts.tv_sec = ns / 1000000000LL; |
348 m->ts.tv_nsec = ns % 1000000000LL; | 316 m->ts.tv_nsec = ns % 1000000000LL; |
349 | 317 |
350 » » m->libcall.fn = (void*)libc·sem_reltimedwait_np; | 318 » » m->libcall.fn = (uintptr)(void*)libc·sem_reltimedwait_np; |
351 m->libcall.n = 2; | 319 m->libcall.n = 2; |
352 runtime·memclr((byte*)&m->scratch, sizeof(m->scratch)); | 320 runtime·memclr((byte*)&m->scratch, sizeof(m->scratch)); |
353 m->scratch.v[0] = m->waitsema; | 321 m->scratch.v[0] = m->waitsema; |
354 m->scratch.v[1] = (uintptr)&m->ts; | 322 m->scratch.v[1] = (uintptr)&m->ts; |
355 » » m->libcall.args = (uintptr*)&m->scratch; | 323 » » m->libcall.args = (uintptr)(uintptr*)&m->scratch; |
356 runtime·asmcgocall(runtime·asmsysvicall6, &m->libcall); | 324 runtime·asmcgocall(runtime·asmsysvicall6, &m->libcall); |
357 if(*m->perrno != 0) { | 325 if(*m->perrno != 0) { |
358 if(*m->perrno == ETIMEDOUT || *m->perrno == EAGAIN || *m
->perrno == EINTR) | 326 if(*m->perrno == ETIMEDOUT || *m->perrno == EAGAIN || *m
->perrno == EINTR) |
359 return -1; | 327 return -1; |
360 runtime·throw("sem_reltimedwait_np"); | 328 runtime·throw("sem_reltimedwait_np"); |
361 } | 329 } |
362 return 0; | 330 return 0; |
363 } | 331 } |
364 for(;;) { | 332 for(;;) { |
365 » » m->libcall.fn = (void*)libc·sem_wait; | 333 » » m->libcall.fn = (uintptr)(void*)libc·sem_wait; |
366 m->libcall.n = 1; | 334 m->libcall.n = 1; |
367 runtime·memclr((byte*)&m->scratch, sizeof(m->scratch)); | 335 runtime·memclr((byte*)&m->scratch, sizeof(m->scratch)); |
368 m->scratch.v[0] = m->waitsema; | 336 m->scratch.v[0] = m->waitsema; |
369 » » m->libcall.args = (uintptr*)&m->scratch; | 337 » » m->libcall.args = (uintptr)(uintptr*)&m->scratch; |
370 runtime·asmcgocall(runtime·asmsysvicall6, &m->libcall); | 338 runtime·asmcgocall(runtime·asmsysvicall6, &m->libcall); |
371 if(m->libcall.r1 == 0) | 339 if(m->libcall.r1 == 0) |
372 break; | 340 break; |
373 if(*m->perrno == EINTR)· | 341 if(*m->perrno == EINTR)· |
374 continue; | 342 continue; |
375 runtime·throw("sem_wait"); | 343 runtime·throw("sem_wait"); |
376 } | 344 } |
377 return 0; | 345 return 0; |
378 } | 346 } |
379 | 347 |
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
573 runtime·osyield(void) | 541 runtime·osyield(void) |
574 { | 542 { |
575 // Check the validity of m because we might be called in cgo callback | 543 // Check the validity of m because we might be called in cgo callback |
576 // path early enough where there isn't a m available yet. | 544 // path early enough where there isn't a m available yet. |
577 if(g && g->m != nil) { | 545 if(g && g->m != nil) { |
578 runtime·sysvicall0(libc·sched_yield); | 546 runtime·sysvicall0(libc·sched_yield); |
579 return; | 547 return; |
580 } | 548 } |
581 runtime·osyield1(); | 549 runtime·osyield1(); |
582 } | 550 } |
| 551 |
| 552 #pragma textflag NOSPLIT |
| 553 int8* |
| 554 runtime·signame(int32 sig) |
| 555 { |
| 556 return runtime·sigtab[sig].name; |
| 557 } |
OLD | NEW |