blob: 638e522e3bb089067fa73e8613ec59444d840f93 [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);
58
59 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
reed@google.comdcbd6e32012-01-12 15:21:16 +000086SkMutex::SkMutex() {
87 if (sizeof(pthread_mutex_t) > sizeof(fStorage)) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000088 SkDEBUGF(("pthread mutex size = %d\n", sizeof(pthread_mutex_t)));
tomhudson@google.com0c00f212011-12-28 14:59:50 +000089 SkDEBUGFAIL("mutex storage is too small");
reed@android.com8a1c16f2008-12-17 15:59:43 +000090 }
91
92 int status;
93 pthread_mutexattr_t attr;
94
95 status = pthread_mutexattr_init(&attr);
96 print_pthread_error(status);
97 SkASSERT(0 == status);
98
99 status = pthread_mutex_init((pthread_mutex_t*)fStorage, &attr);
100 print_pthread_error(status);
101 SkASSERT(0 == status);
102}
103
reed@google.comdcbd6e32012-01-12 15:21:16 +0000104SkMutex::~SkMutex() {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000105 int status = pthread_mutex_destroy((pthread_mutex_t*)fStorage);
reed@google.comdcbd6e32012-01-12 15:21:16 +0000106#if 0
reed@android.com8a1c16f2008-12-17 15:59:43 +0000107 // only report errors on non-global mutexes
reed@google.comdcbd6e32012-01-12 15:21:16 +0000108 if (!fIsGlobal) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000109 print_pthread_error(status);
110 SkASSERT(0 == status);
111 }
reed@google.comdcbd6e32012-01-12 15:21:16 +0000112#endif
reed@android.com8a1c16f2008-12-17 15:59:43 +0000113}
114
reed@google.comdcbd6e32012-01-12 15:21:16 +0000115void SkMutex::acquire() {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000116 int status = pthread_mutex_lock((pthread_mutex_t*)fStorage);
117 print_pthread_error(status);
118 SkASSERT(0 == status);
119}
120
reed@google.comdcbd6e32012-01-12 15:21:16 +0000121void SkMutex::release() {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000122 int status = pthread_mutex_unlock((pthread_mutex_t*)fStorage);
123 print_pthread_error(status);
124 SkASSERT(0 == status);
125}
126