Add assertHeld() to SkMutex.

BUG=skia:
R=bungeman@google.com, mtklein@google.com, reed@google.com

Author: mtklein@chromium.org

Review URL: https://codereview.chromium.org/313823004
This commit is contained in:
mtklein 2014-06-09 14:18:02 -07:00 committed by Commit bot
parent 919ed4c736
commit b83f6c3cbd
7 changed files with 64 additions and 43 deletions

View File

@ -83,8 +83,9 @@ template <typename T> void sk_release_store(T*, T);
class SkBaseMutex {
public:
void acquire();
void release();
void acquire(); // Block until this thread owns the mutex.
void release(); // Assuming this thread owns the mutex, release it.
void assertHeld(); // If SK_DEBUG, assert this thread owns the mutex.
};
class SkMutex : SkBaseMutex {
@ -128,6 +129,12 @@ public:
}
}
/** Assert that we're holding the mutex. */
void assertHeld() {
SkASSERT(fMutex);
fMutex->assertHeld();
}
private:
SkBaseMutex* fMutex;
};

View File

@ -1737,6 +1737,7 @@ static SkScalar gDeviceGamma = SK_ScalarMin;
* the returned SkMaskGamma pointer is refed or forgotten.
*/
static const SkMaskGamma& cachedMaskGamma(SkScalar contrast, SkScalar paintGamma, SkScalar deviceGamma) {
gMaskGammaCacheMutex.assertHeld();
if (0 == contrast && SK_Scalar1 == paintGamma && SK_Scalar1 == deviceGamma) {
if (NULL == gLinearMaskGamma) {
gLinearMaskGamma = SkNEW(SkMaskGamma);

View File

@ -13,25 +13,25 @@
#ifdef SK_USE_POSIX_THREADS
static SkBaseMutex gPixelRefMutexRing[] = {
{ PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER },
{ PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER },
{ PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER },
{ PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER },
SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT,
SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT,
SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT,
SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT,
{ PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER },
{ PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER },
{ PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER },
{ PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER },
SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT,
SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT,
SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT,
SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT,
{ PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER },
{ PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER },
{ PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER },
{ PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER },
SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT,
SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT,
SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT,
SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT,
{ PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER },
{ PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER },
{ PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER },
{ PTHREAD_MUTEX_INITIALIZER }, { PTHREAD_MUTEX_INITIALIZER },
SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT,
SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT,
SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT,
SK_BASE_MUTEX_INIT, SK_BASE_MUTEX_INIT,
};
// must be a power-of-2. undef to just use 1 mutex

View File

@ -675,6 +675,7 @@ static void cleanup_gScaledImageCache() { SkDELETE(gScaledImageCache); }
/** Must hold gMutex when calling. */
static SkScaledImageCache* get_cache() {
// gMutex is always held when this is called, so we don't need to be fancy in here.
gMutex.assertHeld();
if (NULL == gScaledImageCache) {
#ifdef SK_USE_DISCARDABLE_SCALEDIMAGECACHE
gScaledImageCache = SkNEW_ARGS(SkScaledImageCache, (SkDiscardableMemory::Create));

View File

@ -82,24 +82,20 @@ size_t SkPDFGraphicState::getOutputSize(SkPDFCatalog* catalog, bool indirect) {
}
// static
SkTDArray<SkPDFGraphicState::GSCanonicalEntry>&
SkPDFGraphicState::CanonicalPaints() {
// This initialization is only thread safe with gcc.
SkTDArray<SkPDFGraphicState::GSCanonicalEntry>& SkPDFGraphicState::CanonicalPaints() {
CanonicalPaintsMutex().assertHeld();
static SkTDArray<SkPDFGraphicState::GSCanonicalEntry> gCanonicalPaints;
return gCanonicalPaints;
}
// static
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;
}
// static
SkPDFGraphicState* SkPDFGraphicState::GetGraphicStateForPaint(
const SkPaint& paint) {
SkPDFGraphicState* SkPDFGraphicState::GetGraphicStateForPaint(const SkPaint& paint) {
SkAutoMutexAcquire lock(CanonicalPaintsMutex());
int index = Find(paint);
if (index >= 0) {
@ -114,6 +110,7 @@ SkPDFGraphicState* SkPDFGraphicState::GetGraphicStateForPaint(
// static
SkPDFObject* SkPDFGraphicState::GetInvertFunction() {
// This assumes that canonicalPaintsMutex is held.
CanonicalPaintsMutex().assertHeld();
static SkPDFStream* invertFunction = NULL;
if (!invertFunction) {
// Acrobat crashes if we use a type 0 function, kpdf crashes if we use
@ -185,6 +182,7 @@ SkPDFGraphicState* SkPDFGraphicState::GetNoSMaskGraphicState() {
// static
int SkPDFGraphicState::Find(const SkPaint& paint) {
CanonicalPaintsMutex().assertHeld();
GSCanonicalEntry search(&paint);
return CanonicalPaints().find(search);
}

View File

@ -10,16 +10,6 @@
/** Posix pthread_mutex based mutex. */
#ifdef SK_DEBUG_PTHREAD_MUTEX
#include "SkTypes.h"
#define SkDEBUGCODE_PTHREAD_MUTEX(code) code
#else
#define SkDEBUGCODE_PTHREAD_MUTEX(code)
#ifndef SkDebugf
void SkDebugf(const char format[], ...);
#endif
#endif
#include <errno.h>
#include <pthread.h>
@ -28,9 +18,21 @@
// 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); }
void acquire() {
pthread_mutex_lock(&fMutex);
SkDEBUGCODE(fOwner = pthread_self();)
}
void release() {
this->assertHeld();
SkDEBUGCODE(fOwner = 0;)
pthread_mutex_unlock(&fMutex);
}
void assertHeld() {
SkASSERT(pthread_self() == fOwner);
}
pthread_mutex_t fMutex;
SkDEBUGCODE(pthread_t fOwner;)
};
// A normal mutex that requires to be initialized through normal C++ construction,
@ -38,8 +40,8 @@ struct SkBaseMutex {
class SkMutex : public SkBaseMutex {
public:
SkMutex() {
SkDEBUGCODE_PTHREAD_MUTEX(int status = )pthread_mutex_init(&fMutex, NULL);
SkDEBUGCODE_PTHREAD_MUTEX(
SkDEBUGCODE(int status = )pthread_mutex_init(&fMutex, NULL);
SkDEBUGCODE(
if (status != 0) {
print_pthread_error(status);
SkASSERT(0 == status);
@ -48,8 +50,8 @@ public:
}
~SkMutex() {
SkDEBUGCODE_PTHREAD_MUTEX(int status = )pthread_mutex_destroy(&fMutex);
SkDEBUGCODE_PTHREAD_MUTEX(
SkDEBUGCODE(int status = )pthread_mutex_destroy(&fMutex);
SkDEBUGCODE(
if (status != 0) {
print_pthread_error(status);
SkASSERT(0 == status);
@ -78,10 +80,12 @@ private:
}
};
#define SK_BASE_MUTEX_INIT { PTHREAD_MUTEX_INITIALIZER, SkDEBUGCODE(0) }
// Using POD-style initialization prevents the generation of a static initializer.
#define SK_DECLARE_STATIC_MUTEX(name) static SkBaseMutex name = { PTHREAD_MUTEX_INITIALIZER }
#define SK_DECLARE_STATIC_MUTEX(name) static SkBaseMutex name = SK_BASE_MUTEX_INIT
// Special case used when the static mutex must be available globally.
#define SK_DECLARE_GLOBAL_MUTEX(name) SkBaseMutex name = { PTHREAD_MUTEX_INITIALIZER }
#define SK_DECLARE_GLOBAL_MUTEX(name) SkBaseMutex name = SK_BASE_MUTEX_INIT
#endif

View File

@ -36,25 +36,35 @@ class SkMutex {
public:
SkMutex() {
InitializeCriticalSection(&fStorage);
SkDEBUGCODE(fOwner = 0;)
}
~SkMutex() {
SkASSERT(0 == fOwner);
DeleteCriticalSection(&fStorage);
}
void acquire() {
EnterCriticalSection(&fStorage);
SkDEBUGCODE(fOwner = GetCurrentThreadId();)
}
void release() {
this->assertHeld();
SkDEBUGCODE(fOwner = 0;)
LeaveCriticalSection(&fStorage);
}
void assertHeld() {
SkASSERT(GetCurrentThreadId() == fOwner);
}
private:
SkMutex(const SkMutex&);
SkMutex& operator=(const SkMutex&);
CRITICAL_SECTION fStorage;
SkDEBUGCODE(DWORD fOwner;)
};
typedef SkMutex SkBaseMutex;