...
Run Format

Text file src/runtime/cgo/gcc_darwin_amd64.c

Documentation: runtime/cgo

     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 <string.h> /* for strerror */
     6	#include <pthread.h>
     7	#include <signal.h>
     8	#include "libcgo.h"
     9	#include "libcgo_unix.h"
    10	
    11	static void* threadentry(void*);
    12	static pthread_key_t k1;
    13	
    14	#define magic1 (0x23581321345589ULL)
    15	
    16	static void
    17	inittls(void)
    18	{
    19		uint64 x;
    20		pthread_key_t tofree[128], k;
    21		int i, ntofree;
    22	
    23		/*
    24		 * Same logic, code as darwin_386.c:/inittls, except that words
    25		 * are 8 bytes long now, and the thread-local storage starts
    26		 * at 0x60 on Leopard / Snow Leopard. So the offset is
    27		 * 0x60+8*0x108 = 0x8a0.
    28		 *
    29		 * The linker and runtime hard-code this constant offset
    30		 * from %gs where we expect to find g.
    31		 * Known to ../../../liblink/sym.c:/8a0
    32		 * and to ../sys_darwin_amd64.s:/8a0
    33		 *
    34		 * As disgusting as on the 386; same justification.
    35		 */
    36		ntofree = 0;
    37		for(;;) {
    38			if(pthread_key_create(&k, nil) < 0) {
    39				fprintf(stderr, "runtime/cgo: pthread_key_create failed\n");
    40				abort();
    41			}
    42			pthread_setspecific(k, (void*)magic1);
    43			asm volatile("movq %%gs:0x8a0, %0" : "=r"(x));
    44			pthread_setspecific(k, 0);
    45			if(x == magic1) {
    46				k1 = k;
    47				break;
    48			}
    49			if(ntofree >= nelem(tofree)) {
    50				fprintf(stderr, "runtime/cgo: could not obtain pthread_keys\n");
    51				fprintf(stderr, "\ttried");
    52				for(i=0; i<ntofree; i++)
    53					fprintf(stderr, " %#x", (unsigned)tofree[i]);
    54				fprintf(stderr, "\n");
    55				abort();
    56			}
    57			tofree[ntofree++] = k;
    58		}
    59	
    60		/*
    61		 * We got the key we wanted.  Free the others.
    62		 */
    63		for(i=0; i<ntofree; i++)
    64			pthread_key_delete(tofree[i]);
    65	}
    66	
    67	void
    68	x_cgo_init(G *g)
    69	{
    70		pthread_attr_t attr;
    71		size_t size;
    72	
    73		pthread_attr_init(&attr);
    74		pthread_attr_getstacksize(&attr, &size);
    75		g->stacklo = (uintptr)&attr - size + 4096;
    76		pthread_attr_destroy(&attr);
    77	
    78		inittls();
    79	}
    80	
    81	
    82	void
    83	_cgo_sys_thread_start(ThreadStart *ts)
    84	{
    85		pthread_attr_t attr;
    86		sigset_t ign, oset;
    87		pthread_t p;
    88		size_t size;
    89		int err;
    90	
    91		sigfillset(&ign);
    92		pthread_sigmask(SIG_SETMASK, &ign, &oset);
    93	
    94		pthread_attr_init(&attr);
    95		pthread_attr_getstacksize(&attr, &size);
    96		// Leave stacklo=0 and set stackhi=size; mstart will do the rest.
    97		ts->g->stackhi = size;
    98		err = _cgo_try_pthread_create(&p, &attr, threadentry, ts);
    99	
   100		pthread_sigmask(SIG_SETMASK, &oset, nil);
   101	
   102		if (err != 0) {
   103			fprintf(stderr, "runtime/cgo: pthread_create failed: %s\n", strerror(err));
   104			abort();
   105		}
   106	}
   107	
   108	static void*
   109	threadentry(void *v)
   110	{
   111		ThreadStart ts;
   112	
   113		ts = *(ThreadStart*)v;
   114		free(v);
   115	
   116		pthread_setspecific(k1, (void*)ts.g);
   117	
   118		crosscall_amd64(ts.fn);
   119		return nil;
   120	}

View as plain text