1efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen// Copyright 2015 The Go Authors. All rights reserved. 2efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen// Use of this source code is governed by a BSD-style 3efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen// license that can be found in the LICENSE file. 4efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen 5efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen#include <string.h> /* for strerror */ 6efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen#include <pthread.h> 7efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen#include <signal.h> 8efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen#include "libcgo.h" 9efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen 10efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsenstatic void* threadentry(void*); 11efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsenstatic pthread_key_t k1; 12efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen 13efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen#define magic1 (0x23581321U) 14efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen 15efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsenstatic void 16efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemseninittls(void) 17efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen{ 18efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen uint32 x; 19efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen pthread_key_t tofree[128], k; 20efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen int i, ntofree; 21efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen 22efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen /* 23efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen * Same logic, code as gcc_android_amd64.c:/inittls. 24efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen * Note that this is a temporary hack that should be fixed soon. 25efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen * 26efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen * TODO: fix this. 27efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen * 28efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen * The linker and runtime hard-code this constant offset 29efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen * from %gs where we expect to find g. Disgusting. 30efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen * 31efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen * Known to src/cmd/link/internal/ld/sym.go:/0xf8 32efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen * and to src/runtime/sys_linux_386.s:/0xf8 or /GOOS_android. 33efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen * TODO(hyangah): check 0xb0 works with API23+ 34efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen * 35efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen * As disgusting as on the darwin/386, darwin/amd64. 36efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen */ 37efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen ntofree = 0; 38efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen for(;;) { 39efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen if(pthread_key_create(&k, nil) < 0) { 40efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen fprintf(stderr, "runtime/cgo: pthread_key_create failed\n"); 41efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen abort(); 42efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen } 43efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen pthread_setspecific(k, (void*)magic1); 44efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen asm volatile("movl %%gs:0xf8, %0" : "=r"(x)); 45efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen pthread_setspecific(k, 0); 46efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen if (x == magic1) { 47efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen k1 = k; 48efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen break; 49efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen } 50efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen if(ntofree >= nelem(tofree)) { 51efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen fprintf(stderr, "runtime/cgo: could not obtain pthread_keys\n"); 52efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen fprintf(stderr, "\ttried"); 53efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen for(i=0; i<ntofree; i++) 54efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen fprintf(stderr, " %#x", (unsigned)tofree[i]); 55efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen fprintf(stderr, "\n"); 56efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen abort(); 57efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen } 58efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen tofree[ntofree++] = k; 59efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen } 60efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen // TODO: output to stderr is not useful for apps. 61efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen // Can we fall back to Android's log library? 62efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen 63efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen /* 64efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen * We got the key we wanted. Free the others. 65efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen */ 66efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen for(i=0; i<ntofree; i++) { 67efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen pthread_key_delete(tofree[i]); 68efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen } 69efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen} 70efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen 71efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen 72efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsenstatic void* 73efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsenthreadentry(void *v) 74efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen{ 75efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen ThreadStart ts; 76efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen 77efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen ts = *(ThreadStart*)v; 78efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen free(v); 79efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen 80efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen pthread_setspecific(k1, (void*)ts.g); 81efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen 82efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen crosscall_386(ts.fn); 83efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen return nil; 84efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen} 85efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsen 86efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsenvoid (*x_cgo_inittls)(void) = inittls; 87efea46b87b2dcc66da02dfbf66fd901d24c7a09Dan Willemsenvoid* (*x_cgo_threadentry)(void*) = threadentry; 88