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