github.com/hongwozai/go-src-1.4.3@v0.0.0-20191127132709-dc3fce3dbccb/src/runtime/cgo/gcc_darwin_amd64.c (about)

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