diff --git a/bench/MutexBench.cpp b/bench/MutexBench.cpp index d9b427b444..af8a840182 100644 --- a/bench/MutexBench.cpp +++ b/bench/MutexBench.cpp @@ -23,7 +23,7 @@ protected: virtual void onDraw(SkCanvas* canvas) { for (int i = 0; i < N; i++) { - SkMutex mu; + SK_DECLARE_STATIC_MUTEX(mu); for (int j = 0; j < M; j++) { mu.acquire(); mu.release(); diff --git a/gyp/common_conditions.gypi b/gyp/common_conditions.gypi index 99cabc9b16..faa48fb45d 100644 --- a/gyp/common_conditions.gypi +++ b/gyp/common_conditions.gypi @@ -205,6 +205,14 @@ }, ], + # We can POD-style initialization of static mutexes to avoid generating + # static initializers if we're using a pthread-compatible thread interface. + [ 'skia_os != "win"', { + 'defines': [ + 'SK_USE_POSIX_THREADS' + ], + }], + ], # end 'conditions' } diff --git a/include/core/SkPixelRef.h b/include/core/SkPixelRef.h index e247479ad5..3f0784433e 100644 --- a/include/core/SkPixelRef.h +++ b/include/core/SkPixelRef.h @@ -52,7 +52,7 @@ class SkGpuTexture; */ class SkPixelRef : public SkRefCnt { public: - explicit SkPixelRef(SkMutex* mutex = NULL); + explicit SkPixelRef(SkBaseMutex* mutex = NULL); /** Return the pixel memory returned from lockPixels, or null if the lockCount is 0. @@ -201,16 +201,16 @@ protected: /** Return the mutex associated with this pixelref. This value is assigned in the constructor, and cannot change during the lifetime of the object. */ - SkMutex* mutex() const { return fMutex; } + SkBaseMutex* mutex() const { return fMutex; } - SkPixelRef(SkFlattenableReadBuffer&, SkMutex*); + SkPixelRef(SkFlattenableReadBuffer&, SkBaseMutex*); private: #if !SK_ALLOW_STATIC_GLOBAL_INITIALIZERS static void InitializeFlattenables(); #endif - SkMutex* fMutex; // must remain in scope for the life of this object + SkBaseMutex* fMutex; // must remain in scope for the life of this object void* fPixels; SkColorTable* fColorTable; // we do not track ownership, subclass does int fLockCount; diff --git a/include/core/SkThread.h b/include/core/SkThread.h index 5f2da4a006..1495a16fa9 100644 --- a/include/core/SkThread.h +++ b/include/core/SkThread.h @@ -31,7 +31,7 @@ public: class SkAutoMutexAcquire : SkNoncopyable { public: - explicit SkAutoMutexAcquire(SkMutex& mutex) : fMutex(&mutex) + explicit SkAutoMutexAcquire(SkBaseMutex& mutex) : fMutex(&mutex) { SkASSERT(fMutex != NULL); mutex.acquire(); @@ -55,7 +55,7 @@ public: } private: - SkMutex* fMutex; + SkBaseMutex* fMutex; }; #endif diff --git a/include/core/SkThread_platform.h b/include/core/SkThread_platform.h index cbb4891c1a..94a4a1edeb 100644 --- a/include/core/SkThread_platform.h +++ b/include/core/SkThread_platform.h @@ -78,7 +78,44 @@ SK_API int32_t sk_atomic_inc(int32_t* addr); */ SK_API int32_t sk_atomic_dec(int32_t* addr); -class SkMutex { +#endif + +#ifdef SK_USE_POSIX_THREADS + +#include + +// A SkBaseMutex is a POD structure that can be directly initialized +// at declaration time with SK_DECLARE_STATIC/GLOBAL_MUTEX. This avoids the +// generation of a static initializer in the final machine code (and +// a corresponding static finalizer). +// +struct SkBaseMutex { + void acquire() { pthread_mutex_lock(&fMutex); } + void release() { pthread_mutex_unlock(&fMutex); } + pthread_mutex_t fMutex; +}; + +// Using POD-style initialization prevents the generation of a static initializer +// and keeps the acquire() implementation small and fast. +#define SK_DECLARE_STATIC_MUTEX(name) static SkBaseMutex name = { PTHREAD_MUTEX_INITIALIZER } + +// Special case used when the static mutex must be available globally. +#define SK_DECLARE_GLOBAL_MUTEX(name) SkBaseMutex name = { PTHREAD_MUTEX_INITIALIZER } + +// A normal mutex that requires to be initialized through normal C++ construction, +// i.e. when it's a member of another class, or allocated on the heap. +class SkMutex : public SkBaseMutex, SkNoncopyable { +public: + SkMutex(); + ~SkMutex(); +}; + +#else // !SK_USE_POSIX_THREADS + +// In the generic case, SkBaseMutex and SkMutex are the same thing, and we +// can't easily get rid of static initializers. +// +class SkMutex : SkNoncopyable { public: SkMutex(); ~SkMutex(); @@ -94,6 +131,12 @@ private: uint32_t fStorage[kStorageIntCount]; }; -#endif +typedef SkMutex SkBaseMutex; + +#define SK_DECLARE_STATIC_MUTEX(name) static SkBaseMutex name +#define SK_DECLARE_GLOBAL_MUTEX(name) SkBaseMutex name + +#endif // !SK_USE_POSIX_THREADS + #endif diff --git a/include/pdf/SkPDFFont.h b/include/pdf/SkPDFFont.h index b884017912..2ebdec73da 100644 --- a/include/pdf/SkPDFFont.h +++ b/include/pdf/SkPDFFont.h @@ -196,7 +196,7 @@ private: // This should be made a hash table if performance is a problem. static SkTDArray& CanonicalFonts(); - static SkMutex& CanonicalFontsMutex(); + static SkBaseMutex& CanonicalFontsMutex(); }; #endif diff --git a/include/pdf/SkPDFGraphicState.h b/include/pdf/SkPDFGraphicState.h index 9420405273..af01737276 100644 --- a/include/pdf/SkPDFGraphicState.h +++ b/include/pdf/SkPDFGraphicState.h @@ -86,7 +86,7 @@ private: // This should be made a hash table if performance is a problem. static SkTDArray& CanonicalPaints(); - static SkMutex& CanonicalPaintsMutex(); + static SkBaseMutex& CanonicalPaintsMutex(); SkPDFGraphicState(); explicit SkPDFGraphicState(const SkPaint& paint); diff --git a/include/pdf/SkPDFShader.h b/include/pdf/SkPDFShader.h index 6b6ae031b1..439d83bbd5 100644 --- a/include/pdf/SkPDFShader.h +++ b/include/pdf/SkPDFShader.h @@ -56,7 +56,7 @@ protected: }; // This should be made a hash table if performance is a problem. static SkTDArray& CanonicalShaders(); - static SkMutex& CanonicalShadersMutex(); + static SkBaseMutex& CanonicalShadersMutex(); static void RemoveShader(SkPDFObject* shader); SkPDFShader(); diff --git a/obsolete/SkGLDevice.cpp b/obsolete/SkGLDevice.cpp index ec819d28b0..d4606d936a 100644 --- a/obsolete/SkGLDevice.cpp +++ b/obsolete/SkGLDevice.cpp @@ -867,7 +867,7 @@ void SkGLDevice::drawTextOnPath(const SkDraw& draw, const void* text, #include "SkTextureCache.h" #include "SkThread.h" -static SkMutex gTextureCacheMutex; +SK_DECLARE_STATIC_MUTEX(gTextureCacheMutex); static SkTextureCache gTextureCache(kTexCountMax_Default, kTexSizeMax_Default); SkGLDevice::TexCache* SkGLDevice::LockTexCache(const SkBitmap& bitmap, diff --git a/src/core/SkMemory_stdlib.cpp b/src/core/SkMemory_stdlib.cpp index df8735968a..033b331013 100644 --- a/src/core/SkMemory_stdlib.cpp +++ b/src/core/SkMemory_stdlib.cpp @@ -29,7 +29,7 @@ static const char kBlockTrailerTag[] = { 'a', 'i', 'k', 's' }; #define kByteFill 0xCD #define kDeleteFill 0xEF -static SkMutex& get_block_mutex() { +static SkBaseMutex& get_block_mutex() { static SkMutex* gBlockMutex; if (NULL == gBlockMutex) { gBlockMutex = new SkMutex; diff --git a/src/core/SkPixelRef.cpp b/src/core/SkPixelRef.cpp index 1f28ae7eea..d5e1b81525 100644 --- a/src/core/SkPixelRef.cpp +++ b/src/core/SkPixelRef.cpp @@ -9,7 +9,7 @@ #include "SkFlattenable.h" #include "SkThread.h" -static SkMutex gPixelRefMutex; +SK_DECLARE_STATIC_MUTEX(gPixelRefMutex); extern int32_t SkNextPixelRefGenerationID(); int32_t SkNextPixelRefGenerationID() { @@ -24,7 +24,7 @@ int32_t SkNextPixelRefGenerationID() { } -SkPixelRef::SkPixelRef(SkMutex* mutex) { +SkPixelRef::SkPixelRef(SkBaseMutex* mutex) { if (NULL == mutex) { mutex = &gPixelRefMutex; } @@ -36,7 +36,7 @@ SkPixelRef::SkPixelRef(SkMutex* mutex) { fIsImmutable = false; } -SkPixelRef::SkPixelRef(SkFlattenableReadBuffer& buffer, SkMutex* mutex) { +SkPixelRef::SkPixelRef(SkFlattenableReadBuffer& buffer, SkBaseMutex* mutex) { if (NULL == mutex) { mutex = &gPixelRefMutex; } diff --git a/src/core/SkTypefaceCache.cpp b/src/core/SkTypefaceCache.cpp index 5a0b36c860..929b7955f7 100644 --- a/src/core/SkTypefaceCache.cpp +++ b/src/core/SkTypefaceCache.cpp @@ -82,7 +82,7 @@ SkFontID SkTypefaceCache::NewFontID() { return sk_atomic_inc(&gFontID) + 1; } -static SkMutex gMutex; +SK_DECLARE_STATIC_MUTEX(gMutex); void SkTypefaceCache::Add(SkTypeface* face, SkTypeface::Style requestedStyle) { SkAutoMutexAcquire ama(gMutex); diff --git a/src/effects/SkGradientShader.cpp b/src/effects/SkGradientShader.cpp index 240a7a4b25..e32acb2ae8 100644 --- a/src/effects/SkGradientShader.cpp +++ b/src/effects/SkGradientShader.cpp @@ -755,7 +755,7 @@ void Gradient_Shader::commonAsABitmap(SkBitmap* bitmap) const { /////////////////////////////////// - static SkMutex gMutex; + SK_DECLARE_STATIC_MUTEX(gMutex); static SkBitmapCache* gCache; // each cache cost 1K of RAM, since each bitmap will be 1x256 at 32bpp static const int MAX_NUM_CACHED_GRADIENT_BITMAPS = 32; diff --git a/src/gpu/SkGrTexturePixelRef.cpp b/src/gpu/SkGrTexturePixelRef.cpp index 045ddab87d..4b546d62ae 100644 --- a/src/gpu/SkGrTexturePixelRef.cpp +++ b/src/gpu/SkGrTexturePixelRef.cpp @@ -16,7 +16,7 @@ // since we call lockPixels recursively on fBitmap, we need a distinct mutex, // to avoid deadlock with the default one provided by SkPixelRef. -static SkMutex gROLockPixelsPixelRefMutex; +SK_DECLARE_STATIC_MUTEX(gROLockPixelsPixelRefMutex); SkROLockPixelsPixelRef::SkROLockPixelsPixelRef() : INHERITED(&gROLockPixelsPixelRefMutex) { } diff --git a/src/images/SkImageRef.cpp b/src/images/SkImageRef.cpp index 2d53f7ee2d..1d6b270d6c 100644 --- a/src/images/SkImageRef.cpp +++ b/src/images/SkImageRef.cpp @@ -16,7 +16,7 @@ //#define DUMP_IMAGEREF_LIFECYCLE // can't be static, as SkImageRef_Pool needs to see it -SkMutex gImageRefMutex; +SK_DECLARE_GLOBAL_MUTEX(gImageRefMutex); /////////////////////////////////////////////////////////////////////////////// diff --git a/src/images/SkImageRef_GlobalPool.cpp b/src/images/SkImageRef_GlobalPool.cpp index 6ea42c1195..93e7535dc4 100644 --- a/src/images/SkImageRef_GlobalPool.cpp +++ b/src/images/SkImageRef_GlobalPool.cpp @@ -9,7 +9,7 @@ #include "SkImageRefPool.h" #include "SkThread.h" -extern SkMutex gImageRefMutex; +extern SkBaseMutex gImageRefMutex; static SkImageRefPool gGlobalImageRefPool; diff --git a/src/pdf/SkPDFFont.cpp b/src/pdf/SkPDFFont.cpp index 465fbe162f..3aea4b83d8 100644 --- a/src/pdf/SkPDFFont.cpp +++ b/src/pdf/SkPDFFont.cpp @@ -797,9 +797,10 @@ SkTDArray& SkPDFFont::CanonicalFonts() { } // static -SkMutex& SkPDFFont::CanonicalFontsMutex() { - // This initialization is only thread safe with gcc. - static SkMutex gCanonicalFontsMutex; +SkBaseMutex& SkPDFFont::CanonicalFontsMutex() { + // This initialization is only thread safe with gcc, or when + // POD-style mutex initialization is used. + SK_DECLARE_STATIC_MUTEX(gCanonicalFontsMutex); return gCanonicalFontsMutex; } diff --git a/src/pdf/SkPDFGraphicState.cpp b/src/pdf/SkPDFGraphicState.cpp index ad3f57b822..ec9b0e70b2 100644 --- a/src/pdf/SkPDFGraphicState.cpp +++ b/src/pdf/SkPDFGraphicState.cpp @@ -85,9 +85,10 @@ SkPDFGraphicState::CanonicalPaints() { } // static -SkMutex& SkPDFGraphicState::CanonicalPaintsMutex() { - // This initialization is only thread safe with gcc. - static SkMutex gCanonicalPaintsMutex; +SkBaseMutex& SkPDFGraphicState::CanonicalPaintsMutex() { + // This initialization is only thread safe with gcc or when + // POD-style mutex initialization is used. + SK_DECLARE_STATIC_MUTEX(gCanonicalPaintsMutex); return gCanonicalPaintsMutex; } diff --git a/src/pdf/SkPDFShader.cpp b/src/pdf/SkPDFShader.cpp index b6e09395a8..183a4ffb9a 100644 --- a/src/pdf/SkPDFShader.cpp +++ b/src/pdf/SkPDFShader.cpp @@ -391,9 +391,10 @@ SkTDArray& SkPDFShader::CanonicalShaders() { } // static -SkMutex& SkPDFShader::CanonicalShadersMutex() { - // This initialization is only thread safe with gcc. - static SkMutex gCanonicalShadersMutex; +SkBaseMutex& SkPDFShader::CanonicalShadersMutex() { + // This initialization is only thread safe with gcc or when + // POD-style mutex initialization is used. + SK_DECLARE_STATIC_MUTEX(gCanonicalShadersMutex); return gCanonicalShadersMutex; } diff --git a/src/ports/SkFontHost_FreeType.cpp b/src/ports/SkFontHost_FreeType.cpp index a58cd3702c..caca577ac7 100644 --- a/src/ports/SkFontHost_FreeType.cpp +++ b/src/ports/SkFontHost_FreeType.cpp @@ -88,7 +88,7 @@ static bool isLCD(const SkScalerContext::Rec& rec) { struct SkFaceRec; -static SkMutex gFTMutex; +SK_DECLARE_STATIC_MUTEX(gFTMutex); static int gFTCount; static FT_Library gFTLibrary; static SkFaceRec* gFaceRecHead; diff --git a/src/ports/SkFontHost_android.cpp b/src/ports/SkFontHost_android.cpp index 37c922c6c2..a3bd79c721 100644 --- a/src/ports/SkFontHost_android.cpp +++ b/src/ports/SkFontHost_android.cpp @@ -67,7 +67,7 @@ struct NameFamilyPair { static int32_t gUniqueFontID; // this is the mutex that protects these globals -static SkMutex gFamilyMutex; +SK_DECLARE_STATIC_MUTEX(gFamilyMutex); static FamilyRec* gFamilyHead; static SkTDArray gNameList; diff --git a/src/ports/SkFontHost_fontconfig.cpp b/src/ports/SkFontHost_fontconfig.cpp index acc5ae046e..454ded3d20 100644 --- a/src/ports/SkFontHost_fontconfig.cpp +++ b/src/ports/SkFontHost_fontconfig.cpp @@ -38,7 +38,7 @@ SkTypeface::Style find_name_and_style(SkStream* stream, SkString* name); // Although truetype fonts can support multiple faces in a single file, at the // moment Skia doesn't. // ----------------------------------------------------------------------------- -static SkMutex global_fc_map_lock; +SK_DECLARE_STATIC_MUTEX(global_fc_map_lock); static std::map global_fc_map; static std::map global_fc_map_inverted; static std::map global_fc_typefaces; diff --git a/src/ports/SkFontHost_linux.cpp b/src/ports/SkFontHost_linux.cpp index c87b03634e..fa1d2eca66 100644 --- a/src/ports/SkFontHost_linux.cpp +++ b/src/ports/SkFontHost_linux.cpp @@ -60,7 +60,7 @@ struct NameFamilyPair { static int32_t gUniqueFontID; // this is the mutex that protects these globals -static SkMutex gFamilyMutex; +SK_DECLARE_STATIC_MUTEX(gFamilyMutex); static FamilyRec* gFamilyHead; static SkTDArray gNameList; diff --git a/src/ports/SkFontHost_mac_atsui.cpp b/src/ports/SkFontHost_mac_atsui.cpp index b90757cf5c..ae3203668c 100644 --- a/src/ports/SkFontHost_mac_atsui.cpp +++ b/src/ports/SkFontHost_mac_atsui.cpp @@ -16,7 +16,7 @@ #include "SkPoint.h" const char* gDefaultfont = "Arial"; // hard code for now -static SkMutex gFTMutex; +SK_DECLARE_STATIC_MUTEX(gFTMutex); static inline SkPoint F32PtToSkPoint(const Float32Point p) { SkPoint sp = { SkFloatToScalar(p.x), SkFloatToScalar(p.y) }; diff --git a/src/ports/SkFontHost_mac_coretext.cpp b/src/ports/SkFontHost_mac_coretext.cpp index 3ba11a8c0a..9c69ed7043 100644 --- a/src/ports/SkFontHost_mac_coretext.cpp +++ b/src/ports/SkFontHost_mac_coretext.cpp @@ -450,7 +450,7 @@ static CTFontRef GetFontRefFromFontID(SkFontID fontID) { } static SkTypeface* GetDefaultFace() { - static SkMutex gMutex; + SK_DECLARE_STATIC_MUTEX(gMutex); SkAutoMutexAcquire ma(gMutex); static SkTypeface* gDefaultFace; diff --git a/src/ports/SkFontHost_simple.cpp b/src/ports/SkFontHost_simple.cpp index 0624d359a2..7a06b10d65 100644 --- a/src/ports/SkFontHost_simple.cpp +++ b/src/ports/SkFontHost_simple.cpp @@ -59,7 +59,7 @@ struct NameFamilyPair { static int32_t gUniqueFontID; // this is the mutex that protects these globals -static SkMutex gFamilyMutex; +SK_DECLARE_STATIC_MUTEX(gFamilyMutex); static FamilyRec* gFamilyHead; static SkTDArray gNameList; diff --git a/src/ports/SkFontHost_win.cpp b/src/ports/SkFontHost_win.cpp index 156f51cff2..e78bfbb222 100755 --- a/src/ports/SkFontHost_win.cpp +++ b/src/ports/SkFontHost_win.cpp @@ -448,7 +448,7 @@ static FIXED float2FIXED(float x) { return SkFixedToFIXED(SkFloatToFixed(x)); } -static SkMutex gFTMutex; +SK_DECLARE_STATIC_MUTEX(gFTMutex); #define HIRES_TEXTSIZE 2048 #define HIRES_SHIFT 11 diff --git a/src/ports/SkThread_pthread.cpp b/src/ports/SkThread_pthread.cpp index 638e522e3b..4750d4f2c4 100644 --- a/src/ports/SkThread_pthread.cpp +++ b/src/ports/SkThread_pthread.cpp @@ -55,7 +55,7 @@ int32_t sk_atomic_inc(int32_t* addr) int32_t sk_atomic_dec(int32_t* addr) { SkAutoMutexAcquire ac(gAtomicMutex); - + int32_t value = *addr; *addr = value - 1; return value; @@ -83,6 +83,30 @@ static void print_pthread_error(int status) { } } +#ifdef SK_USE_POSIX_THREADS + +SkMutex::SkMutex() { + int status; + + status = pthread_mutex_init(&fMutex, NULL); + if (status != 0) { + print_pthread_error(status); + SkASSERT(0 == status); + } +} + +SkMutex::~SkMutex() { + int status = pthread_mutex_destroy(&fMutex); + + // only report errors on non-global mutexes + if (status != 0) { + print_pthread_error(status); + SkASSERT(0 == status); + } +} + +#else // !SK_USE_POSIX_THREADS + SkMutex::SkMutex() { if (sizeof(pthread_mutex_t) > sizeof(fStorage)) { SkDEBUGF(("pthread mutex size = %d\n", sizeof(pthread_mutex_t))); @@ -124,3 +148,4 @@ void SkMutex::release() { SkASSERT(0 == status); } +#endif // !SK_USE_POSIX_THREADS diff --git a/src/views/SkEventSink.cpp b/src/views/SkEventSink.cpp index 0b01669a61..20d8cdfc5b 100644 --- a/src/views/SkEventSink.cpp +++ b/src/views/SkEventSink.cpp @@ -260,7 +260,7 @@ SkEventSink* SkEventSink::FindSink(SkEventSinkID sinkID) #include "SkTDict.h" #define kMinStringBufferSize 128 -static SkMutex gNamedSinkMutex; +SK_DECLARE_STATIC_MUTEX(gNamedSinkMutex); static SkTDict gNamedSinkIDs(kMinStringBufferSize); /** Register a name/id pair with the system. If the name already exists,