180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/* 380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2011 Google Inc. 480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * 580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be 680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file. 780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkThread.h" 980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 1080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include <pthread.h> 1180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include <errno.h> 1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 1380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifndef SK_BUILD_FOR_ANDROID 1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/** 1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru We prefer the GCC intrinsic implementation of the atomic operations over the 1780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkMutex-based implementation. The SkMutex version suffers from static 1880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru destructor ordering problems. 1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru Note clang also defines the GCC version macros and implements the intrinsics. 2080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru TODO: Verify that gcc-style __sync_* intrinsics work on ARM 2180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru According to this the intrinsics are supported on ARM in LLVM 2.7+ 2280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru http://llvm.org/releases/2.7/docs/ReleaseNotes.html 2380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru*/ 2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || __GNUC__ > 4 2580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #if (defined(__x86_64) || defined(__i386__)) 2680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #define GCC_INTRINSIC 2780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru #endif 2880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif 2980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 3080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if defined(GCC_INTRINSIC) 3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruint32_t sk_atomic_inc(int32_t* addr) 3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{ 3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return __sync_fetch_and_add(addr, 1); 3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 3680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 3780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruint32_t sk_atomic_add(int32_t* addr, int32_t inc) 3880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{ 3980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return __sync_fetch_and_add(addr, inc); 4080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 4180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 4280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruint32_t sk_atomic_dec(int32_t* addr) 4380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{ 4480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return __sync_fetch_and_add(addr, -1); 4580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 4680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid sk_membar_aquire__after_atomic_dec() { } 4780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 4880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruint32_t sk_atomic_conditional_inc(int32_t* addr) 4980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{ 5080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int32_t value = *addr; 5180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 5280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru while (true) { 5380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (value == 0) { 5480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return 0; 5580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 5680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 5780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int32_t before = __sync_val_compare_and_swap(addr, value, value + 1); 5880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 5980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (before == value) { 6080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return value; 6180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } else { 6280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru value = before; 6380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 6480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 6580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 6680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid sk_membar_aquire__after_atomic_conditional_inc() { } 6780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 6880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else 6980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 7080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkMutex gAtomicMutex; 7180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 7280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruint32_t sk_atomic_inc(int32_t* addr) 7380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{ 7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkAutoMutexAcquire ac(gAtomicMutex); 7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int32_t value = *addr; 7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *addr = value + 1; 7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return value; 7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 8080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 8180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruint32_t sk_atomic_add(int32_t* addr, int32_t inc) 8280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{ 8380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkAutoMutexAcquire ac(gAtomicMutex); 8480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 8580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int32_t value = *addr; 8680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *addr = value + inc; 8780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return value; 8880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 8980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 9080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruint32_t sk_atomic_dec(int32_t* addr) 9180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{ 9280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkAutoMutexAcquire ac(gAtomicMutex); 9380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 9480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int32_t value = *addr; 9580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *addr = value - 1; 9680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return value; 9780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 9880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid sk_membar_aquire__after_atomic_dec() { } 9980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 10080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruint32_t sk_atomic_conditional_inc(int32_t* addr) 10180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{ 10280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkAutoMutexAcquire ac(gAtomicMutex); 10380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 10480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int32_t value = *addr; 10580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (value != 0) ++*addr; 10680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return value; 10780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 10880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid sk_membar_aquire__after_atomic_conditional_inc() { } 10980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 11080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif 11180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 11280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif // SK_BUILD_FOR_ANDROID 11380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 11480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru////////////////////////////////////////////////////////////////////////////// 11580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 11680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void print_pthread_error(int status) { 11780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru switch (status) { 11880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru case 0: // success 11980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru break; 12080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru case EINVAL: 12180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkDebugf("pthread error [%d] EINVAL\n", status); 12280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru break; 12380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru case EBUSY: 12480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkDebugf("pthread error [%d] EBUSY\n", status); 12580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru break; 12680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru default: 12780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkDebugf("pthread error [%d] unknown\n", status); 12880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru break; 12980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 13080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 13180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 13280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifdef SK_USE_POSIX_THREADS 13380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 13480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkMutex::SkMutex() { 13580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int status; 13680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 13780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru status = pthread_mutex_init(&fMutex, NULL); 13880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (status != 0) { 13980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru print_pthread_error(status); 14080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(0 == status); 14180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 14280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 14380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 14480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkMutex::~SkMutex() { 14580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int status = pthread_mutex_destroy(&fMutex); 14680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 14780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // only report errors on non-global mutexes 14880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (status != 0) { 14980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru print_pthread_error(status); 15080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(0 == status); 15180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 15280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 15380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 15480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#else // !SK_USE_POSIX_THREADS 15580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 15680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkMutex::SkMutex() { 15780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (sizeof(pthread_mutex_t) > sizeof(fStorage)) { 15880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkDEBUGF(("pthread mutex size = %d\n", sizeof(pthread_mutex_t))); 15980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkDEBUGFAIL("mutex storage is too small"); 16080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 16180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 16280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int status; 16380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru pthread_mutexattr_t attr; 16480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 16580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru status = pthread_mutexattr_init(&attr); 16680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru print_pthread_error(status); 16780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(0 == status); 16880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 16980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru status = pthread_mutex_init((pthread_mutex_t*)fStorage, &attr); 17080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru print_pthread_error(status); 17180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(0 == status); 17280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 17380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 17480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkMutex::~SkMutex() { 17580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int status = pthread_mutex_destroy((pthread_mutex_t*)fStorage); 17680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if 0 17780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // only report errors on non-global mutexes 17880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (!fIsGlobal) { 17980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru print_pthread_error(status); 18080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(0 == status); 18180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 18280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif 18380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 18480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 18580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkMutex::acquire() { 18680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int status = pthread_mutex_lock((pthread_mutex_t*)fStorage); 18780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru print_pthread_error(status); 18880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(0 == status); 18980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 19080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 19180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkMutex::release() { 19280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int status = pthread_mutex_unlock((pthread_mutex_t*)fStorage); 19380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru print_pthread_error(status); 19480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(0 == status); 19580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru} 19680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 19780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif // !SK_USE_POSIX_THREADS 198