Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(73)

Side by Side Diff: src/ports/SkThread_pthread.cpp

Issue 19808007: Split atomic and mutex implementations and make inlinable. (Closed) Base URL: http://skia.googlecode.com/svn/trunk/
Patch Set: Address dependency comments. Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ports/SkThread_none.cpp ('k') | src/ports/SkThread_win.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
32 int32_t sk_atomic_inc(int32_t* addr)
33 {
34 return __sync_fetch_and_add(addr, 1);
35 }
36
37 int32_t sk_atomic_add(int32_t* addr, int32_t inc)
38 {
39 return __sync_fetch_and_add(addr, inc);
40 }
41
42 int32_t sk_atomic_dec(int32_t* addr)
43 {
44 return __sync_fetch_and_add(addr, -1);
45 }
46 void sk_membar_aquire__after_atomic_dec() { }
47
48 int32_t sk_atomic_conditional_inc(int32_t* addr)
49 {
50 int32_t value = *addr;
51
52 while (true) {
53 if (value == 0) {
54 return 0;
55 }
56
57 int32_t before = __sync_val_compare_and_swap(addr, value, value + 1);
58
59 if (before == value) {
60 return value;
61 } else {
62 value = before;
63 }
64 }
65 }
66 void sk_membar_aquire__after_atomic_conditional_inc() { }
67
68 #else
69
70 SkMutex gAtomicMutex;
71
72 int32_t sk_atomic_inc(int32_t* addr)
73 {
74 SkAutoMutexAcquire ac(gAtomicMutex);
75
76 int32_t value = *addr;
77 *addr = value + 1;
78 return value;
79 }
80
81 int32_t sk_atomic_add(int32_t* addr, int32_t inc)
82 {
83 SkAutoMutexAcquire ac(gAtomicMutex);
84
85 int32_t value = *addr;
86 *addr = value + inc;
87 return value;
88 }
89
90 int32_t sk_atomic_dec(int32_t* addr)
91 {
92 SkAutoMutexAcquire ac(gAtomicMutex);
93
94 int32_t value = *addr;
95 *addr = value - 1;
96 return value;
97 }
98 void sk_membar_aquire__after_atomic_dec() { }
99
100 int32_t sk_atomic_conditional_inc(int32_t* addr)
101 {
102 SkAutoMutexAcquire ac(gAtomicMutex);
103
104 int32_t value = *addr;
105 if (value != 0) ++*addr;
106 return value;
107 }
108 void sk_membar_aquire__after_atomic_conditional_inc() { }
109
110 #endif
111
112 #endif // SK_BUILD_FOR_ANDROID
113
114 //////////////////////////////////////////////////////////////////////////////
115
116 static void print_pthread_error(int status) {
117 switch (status) {
118 case 0: // success
119 break;
120 case EINVAL:
121 SkDebugf("pthread error [%d] EINVAL\n", status);
122 break;
123 case EBUSY:
124 SkDebugf("pthread error [%d] EBUSY\n", status);
125 break;
126 default:
127 SkDebugf("pthread error [%d] unknown\n", status);
128 break;
129 }
130 }
131
132 #ifdef SK_USE_POSIX_THREADS
133
134 SkMutex::SkMutex() {
135 int status;
136
137 status = pthread_mutex_init(&fMutex, NULL);
138 if (status != 0) {
139 print_pthread_error(status);
140 SkASSERT(0 == status);
141 }
142 }
143
144 SkMutex::~SkMutex() {
145 int status = pthread_mutex_destroy(&fMutex);
146
147 // only report errors on non-global mutexes
148 if (status != 0) {
149 print_pthread_error(status);
150 SkASSERT(0 == status);
151 }
152 }
153
154 #else // !SK_USE_POSIX_THREADS
155
156 SkMutex::SkMutex() {
157 if (sizeof(pthread_mutex_t) > sizeof(fStorage)) {
158 SkDEBUGF(("pthread mutex size = %d\n", sizeof(pthread_mutex_t)));
159 SkDEBUGFAIL("mutex storage is too small");
160 }
161
162 int status;
163 pthread_mutexattr_t attr;
164
165 status = pthread_mutexattr_init(&attr);
166 print_pthread_error(status);
167 SkASSERT(0 == status);
168
169 status = pthread_mutex_init((pthread_mutex_t*)fStorage, &attr);
170 print_pthread_error(status);
171 SkASSERT(0 == status);
172 }
173
174 SkMutex::~SkMutex() {
175 int status = pthread_mutex_destroy((pthread_mutex_t*)fStorage);
176 #if 0
177 // only report errors on non-global mutexes
178 if (!fIsGlobal) {
179 print_pthread_error(status);
180 SkASSERT(0 == status);
181 }
182 #endif
183 }
184
185 void SkMutex::acquire() {
186 int status = pthread_mutex_lock((pthread_mutex_t*)fStorage);
187 print_pthread_error(status);
188 SkASSERT(0 == status);
189 }
190
191 void SkMutex::release() {
192 int status = pthread_mutex_unlock((pthread_mutex_t*)fStorage);
193 print_pthread_error(status);
194 SkASSERT(0 == status);
195 }
196
197 #endif // !SK_USE_POSIX_THREADS
OLDNEW
« no previous file with comments | « src/ports/SkThread_none.cpp ('k') | src/ports/SkThread_win.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698