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__ 36pid_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 49void* 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 57extern 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) */ 75void* 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 83void 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