• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /*
3  * Copyright 2011 Google Inc.
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 #include "SkThread.h"
9 
10 #include <pthread.h>
11 #include <errno.h>
12 
13 #ifndef SK_BUILD_FOR_ANDROID
14 
15 /**
16  We prefer the GCC intrinsic implementation of the atomic operations over the
17  SkMutex-based implementation. The SkMutex version suffers from static
18  destructor ordering problems.
19  Note clang also defines the GCC version macros and implements the intrinsics.
20  TODO: Verify that gcc-style __sync_* intrinsics work on ARM
21  According to this the intrinsics are supported on ARM in LLVM 2.7+
22  http://llvm.org/releases/2.7/docs/ReleaseNotes.html
23 */
24 #if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || __GNUC__ > 4
25     #if (defined(__x86_64) || defined(__i386__))
26         #define GCC_INTRINSIC
27     #endif
28 #endif
29 
30 #if defined(GCC_INTRINSIC)
31 
sk_atomic_inc(int32_t * addr)32 int32_t sk_atomic_inc(int32_t* addr)
33 {
34     return __sync_fetch_and_add(addr, 1);
35 }
36 
sk_atomic_dec(int32_t * addr)37 int32_t sk_atomic_dec(int32_t* addr)
38 {
39     return __sync_fetch_and_add(addr, -1);
40 }
41 
42 #else
43 
44 SkMutex gAtomicMutex;
45 
sk_atomic_inc(int32_t * addr)46 int32_t sk_atomic_inc(int32_t* addr)
47 {
48     SkAutoMutexAcquire ac(gAtomicMutex);
49 
50     int32_t value = *addr;
51     *addr = value + 1;
52     return value;
53 }
54 
sk_atomic_dec(int32_t * addr)55 int32_t sk_atomic_dec(int32_t* addr)
56 {
57     SkAutoMutexAcquire ac(gAtomicMutex);
58 
59     int32_t value = *addr;
60     *addr = value - 1;
61     return value;
62 }
63 
64 #endif
65 
66 #endif // SK_BUILD_FOR_ANDROID
67 
68 //////////////////////////////////////////////////////////////////////////////
69 
print_pthread_error(int status)70 static void print_pthread_error(int status) {
71     switch (status) {
72     case 0: // success
73         break;
74     case EINVAL:
75         SkDebugf("pthread error [%d] EINVAL\n", status);
76         break;
77     case EBUSY:
78         SkDebugf("pthread error [%d] EBUSY\n", status);
79         break;
80     default:
81         SkDebugf("pthread error [%d] unknown\n", status);
82         break;
83     }
84 }
85 
86 #ifdef SK_USE_POSIX_THREADS
87 
SkMutex()88 SkMutex::SkMutex() {
89     int status;
90 
91     status = pthread_mutex_init(&fMutex, NULL);
92     if (status != 0) {
93         print_pthread_error(status);
94         SkASSERT(0 == status);
95     }
96 }
97 
~SkMutex()98 SkMutex::~SkMutex() {
99     int status = pthread_mutex_destroy(&fMutex);
100 
101     // only report errors on non-global mutexes
102     if (status != 0) {
103         print_pthread_error(status);
104         SkASSERT(0 == status);
105     }
106 }
107 
108 #else // !SK_USE_POSIX_THREADS
109 
SkMutex()110 SkMutex::SkMutex() {
111     if (sizeof(pthread_mutex_t) > sizeof(fStorage)) {
112         SkDEBUGF(("pthread mutex size = %d\n", sizeof(pthread_mutex_t)));
113         SkDEBUGFAIL("mutex storage is too small");
114     }
115 
116     int status;
117     pthread_mutexattr_t attr;
118 
119     status = pthread_mutexattr_init(&attr);
120     print_pthread_error(status);
121     SkASSERT(0 == status);
122 
123     status = pthread_mutex_init((pthread_mutex_t*)fStorage, &attr);
124     print_pthread_error(status);
125     SkASSERT(0 == status);
126 }
127 
~SkMutex()128 SkMutex::~SkMutex() {
129     int status = pthread_mutex_destroy((pthread_mutex_t*)fStorage);
130 #if 0
131     // only report errors on non-global mutexes
132     if (!fIsGlobal) {
133         print_pthread_error(status);
134         SkASSERT(0 == status);
135     }
136 #endif
137 }
138 
acquire()139 void SkMutex::acquire() {
140     int status = pthread_mutex_lock((pthread_mutex_t*)fStorage);
141     print_pthread_error(status);
142     SkASSERT(0 == status);
143 }
144 
release()145 void SkMutex::release() {
146     int status = pthread_mutex_unlock((pthread_mutex_t*)fStorage);
147     print_pthread_error(status);
148     SkASSERT(0 == status);
149 }
150 
151 #endif // !SK_USE_POSIX_THREADS
152