1// 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 <sys/types.h>
6#include <pthread.h>
7#include <signal.h>
8#include <string.h>
9#include "libcgo.h"
10#include "libcgo_unix.h"
11
12static void* threadentry(void*);
13static void (*setg_gcc)(void*);
14
15void
16x_cgo_init(G *g, void (*setg)(void*))
17{
18	pthread_attr_t attr;
19	size_t size;
20
21	setg_gcc = setg;
22	pthread_attr_init(&attr);
23	pthread_attr_getstacksize(&attr, &size);
24	g->stacklo = (uintptr)&attr - size + 4096;
25	pthread_attr_destroy(&attr);
26}
27
28
29void
30_cgo_sys_thread_start(ThreadStart *ts)
31{
32	pthread_attr_t attr;
33	sigset_t ign, oset;
34	pthread_t p;
35	size_t size;
36	int err;
37
38	sigfillset(&ign);
39	pthread_sigmask(SIG_SETMASK, &ign, &oset);
40
41	pthread_attr_init(&attr);
42	pthread_attr_getstacksize(&attr, &size);
43
44	// Leave stacklo=0 and set stackhi=size; mstack will do the rest.
45	ts->g->stackhi = size;
46	err = _cgo_try_pthread_create(&p, &attr, threadentry, ts);
47
48	pthread_sigmask(SIG_SETMASK, &oset, nil);
49
50	if (err != 0) {
51		fprintf(stderr, "runtime/cgo: pthread_create failed: %s\n", strerror(err));
52		abort();
53	}
54}
55
56static void*
57threadentry(void *v)
58{
59	ThreadStart ts;
60	stack_t ss;
61
62	ts = *(ThreadStart*)v;
63	free(v);
64
65	/*
66	 * Set specific keys.
67	 */
68	setg_gcc((void*)ts.g);
69
70	// On NetBSD, a new thread inherits the signal stack of the
71	// creating thread. That confuses minit, so we remove that
72	// signal stack here before calling the regular mstart. It's
73	// a bit baroque to remove a signal stack here only to add one
74	// in minit, but it's a simple change that keeps NetBSD
75	// working like other OS's. At this point all signals are
76	// blocked, so there is no race.
77	memset(&ss, 0, sizeof ss);
78	ss.ss_flags = SS_DISABLE;
79	sigaltstack(&ss, nil);
80
81	crosscall_amd64(ts.fn);
82	return nil;
83}
84