1 /* 2 ** Copyright (C) 2007, The Android Open Source Project 3 ** 4 ** Licensed under the Apache License, Version 2.0 (the "License"); 5 ** you may not use this file except in compliance with the License. 6 ** You may obtain a copy of the License at 7 ** 8 ** http://www.apache.org/licenses/LICENSE-2.0 9 ** 10 ** Unless required by applicable law or agreed to in writing, software 11 ** distributed under the License is distributed on an "AS IS" BASIS, 12 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 ** See the License for the specific language governing permissions and 14 ** limitations under the License. 15 */ 16 17 #include <cutils/threads.h> 18 19 // For gettid. 20 #if defined(__APPLE__) 21 #include "AvailabilityMacros.h" // For MAC_OS_X_VERSION_MAX_ALLOWED 22 #include <stdint.h> 23 #include <stdlib.h> 24 #include <sys/syscall.h> 25 #include <sys/time.h> 26 #include <unistd.h> 27 #elif defined(__linux__) && !defined(__ANDROID__) 28 #include <syscall.h> 29 #include <unistd.h> 30 #elif defined(_WIN32) 31 #include <windows.h> 32 #endif 33 34 // No definition needed for Android because we'll just pick up bionic's copy. 35 #ifndef __ANDROID__ 36 pid_t gettid() { 37 #if defined(__APPLE__) 38 uint64_t tid; 39 pthread_threadid_np(NULL, &tid); 40 return tid; 41 #elif defined(__linux__) 42 return syscall(__NR_gettid); 43 #elif defined(_WIN32) 44 return GetCurrentThreadId(); 45 #endif 46 } 47 #endif // __ANDROID__ 48 49 #if !defined(_WIN32) 50 51 void* thread_store_get( thread_store_t* store ) 52 { 53 if (!store->has_tls) 54 return NULL; 55 56 return pthread_getspecific( store->tls ); 57 } 58 59 extern void thread_store_set( thread_store_t* store, 60 void* value, 61 thread_store_destruct_t destroy) 62 { 63 pthread_mutex_lock( &store->lock ); 64 if (!store->has_tls) { 65 if (pthread_key_create( &store->tls, destroy) != 0) { 66 pthread_mutex_unlock(&store->lock); 67 return; 68 } 69 store->has_tls = 1; 70 } 71 pthread_mutex_unlock( &store->lock ); 72 73 pthread_setspecific( store->tls, value ); 74 } 75 76 #else /* !defined(_WIN32) */ 77 void* thread_store_get( thread_store_t* store ) 78 { 79 if (!store->has_tls) 80 return NULL; 81 82 return (void*) TlsGetValue( store->tls ); 83 } 84 85 void thread_store_set( thread_store_t* store, 86 void* value, 87 thread_store_destruct_t /*destroy*/ ) 88 { 89 /* XXX: can't use destructor on thread exit */ 90 if (!store->lock_init) { 91 store->lock_init = -1; 92 InitializeCriticalSection( &store->lock ); 93 store->lock_init = -2; 94 } else while (store->lock_init != -2) { 95 Sleep(10); /* 10ms */ 96 } 97 98 EnterCriticalSection( &store->lock ); 99 if (!store->has_tls) { 100 store->tls = TlsAlloc(); 101 if (store->tls == TLS_OUT_OF_INDEXES) { 102 LeaveCriticalSection( &store->lock ); 103 return; 104 } 105 store->has_tls = 1; 106 } 107 LeaveCriticalSection( &store->lock ); 108 109 TlsSetValue( store->tls, value ); 110 } 111 #endif /* !defined(_WIN32) */ 112