Home | History | Annotate | Download | only in core
      1 
      2 /*
      3  * Copyright 2006 The Android Open Source Project
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 
      9 
     10 #ifndef SkThread_platform_DEFINED
     11 #define SkThread_platform_DEFINED
     12 
     13 #if defined(SK_BUILD_FOR_ANDROID)
     14 
     15 #if defined(SK_BUILD_FOR_ANDROID_NDK)
     16 
     17 #include <stdint.h>
     18 
     19 /* Just use the GCC atomic intrinsics. They're supported by the NDK toolchain,
     20  * have reasonable performance, and provide full memory barriers
     21  */
     22 static __attribute__((always_inline)) int32_t sk_atomic_inc(int32_t *addr) {
     23     return __sync_fetch_and_add(addr, 1);
     24 }
     25 
     26 static __attribute__((always_inline)) int32_t sk_atomic_dec(int32_t *addr) {
     27     return __sync_fetch_and_add(addr, -1);
     28 }
     29 
     30 #else // !SK_BUILD_FOR_ANDROID_NDK
     31 
     32 /* The platform atomics operations are slightly more efficient than the
     33  * GCC built-ins, so use them.
     34  */
     35 #include <utils/Atomic.h>
     36 
     37 #define sk_atomic_inc(addr)     android_atomic_inc(addr)
     38 #define sk_atomic_dec(addr)     android_atomic_dec(addr)
     39 
     40 #endif // !SK_BUILD_FOR_ANDROID_NDK
     41 
     42 #else  // !SK_BUILD_FOR_ANDROID
     43 
     44 /** Implemented by the porting layer, this function adds 1 to the int specified
     45     by the address (in a thread-safe manner), and returns the previous value.
     46 */
     47 SK_API int32_t sk_atomic_inc(int32_t* addr);
     48 /** Implemented by the porting layer, this function subtracts 1 to the int
     49     specified by the address (in a thread-safe manner), and returns the previous
     50     value.
     51 */
     52 SK_API int32_t sk_atomic_dec(int32_t* addr);
     53 
     54 #endif // !SK_BUILD_FOR_ANDROID
     55 
     56 #ifdef SK_USE_POSIX_THREADS
     57 
     58 #include <pthread.h>
     59 
     60 // A SkBaseMutex is a POD structure that can be directly initialized
     61 // at declaration time with SK_DECLARE_STATIC/GLOBAL_MUTEX. This avoids the
     62 // generation of a static initializer in the final machine code (and
     63 // a corresponding static finalizer).
     64 //
     65 struct SkBaseMutex {
     66     void    acquire() { pthread_mutex_lock(&fMutex); }
     67     void    release() { pthread_mutex_unlock(&fMutex); }
     68     pthread_mutex_t  fMutex;
     69 };
     70 
     71 // Using POD-style initialization prevents the generation of a static initializer
     72 // and keeps the acquire() implementation small and fast.
     73 #define SK_DECLARE_STATIC_MUTEX(name)   static SkBaseMutex  name = { PTHREAD_MUTEX_INITIALIZER }
     74 
     75 // Special case used when the static mutex must be available globally.
     76 #define SK_DECLARE_GLOBAL_MUTEX(name)   SkBaseMutex  name = { PTHREAD_MUTEX_INITIALIZER }
     77 
     78 #define SK_DECLARE_MUTEX_ARRAY(name, count)    SkBaseMutex name[count] = { PTHREAD_MUTEX_INITIALIZER }
     79 
     80 // A normal mutex that requires to be initialized through normal C++ construction,
     81 // i.e. when it's a member of another class, or allocated on the heap.
     82 class SkMutex : public SkBaseMutex, SkNoncopyable {
     83 public:
     84     SkMutex();
     85     ~SkMutex();
     86 };
     87 
     88 #else // !SK_USE_POSIX_THREADS
     89 
     90 // In the generic case, SkBaseMutex and SkMutex are the same thing, and we
     91 // can't easily get rid of static initializers.
     92 //
     93 class SkMutex : SkNoncopyable {
     94 public:
     95     SkMutex();
     96     ~SkMutex();
     97 
     98     void    acquire();
     99     void    release();
    100 
    101 private:
    102     bool fIsGlobal;
    103     enum {
    104         kStorageIntCount = 64
    105     };
    106     uint32_t    fStorage[kStorageIntCount];
    107 };
    108 
    109 typedef SkMutex SkBaseMutex;
    110 
    111 #define SK_DECLARE_STATIC_MUTEX(name)           static SkBaseMutex  name
    112 #define SK_DECLARE_GLOBAL_MUTEX(name)           SkBaseMutex  name
    113 #define SK_DECLARE_MUTEX_ARRAY(name, count)     SkBaseMutex name[count]
    114 
    115 #endif // !SK_USE_POSIX_THREADS
    116 
    117 
    118 #endif
    119