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   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