blob: b724c5126bc652995b06dc79cc6d6fcbc966c1a7 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
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 */
reed@android.com8a1c16f2008-12-17 15:59:43 +00008#include "SkThread.h"
9
10#include <pthread.h>
11#include <errno.h>
12
digit@google.comf66436c2012-01-11 17:44:41 +000013#ifndef SK_BUILD_FOR_ANDROID
14
bsalomon@google.com09866002011-08-18 20:31:35 +000015/**
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
32int32_t sk_atomic_inc(int32_t* addr)
33{
34 return __sync_fetch_and_add(addr, 1);
35}
36
37int32_t sk_atomic_dec(int32_t* addr)
38{
39 return __sync_fetch_and_add(addr, -1);
40}
41
42#else
43
reed@android.com8a1c16f2008-12-17 15:59:43 +000044SkMutex gAtomicMutex;
45
46int32_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
55int32_t sk_atomic_dec(int32_t* addr)
56{
57 SkAutoMutexAcquire ac(gAtomicMutex);
digit@google.com1771cbf2012-01-26 21:26:40 +000058
reed@android.com8a1c16f2008-12-17 15:59:43 +000059 int32_t value = *addr;
60 *addr = value - 1;
61 return value;
62}
63
bsalomon@google.com09866002011-08-18 20:31:35 +000064#endif
65
digit@google.comf66436c2012-01-11 17:44:41 +000066#endif // SK_BUILD_FOR_ANDROID
67
reed@android.com8a1c16f2008-12-17 15:59:43 +000068//////////////////////////////////////////////////////////////////////////////
69
reed@google.comdcbd6e32012-01-12 15:21:16 +000070static void print_pthread_error(int status) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000071 switch (status) {
72 case 0: // success
73 break;
74 case EINVAL:
reed@google.comdcbd6e32012-01-12 15:21:16 +000075 SkDebugf("pthread error [%d] EINVAL\n", status);
reed@android.com8a1c16f2008-12-17 15:59:43 +000076 break;
77 case EBUSY:
reed@google.comdcbd6e32012-01-12 15:21:16 +000078 SkDebugf("pthread error [%d] EBUSY\n", status);
reed@android.com8a1c16f2008-12-17 15:59:43 +000079 break;
80 default:
reed@google.comdcbd6e32012-01-12 15:21:16 +000081 SkDebugf("pthread error [%d] unknown\n", status);
reed@android.com8a1c16f2008-12-17 15:59:43 +000082 break;
83 }
84}
85
digit@google.com1771cbf2012-01-26 21:26:40 +000086#ifdef SK_USE_POSIX_THREADS
87
88SkMutex::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
98SkMutex::~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
reed@google.comdcbd6e32012-01-12 15:21:16 +0000110SkMutex::SkMutex() {
111 if (sizeof(pthread_mutex_t) > sizeof(fStorage)) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000112 SkDEBUGF(("pthread mutex size = %d\n", sizeof(pthread_mutex_t)));
tomhudson@google.com0c00f212011-12-28 14:59:50 +0000113 SkDEBUGFAIL("mutex storage is too small");
reed@android.com8a1c16f2008-12-17 15:59:43 +0000114 }
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
reed@google.comdcbd6e32012-01-12 15:21:16 +0000128SkMutex::~SkMutex() {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000129 int status = pthread_mutex_destroy((pthread_mutex_t*)fStorage);
reed@google.comdcbd6e32012-01-12 15:21:16 +0000130#if 0
reed@android.com8a1c16f2008-12-17 15:59:43 +0000131 // only report errors on non-global mutexes
reed@google.comdcbd6e32012-01-12 15:21:16 +0000132 if (!fIsGlobal) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000133 print_pthread_error(status);
134 SkASSERT(0 == status);
135 }
reed@google.comdcbd6e32012-01-12 15:21:16 +0000136#endif
reed@android.com8a1c16f2008-12-17 15:59:43 +0000137}
138
reed@google.comdcbd6e32012-01-12 15:21:16 +0000139void SkMutex::acquire() {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000140 int status = pthread_mutex_lock((pthread_mutex_t*)fStorage);
141 print_pthread_error(status);
142 SkASSERT(0 == status);
143}
144
reed@google.comdcbd6e32012-01-12 15:21:16 +0000145void SkMutex::release() {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000146 int status = pthread_mutex_unlock((pthread_mutex_t*)fStorage);
147 print_pthread_error(status);
148 SkASSERT(0 == status);
149}
150
digit@google.com1771cbf2012-01-26 21:26:40 +0000151#endif // !SK_USE_POSIX_THREADS
reed@google.come6f7d682012-04-23 12:51:32 +0000152
153///////////////////////////////////////////////////////////////////////////////
154
reed@google.come6f7d682012-04-23 12:51:32 +0000155static pthread_key_t gSkTLSKey;
156static pthread_once_t gSkTLSKey_Once = PTHREAD_ONCE_INIT;
157
158static void sk_tls_make_key() {
reed@google.com48ca7e32012-05-07 20:23:27 +0000159 (void)pthread_key_create(&gSkTLSKey, SkTLS::Destructor);
reed@google.come6f7d682012-04-23 12:51:32 +0000160}
161
reed@google.com48ca7e32012-05-07 20:23:27 +0000162void* SkTLS::PlatformGetSpecific() {
reed@google.come6f7d682012-04-23 12:51:32 +0000163 (void)pthread_once(&gSkTLSKey_Once, sk_tls_make_key);
reed@google.com48ca7e32012-05-07 20:23:27 +0000164 return pthread_getspecific(gSkTLSKey);
reed@google.come6f7d682012-04-23 12:51:32 +0000165}
166
reed@google.com48ca7e32012-05-07 20:23:27 +0000167void SkTLS::PlatformSetSpecific(void* ptr) {
168 (void)pthread_setspecific(gSkTLSKey, ptr);
reed@google.comae1b6b62012-04-23 15:49:45 +0000169}
170