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 return syscall(SYS_thread_selfid); 39 #elif defined(__linux__) 40 return syscall(__NR_gettid); 41 #elif defined(_WIN32) 42 return GetCurrentThreadId(); 43 #endif 44 } 45 #endif // __ANDROID__ 46 47 #if !defined(_WIN32) 48 49 void* thread_store_get( thread_store_t* store ) 50 { 51 if (!store->has_tls) 52 return NULL; 53 54 return pthread_getspecific( store->tls ); 55 } 56 57 extern void thread_store_set( thread_store_t* store, 58 void* value, 59 thread_store_destruct_t destroy) 60 { 61 pthread_mutex_lock( &store->lock ); 62 if (!store->has_tls) { 63 if (pthread_key_create( &store->tls, destroy) != 0) { 64 pthread_mutex_unlock(&store->lock); 65 return; 66 } 67 store->has_tls = 1; 68 } 69 pthread_mutex_unlock( &store->lock ); 70 71 pthread_setspecific( store->tls, value ); 72 } 73 74 #else /* !defined(_WIN32) */ 75 void* thread_store_get( thread_store_t* store ) 76 { 77 if (!store->has_tls) 78 return NULL; 79 80 return (void*) TlsGetValue( store->tls ); 81 } 82 83 void thread_store_set( thread_store_t* store, 84 void* value, 85 thread_store_destruct_t destroy ) 86 { 87 /* XXX: can't use destructor on thread exit */ 88 if (!store->lock_init) { 89 store->lock_init = -1; 90 InitializeCriticalSection( &store->lock ); 91 store->lock_init = -2; 92 } else while (store->lock_init != -2) { 93 Sleep(10); /* 10ms */ 94 } 95 96 EnterCriticalSection( &store->lock ); 97 if (!store->has_tls) { 98 store->tls = TlsAlloc(); 99 if (store->tls == TLS_OUT_OF_INDEXES) { 100 LeaveCriticalSection( &store->lock ); 101 return; 102 } 103 store->has_tls = 1; 104 } 105 LeaveCriticalSection( &store->lock ); 106 107 TlsSetValue( store->tls, value ); 108 } 109 #endif /* !defined(_WIN32) */ 110