• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015 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 <pthread.h>
6 #include <string.h>
7 #include <signal.h>
8 #include <ucontext.h>
9 #include "libcgo.h"
10 #include "libcgo_unix.h"
11 
12 static void* threadentry(void*);
13 static void (*setg_gcc)(void*);
14 
15 void
x_cgo_init(G * g,void (* setg)(void *))16 x_cgo_init(G *g, void (*setg)(void*))
17 {
18 	ucontext_t ctx;
19 
20 	setg_gcc = setg;
21 	if (getcontext(&ctx) != 0)
22 		perror("runtime/cgo: getcontext failed");
23 	g->stacklo = (uintptr_t)ctx.uc_stack.ss_sp;
24 
25 	// Solaris processes report a tiny stack when run with "ulimit -s unlimited".
26 	// Correct that as best we can: assume it's at least 1 MB.
27 	// See golang.org/issue/12210.
28 	if(ctx.uc_stack.ss_size < 1024*1024)
29 		g->stacklo -= 1024*1024 - ctx.uc_stack.ss_size;
30 
31 	// Sanity check the results now, rather than getting a
32 	// morestack on g0 crash.
33 	if (g->stacklo >= g->stackhi) {
34 		fatalf("bad stack bounds: lo=%p hi=%p", (void*)(g->stacklo), (void*)(g->stackhi));
35 	}
36 }
37 
38 void
_cgo_sys_thread_start(ThreadStart * ts)39 _cgo_sys_thread_start(ThreadStart *ts)
40 {
41 	pthread_attr_t attr;
42 	sigset_t ign, oset;
43 	pthread_t p;
44 	void *base;
45 	size_t size;
46 	int err;
47 
48 	sigfillset(&ign);
49 	pthread_sigmask(SIG_SETMASK, &ign, &oset);
50 
51 	pthread_attr_init(&attr);
52 
53 	if (pthread_attr_getstack(&attr, &base, &size) != 0)
54 		perror("runtime/cgo: pthread_attr_getstack failed");
55 	if (size == 0) {
56 		ts->g->stackhi = 2 << 20;
57 		if (pthread_attr_setstack(&attr, NULL, ts->g->stackhi) != 0)
58 			perror("runtime/cgo: pthread_attr_setstack failed");
59 	} else {
60 		ts->g->stackhi = size;
61 	}
62 	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
63 	err = _cgo_try_pthread_create(&p, &attr, threadentry, ts);
64 
65 	pthread_sigmask(SIG_SETMASK, &oset, nil);
66 
67 	if (err != 0) {
68 		fatalf("pthread_create failed: %s", strerror(err));
69 	}
70 }
71 
72 extern void crosscall1(void (*fn)(void), void (*setg_gcc)(void*), void *g);
73 static void*
threadentry(void * v)74 threadentry(void *v)
75 {
76 	ThreadStart ts;
77 
78 	ts = *(ThreadStart*)v;
79 	free(v);
80 
81 	crosscall1(ts.fn, setg_gcc, (void*)ts.g);
82 	return nil;
83 }
84