Home | History | Annotate | Download | only in libcutils
      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