Remove all global mutexes

Remove the SkBaseMutex (and SkBaseSemaphore). This allows all the thread
annotation machinery to work.

Change-Id: I2da420ec3165ccbcd90c474c0b62bfef42df2a53
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/221340
Commit-Queue: Herb Derby <herb@google.com>
Reviewed-by: Mike Klein <mtklein@google.com>
This commit is contained in:
Herb Derby 2019-06-17 14:40:42 -04:00 committed by Skia Commit-Bot
parent 17a9655db2
commit 9c71e7be10
16 changed files with 128 additions and 169 deletions

View File

@ -18,7 +18,6 @@
#include "include/ports/SkTypeface_win.h"
#include "include/private/SkChecksum.h"
#include "include/private/SkHalf.h"
#include "include/private/SkMutex.h"
#include "include/private/SkSpinlock.h"
#include "include/private/SkTHash.h"
#include "src/core/SkColorSpacePriv.h"
@ -182,11 +181,11 @@ static void info(const char* fmt) {
}
}
SK_DECLARE_STATIC_MUTEX(gFailuresMutex);
static SkTArray<SkString> gFailures;
static void fail(const SkString& err) {
SkAutoMutexAcquire lock(gFailuresMutex);
static SkSpinlock mutex;
SkAutoSpinlock lock(mutex);
SkDebugf("\n\nFAILURE: %s\n\n", err.c_str());
gFailures.push_back(err);
}

View File

@ -20,10 +20,14 @@
namespace DM {
SkTArray<JsonWriter::BitmapResult> gBitmapResults;
SK_DECLARE_STATIC_MUTEX(gBitmapResultLock);
static SkMutex& bitmap_result_mutex() {
static SkMutex& mutex = *(new SkMutex);
return mutex;
}
void JsonWriter::AddBitmapResult(const BitmapResult& result) {
SkAutoMutexAcquire lock(&gBitmapResultLock);
SkAutoMutexExclusive lock(bitmap_result_mutex());
gBitmapResults.push_back(result);
}
@ -57,7 +61,7 @@ void JsonWriter::DumpJson(const char* dir,
}
{
SkAutoMutexAcquire lock(&gBitmapResultLock);
SkAutoMutexExclusive lock(bitmap_result_mutex());
writer.beginArray("results");
for (int i = 0; i < gBitmapResults.count(); i++) {
writer.beginObject();

View File

@ -14,32 +14,6 @@
#include "include/private/SkThreadAnnotations.h"
#include "include/private/SkThreadID.h"
#define SK_DECLARE_STATIC_MUTEX(name) static SkBaseMutex name;
class SkBaseMutex {
public:
constexpr SkBaseMutex() = default;
void acquire() {
fSemaphore.wait();
SkDEBUGCODE(fOwner = SkGetThreadID();)
}
void release() {
this->assertHeld();
SkDEBUGCODE(fOwner = kIllegalThreadID;)
fSemaphore.signal();
}
void assertHeld() {
SkASSERT(fOwner == SkGetThreadID());
}
protected:
SkBaseSemaphore fSemaphore{1};
SkDEBUGCODE(SkThreadID fOwner{kIllegalThreadID};)
};
class SK_CAPABILITY("mutex") SkMutex {
public:
constexpr SkMutex() = default;
@ -64,34 +38,6 @@ private:
SkDEBUGCODE(SkThreadID fOwner{kIllegalThreadID};)
};
class SkAutoMutexAcquire {
public:
template <typename T>
SkAutoMutexAcquire(T* mutex) : fMutex(mutex) {
if (mutex) {
mutex->acquire();
}
fRelease = [](void* mutex) { ((T*)mutex)->release(); };
}
template <typename T>
SkAutoMutexAcquire(T& mutex) : SkAutoMutexAcquire(&mutex) {}
~SkAutoMutexAcquire() { this->release(); }
void release() {
if (fMutex) {
fRelease(fMutex);
}
fMutex = nullptr;
}
private:
void* fMutex;
void (*fRelease)(void*);
};
#define SkAutoMutexAcquire(...) SK_REQUIRE_LOCAL_VAR(SkAutoMutexAcquire)
class SK_SCOPED_CAPABILITY SkAutoMutexExclusive {
public:
SkAutoMutexExclusive(SkMutex& mutex) SK_ACQUIRE(mutex) : fMutex(mutex) { fMutex.acquire(); }
@ -103,4 +49,4 @@ private:
#define SkAutoMutexExclusive(...) SK_REQUIRE_LOCAL_VAR(SkAutoMutexExclusive)
#endif//SkMutex_DEFINED
#endif // SkMutex_DEFINED

View File

@ -12,10 +12,12 @@
#include "include/private/SkOnce.h"
#include <atomic>
class SkBaseSemaphore {
class SkSemaphore {
public:
constexpr SkBaseSemaphore(int count = 0)
: fCount(count), fOSSemaphore(nullptr) {}
constexpr SkSemaphore(int count = 0) : fCount(count), fOSSemaphore(nullptr) {}
// Cleanup the underlying OS semaphore.
~SkSemaphore();
// Increment the counter n times.
// Generally it's better to call signal(n) instead of signal() n times.
@ -28,9 +30,6 @@ public:
// If the counter is positive, decrement it by 1 and return true, otherwise return false.
bool try_wait();
// SkBaseSemaphore has no destructor. Call this to clean it up.
void cleanup();
private:
// This implementation follows the general strategy of
// 'A Lightweight Semaphore with Partial Spinning'
@ -51,13 +50,7 @@ private:
OSSemaphore* fOSSemaphore;
};
class SkSemaphore : public SkBaseSemaphore {
public:
using SkBaseSemaphore::SkBaseSemaphore;
~SkSemaphore() { this->cleanup(); }
};
inline void SkBaseSemaphore::signal(int n) {
inline void SkSemaphore::signal(int n) {
int prev = fCount.fetch_add(n, std::memory_order_release);
// We only want to call the OS semaphore when our logical count crosses
@ -75,7 +68,7 @@ inline void SkBaseSemaphore::signal(int n) {
}
}
inline void SkBaseSemaphore::wait() {
inline void SkSemaphore::wait() {
// Since this fetches the value before the subtract, zero and below means that there are no
// resources left, so the thread needs to wait.
if (fCount.fetch_sub(1, std::memory_order_acquire) <= 0) {

View File

@ -449,13 +449,16 @@ void SkResourceCache::checkMessages() {
///////////////////////////////////////////////////////////////////////////////
SK_DECLARE_STATIC_MUTEX(gMutex);
static SkResourceCache* gResourceCache = nullptr;
static SkMutex& resource_cache_mutex() {
static SkMutex& mutex = *(new SkMutex);
return mutex;
}
/** Must hold gMutex when calling. */
/** Must hold resource_cache_mutex() when calling. */
static SkResourceCache* get_cache() {
// gMutex is always held when this is called, so we don't need to be fancy in here.
gMutex.assertHeld();
// resource_cache_mutex() is always held when this is called, so we don't need to be fancy in here.
resource_cache_mutex().assertHeld();
if (nullptr == gResourceCache) {
#ifdef SK_USE_DISCARDABLE_SCALEDIMAGECACHE
gResourceCache = new SkResourceCache(SkDiscardableMemory::Create);
@ -467,67 +470,67 @@ static SkResourceCache* get_cache() {
}
size_t SkResourceCache::GetTotalBytesUsed() {
SkAutoMutexAcquire am(gMutex);
SkAutoMutexExclusive am(resource_cache_mutex());
return get_cache()->getTotalBytesUsed();
}
size_t SkResourceCache::GetTotalByteLimit() {
SkAutoMutexAcquire am(gMutex);
SkAutoMutexExclusive am(resource_cache_mutex());
return get_cache()->getTotalByteLimit();
}
size_t SkResourceCache::SetTotalByteLimit(size_t newLimit) {
SkAutoMutexAcquire am(gMutex);
SkAutoMutexExclusive am(resource_cache_mutex());
return get_cache()->setTotalByteLimit(newLimit);
}
SkResourceCache::DiscardableFactory SkResourceCache::GetDiscardableFactory() {
SkAutoMutexAcquire am(gMutex);
SkAutoMutexExclusive am(resource_cache_mutex());
return get_cache()->discardableFactory();
}
SkCachedData* SkResourceCache::NewCachedData(size_t bytes) {
SkAutoMutexAcquire am(gMutex);
SkAutoMutexExclusive am(resource_cache_mutex());
return get_cache()->newCachedData(bytes);
}
void SkResourceCache::Dump() {
SkAutoMutexAcquire am(gMutex);
SkAutoMutexExclusive am(resource_cache_mutex());
get_cache()->dump();
}
size_t SkResourceCache::SetSingleAllocationByteLimit(size_t size) {
SkAutoMutexAcquire am(gMutex);
SkAutoMutexExclusive am(resource_cache_mutex());
return get_cache()->setSingleAllocationByteLimit(size);
}
size_t SkResourceCache::GetSingleAllocationByteLimit() {
SkAutoMutexAcquire am(gMutex);
SkAutoMutexExclusive am(resource_cache_mutex());
return get_cache()->getSingleAllocationByteLimit();
}
size_t SkResourceCache::GetEffectiveSingleAllocationByteLimit() {
SkAutoMutexAcquire am(gMutex);
SkAutoMutexExclusive am(resource_cache_mutex());
return get_cache()->getEffectiveSingleAllocationByteLimit();
}
void SkResourceCache::PurgeAll() {
SkAutoMutexAcquire am(gMutex);
SkAutoMutexExclusive am(resource_cache_mutex());
return get_cache()->purgeAll();
}
bool SkResourceCache::Find(const Key& key, FindVisitor visitor, void* context) {
SkAutoMutexAcquire am(gMutex);
SkAutoMutexExclusive am(resource_cache_mutex());
return get_cache()->find(key, visitor, context);
}
void SkResourceCache::Add(Rec* rec, void* payload) {
SkAutoMutexAcquire am(gMutex);
SkAutoMutexExclusive am(resource_cache_mutex());
get_cache()->add(rec, payload);
}
void SkResourceCache::VisitAll(Visitor visitor, void* context) {
SkAutoMutexAcquire am(gMutex);
SkAutoMutexExclusive am(resource_cache_mutex());
get_cache()->visitAll(visitor, context);
}

View File

@ -95,10 +95,13 @@ SkScalerContext::~SkScalerContext() {}
/**
* In order to call cachedDeviceLuminance, cachedPaintLuminance, or
* cachedMaskGamma the caller must hold the gMaskGammaCacheMutex and continue
* cachedMaskGamma the caller must hold the mask_gamma_cache_mutex and continue
* to hold it until the returned pointer is refed or forgotten.
*/
SK_DECLARE_STATIC_MUTEX(gMaskGammaCacheMutex);
static SkMutex& mask_gamma_cache_mutex() {
static SkMutex& mutex = *(new SkMutex);
return mutex;
}
static SkMaskGamma* gLinearMaskGamma = nullptr;
static SkMaskGamma* gMaskGamma = nullptr;
@ -107,12 +110,12 @@ static SkScalar gPaintGamma = SK_ScalarMin;
static SkScalar gDeviceGamma = SK_ScalarMin;
/**
* The caller must hold the gMaskGammaCacheMutex and continue to hold it until
* The caller must hold the mask_gamma_cache_mutex() and continue to hold it until
* the returned SkMaskGamma pointer is refed or forgotten.
*/
static const SkMaskGamma& cached_mask_gamma(SkScalar contrast, SkScalar paintGamma,
SkScalar deviceGamma) {
gMaskGammaCacheMutex.assertHeld();
mask_gamma_cache_mutex().assertHeld();
if (0 == contrast && SK_Scalar1 == paintGamma && SK_Scalar1 == deviceGamma) {
if (nullptr == gLinearMaskGamma) {
gLinearMaskGamma = new SkMaskGamma;
@ -133,7 +136,7 @@ static const SkMaskGamma& cached_mask_gamma(SkScalar contrast, SkScalar paintGam
* Expands fDeviceGamma, fPaintGamma, fContrast, and fLumBits into a mask pre-blend.
*/
SkMaskGamma::PreBlend SkScalerContext::GetMaskPreBlend(const SkScalerContextRec& rec) {
SkAutoMutexAcquire ama(gMaskGammaCacheMutex);
SkAutoMutexExclusive ama(mask_gamma_cache_mutex());
const SkMaskGamma& maskGamma = cached_mask_gamma(rec.getContrast(),
rec.getPaintGamma(),
@ -145,7 +148,7 @@ SkMaskGamma::PreBlend SkScalerContext::GetMaskPreBlend(const SkScalerContextRec&
size_t SkScalerContext::GetGammaLUTSize(SkScalar contrast, SkScalar paintGamma,
SkScalar deviceGamma, int* width, int* height) {
SkAutoMutexAcquire ama(gMaskGammaCacheMutex);
SkAutoMutexExclusive ama(mask_gamma_cache_mutex());
const SkMaskGamma& maskGamma = cached_mask_gamma(contrast,
paintGamma,
deviceGamma);
@ -158,7 +161,7 @@ size_t SkScalerContext::GetGammaLUTSize(SkScalar contrast, SkScalar paintGamma,
bool SkScalerContext::GetGammaLUTData(SkScalar contrast, SkScalar paintGamma, SkScalar deviceGamma,
uint8_t* data) {
SkAutoMutexAcquire ama(gMaskGammaCacheMutex);
SkAutoMutexExclusive ama(mask_gamma_cache_mutex());
const SkMaskGamma& maskGamma = cached_mask_gamma(contrast,
paintGamma,
deviceGamma);

View File

@ -11,7 +11,7 @@
#if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
#include <mach/mach.h>
// We've got to teach TSAN that there is a happens-before edge beteween
// We've got to teach TSAN that there is a happens-before edge between
// semaphore_signal() and semaphore_wait().
#if __has_feature(thread_sanitizer)
extern "C" void AnnotateHappensBefore(const char*, int, void*);
@ -21,7 +21,7 @@
static void AnnotateHappensAfter (const char*, int, void*) {}
#endif
struct SkBaseSemaphore::OSSemaphore {
struct SkSemaphore::OSSemaphore {
semaphore_t fSemaphore;
OSSemaphore() {
@ -41,7 +41,7 @@
}
};
#elif defined(SK_BUILD_FOR_WIN)
struct SkBaseSemaphore::OSSemaphore {
struct SkSemaphore::OSSemaphore {
HANDLE fSemaphore;
OSSemaphore() {
@ -61,7 +61,7 @@
// It's important we test for Mach before this. This code will compile but not work there.
#include <errno.h>
#include <semaphore.h>
struct SkBaseSemaphore::OSSemaphore {
struct SkSemaphore::OSSemaphore {
sem_t fSemaphore;
OSSemaphore() { sem_init(&fSemaphore, 0/*cross process?*/, 0/*initial count*/); }
@ -77,21 +77,21 @@
///////////////////////////////////////////////////////////////////////////////
void SkBaseSemaphore::osSignal(int n) {
SkSemaphore::~SkSemaphore() {
delete fOSSemaphore;
}
void SkSemaphore::osSignal(int n) {
fOSSemaphoreOnce([this] { fOSSemaphore = new OSSemaphore; });
fOSSemaphore->signal(n);
}
void SkBaseSemaphore::osWait() {
void SkSemaphore::osWait() {
fOSSemaphoreOnce([this] { fOSSemaphore = new OSSemaphore; });
fOSSemaphore->wait();
}
void SkBaseSemaphore::cleanup() {
delete fOSSemaphore;
}
bool SkBaseSemaphore::try_wait() {
bool SkSemaphore::try_wait() {
int count = fCount.load(std::memory_order_relaxed);
if (count > 0) {
return fCount.compare_exchange_weak(count, count-1, std::memory_order_acquire);

View File

@ -62,20 +62,23 @@ SkFontID SkTypefaceCache::NewFontID() {
return nextID++;
}
SK_DECLARE_STATIC_MUTEX(gMutex);
static SkMutex& typeface_cache_mutex() {
static SkMutex& mutex = *(new SkMutex);
return mutex;
}
void SkTypefaceCache::Add(sk_sp<SkTypeface> face) {
SkAutoMutexAcquire ama(gMutex);
SkAutoMutexExclusive ama(typeface_cache_mutex());
Get().add(std::move(face));
}
sk_sp<SkTypeface> SkTypefaceCache::FindByProcAndRef(FindProc proc, void* ctx) {
SkAutoMutexAcquire ama(gMutex);
SkAutoMutexExclusive ama(typeface_cache_mutex());
return Get().findByProcAndRef(proc, ctx);
}
void SkTypefaceCache::PurgeAll() {
SkAutoMutexAcquire ama(gMutex);
SkAutoMutexExclusive ama(typeface_cache_mutex());
Get().purgeAll();
}

View File

@ -557,11 +557,11 @@ static void show_op(SkPathOp op, const char* pathOne, const char* pathTwo) {
SkDebugf("}\n");
}
SK_DECLARE_STATIC_MUTEX(gTestMutex);
void SkPathOpsDebug::ShowPath(const SkPath& a, const SkPath& b, SkPathOp shapeOp,
const char* testName) {
SkAutoMutexAcquire ac(gTestMutex);
static SkMutex& mutex = *(new SkMutex);
SkAutoMutexExclusive ac(mutex);
show_function_header(testName);
ShowOnePath(a, "path", true);
ShowOnePath(b, "pathB", true);
@ -574,10 +574,9 @@ void SkPathOpsDebug::ShowPath(const SkPath& a, const SkPath& b, SkPathOp shapeOp
#if DEBUG_COIN
SK_DECLARE_STATIC_MUTEX(gCoinDictMutex);
void SkOpGlobalState::debugAddToGlobalCoinDicts() {
SkAutoMutexAcquire ac(&gCoinDictMutex);
static SkMutex& mutex = *(new SkMutex);
SkAutoMutexExclusive ac(mutex);
SkPathOpsDebug::gCoinSumChangedDict.add(fCoinChangedDict);
SkPathOpsDebug::gCoinSumVisitedDict.add(fCoinVisitedDict);
}

View File

@ -226,8 +226,6 @@ static const bool gOutInverse[kReverseDifference_SkPathOp + 1][2][2] = {
#include "include/private/SkMutex.h"
SK_DECLARE_STATIC_MUTEX(debugWorstLoop);
SkOpGlobalState debugWorstState(nullptr, nullptr SkDEBUGPARAMS(false) SkDEBUGPARAMS(nullptr));
void ReportPathOpsDebugging() {
@ -357,8 +355,9 @@ bool OpDebug(const SkPath& one, const SkPath& two, SkPathOp op, SkPath* result
}
wrapper.assemble(); // if some edges could not be resolved, assemble remaining
#if DEBUG_T_SECT_LOOP_COUNT
static SkMutex& debugWorstLoop = *(new SkMutex);
{
SkAutoMutexAcquire autoM(debugWorstLoop);
SkAutoMutexExclusive autoM(debugWorstLoop);
if (!gVerboseFinalize) {
gVerboseFinalize = &ReportPathOpsDebugging;
}

View File

@ -10,11 +10,14 @@
#include "include/ports/SkFontConfigInterface.h"
#include "include/private/SkMutex.h"
SK_DECLARE_STATIC_MUTEX(gFontConfigInterfaceMutex);
static SkMutex& font_config_interface_mutex() {
static SkMutex& mutex = *(new SkMutex);
return mutex;
}
static SkFontConfigInterface* gFontConfigInterface;
sk_sp<SkFontConfigInterface> SkFontConfigInterface::RefGlobal() {
SkAutoMutexAcquire ac(gFontConfigInterfaceMutex);
SkAutoMutexExclusive ac(font_config_interface_mutex());
if (gFontConfigInterface) {
return sk_ref_sp(gFontConfigInterface);
@ -23,7 +26,7 @@ sk_sp<SkFontConfigInterface> SkFontConfigInterface::RefGlobal() {
}
void SkFontConfigInterface::SetGlobal(sk_sp<SkFontConfigInterface> fc) {
SkAutoMutexAcquire ac(gFontConfigInterfaceMutex);
SkAutoMutexExclusive ac(font_config_interface_mutex());
SkSafeUnref(gFontConfigInterface);
gFontConfigInterface = fc.release();

View File

@ -31,7 +31,10 @@ namespace {
// Fontconfig is not threadsafe before 2.10.91. Before that, we lock with a global mutex.
// See https://bug.skia.org/1497 for background.
SK_DECLARE_STATIC_MUTEX(gFCMutex);
static SkMutex& f_c_mutex() {
static SkMutex& mutex = *(new SkMutex);
return mutex;
}
#ifdef SK_DEBUG
void* CreateThreadFcLocked() { return new bool(false); }
@ -45,7 +48,7 @@ struct FCLocker {
FCLocker() {
if (FcGetVersion() < 21091) {
gFCMutex.acquire();
f_c_mutex().acquire();
} else {
SkDEBUGCODE(bool* threadLocked = THREAD_FC_LOCKED);
SkASSERT(false == *threadLocked);
@ -56,7 +59,7 @@ struct FCLocker {
~FCLocker() {
AssertHeld();
if (FcGetVersion() < 21091) {
gFCMutex.release();
f_c_mutex().release();
} else {
SkDEBUGCODE(*THREAD_FC_LOCKED = false);
}
@ -64,7 +67,7 @@ struct FCLocker {
static void AssertHeld() { SkDEBUGCODE(
if (FcGetVersion() < 21091) {
gFCMutex.assertHeld();
f_c_mutex().assertHeld();
} else {
SkASSERT(true == *THREAD_FC_LOCKED);
}

View File

@ -254,16 +254,20 @@ private:
struct SkFaceRec;
SK_DECLARE_STATIC_MUTEX(gFTMutex);
static SkMutex& f_t_mutex() {
static SkMutex& mutex = *(new SkMutex);
return mutex;
}
static FreeTypeLibrary* gFTLibrary;
static SkFaceRec* gFaceRecHead;
// Private to ref_ft_library and unref_ft_library
static int gFTCount;
// Caller must lock gFTMutex before calling this function.
// Caller must lock f_t_mutex() before calling this function.
static bool ref_ft_library() {
gFTMutex.assertHeld();
f_t_mutex().assertHeld();
SkASSERT(gFTCount >= 0);
if (0 == gFTCount) {
@ -274,9 +278,9 @@ static bool ref_ft_library() {
return gFTLibrary->library();
}
// Caller must lock gFTMutex before calling this function.
// Caller must lock f_t_mutex() before calling this function.
static void unref_ft_library() {
gFTMutex.assertHeld();
f_t_mutex().assertHeld();
SkASSERT(gFTCount > 0);
--gFTCount;
@ -387,9 +391,9 @@ static void ft_face_setup_axes(SkFaceRec* rec, const SkFontData& data) {
}
// Will return nullptr on failure
// Caller must lock gFTMutex before calling this function.
// Caller must lock f_t_mutex() before calling this function.
static SkFaceRec* ref_ft_face(const SkTypeface* typeface) {
gFTMutex.assertHeld();
f_t_mutex().assertHeld();
const SkFontID fontID = typeface->uniqueID();
SkFaceRec* cachedRec = gFaceRecHead;
@ -449,10 +453,10 @@ static SkFaceRec* ref_ft_face(const SkTypeface* typeface) {
return rec.release();
}
// Caller must lock gFTMutex before calling this function.
// Caller must lock f_t_mutex() before calling this function.
// Marked extern because vc++ does not support internal linkage template parameters.
extern /*static*/ void unref_ft_face(SkFaceRec* faceRec) {
gFTMutex.assertHeld();
f_t_mutex().assertHeld();
SkFaceRec* rec = gFaceRecHead;
SkFaceRec* prev = nullptr;
@ -478,7 +482,7 @@ extern /*static*/ void unref_ft_face(SkFaceRec* faceRec) {
class AutoFTAccess {
public:
AutoFTAccess(const SkTypeface* tf) : fFaceRec(nullptr) {
gFTMutex.acquire();
f_t_mutex().acquire();
SkASSERT_RELEASE(ref_ft_library());
fFaceRec = ref_ft_face(tf);
}
@ -488,7 +492,7 @@ public:
unref_ft_face(fFaceRec);
}
unref_ft_library();
gFTMutex.release();
f_t_mutex().release();
}
FT_Face face() { return fFaceRec ? fFaceRec->fFace.get() : nullptr; }
@ -549,9 +553,9 @@ private:
void getBBoxForCurrentGlyph(const SkGlyph* glyph, FT_BBox* bbox,
bool snapToPixelBoundary = false);
bool getCBoxForLetter(char letter, FT_BBox* bbox);
// Caller must lock gFTMutex before calling this function.
// Caller must lock f_t_mutex() before calling this function.
void updateGlyphIfLCD(SkGlyph* glyph);
// Caller must lock gFTMutex before calling this function.
// Caller must lock f_t_mutex() before calling this function.
// update FreeType2 glyph slot with glyph emboldened
void emboldenIfNeeded(FT_Face face, FT_GlyphSlot glyph, SkGlyphID gid);
bool shouldSubpixelBitmap(const SkGlyph&, const SkMatrix&);
@ -733,7 +737,7 @@ void SkTypeface_FreeType::onFilterRec(SkScalerContextRec* rec) const {
if (isLCD(*rec)) {
// TODO: re-work so that FreeType is set-up and selected by the SkFontMgr.
SkAutoMutexAcquire ama(gFTMutex);
SkAutoMutexExclusive ama(f_t_mutex());
ref_ft_library();
if (!gFTLibrary->isLCDSupported()) {
// If the runtime Freetype library doesn't support LCD, disable it here.
@ -844,7 +848,7 @@ SkScalerContext_FreeType::SkScalerContext_FreeType(sk_sp<SkTypeface> typeface,
, fFTSize(nullptr)
, fStrikeIndex(-1)
{
SkAutoMutexAcquire ac(gFTMutex);
SkAutoMutexExclusive ac(f_t_mutex());
SkASSERT_RELEASE(ref_ft_library());
fFaceRec.reset(ref_ft_face(this->getTypeface()));
@ -1022,7 +1026,7 @@ SkScalerContext_FreeType::SkScalerContext_FreeType(sk_sp<SkTypeface> typeface,
}
SkScalerContext_FreeType::~SkScalerContext_FreeType() {
SkAutoMutexAcquire ac(gFTMutex);
SkAutoMutexExclusive ac(f_t_mutex());
if (fFTSize != nullptr) {
FT_Done_Size(fFTSize);
@ -1037,7 +1041,7 @@ SkScalerContext_FreeType::~SkScalerContext_FreeType() {
this face with other context (at different sizes).
*/
FT_Error SkScalerContext_FreeType::setupSize() {
gFTMutex.assertHeld();
f_t_mutex().assertHeld();
FT_Error err = FT_Activate_Size(fFTSize);
if (err != 0) {
return err;
@ -1058,7 +1062,7 @@ bool SkScalerContext_FreeType::generateAdvance(SkGlyph* glyph) {
return false;
}
SkAutoMutexAcquire ac(gFTMutex);
SkAutoMutexExclusive ac(f_t_mutex());
if (this->setupSize()) {
glyph->zeroMetrics();
@ -1163,7 +1167,7 @@ bool SkScalerContext_FreeType::shouldSubpixelBitmap(const SkGlyph& glyph, const
}
void SkScalerContext_FreeType::generateMetrics(SkGlyph* glyph) {
SkAutoMutexAcquire ac(gFTMutex);
SkAutoMutexExclusive ac(f_t_mutex());
glyph->fMaskFormat = fRec.fMaskFormat;
@ -1319,7 +1323,7 @@ static void clear_glyph_image(const SkGlyph& glyph) {
}
void SkScalerContext_FreeType::generateImage(const SkGlyph& glyph) {
SkAutoMutexAcquire ac(gFTMutex);
SkAutoMutexExclusive ac(f_t_mutex());
if (this->setupSize()) {
clear_glyph_image(glyph);
@ -1352,7 +1356,7 @@ void SkScalerContext_FreeType::generateImage(const SkGlyph& glyph) {
bool SkScalerContext_FreeType::generatePath(SkGlyphID glyphID, SkPath* path) {
SkASSERT(path);
SkAutoMutexAcquire ac(gFTMutex);
SkAutoMutexExclusive ac(f_t_mutex());
// FT_IS_SCALABLE is documented to mean the face contains outline glyphs.
if (!FT_IS_SCALABLE(fFace) || this->setupSize()) {
@ -1393,7 +1397,7 @@ void SkScalerContext_FreeType::generateFontMetrics(SkFontMetrics* metrics) {
return;
}
SkAutoMutexAcquire ac(gFTMutex);
SkAutoMutexExclusive ac(f_t_mutex());
if (this->setupSize()) {
sk_bzero(metrics, sizeof(*metrics));

View File

@ -64,7 +64,10 @@ namespace {
// Fontconfig is not threadsafe before 2.10.91. Before that, we lock with a global mutex.
// See https://bug.skia.org/1497 for background.
SK_DECLARE_STATIC_MUTEX(gFCMutex);
static SkMutex& f_c_mutex() {
static SkMutex& mutex = *(new SkMutex);
return mutex;
}
#ifdef SK_DEBUG
void* CreateThreadFcLocked() { return new bool(false); }
@ -75,19 +78,19 @@ void DeleteThreadFcLocked(void* v) { delete static_cast<bool*>(v); }
class FCLocker {
// Assume FcGetVersion() has always been thread safe.
static void lock() {
static void lock() SK_NO_THREAD_SAFETY_ANALYSIS {
if (FcGetVersion() < 21091) {
gFCMutex.acquire();
f_c_mutex().acquire();
} else {
SkDEBUGCODE(bool* threadLocked = THREAD_FC_LOCKED);
SkASSERT(false == *threadLocked);
SkDEBUGCODE(*threadLocked = true);
}
}
static void unlock() {
static void unlock() SK_NO_THREAD_SAFETY_ANALYSIS {
AssertHeld();
if (FcGetVersion() < 21091) {
gFCMutex.release();
f_c_mutex().release();
} else {
SkDEBUGCODE(*THREAD_FC_LOCKED = false);
}
@ -109,7 +112,7 @@ public:
static void AssertHeld() { SkDEBUGCODE(
if (FcGetVersion() < 21091) {
gFCMutex.assertHeld();
f_c_mutex().assertHeld();
} else {
SkASSERT(true == *THREAD_FC_LOCKED);
}

View File

@ -13,15 +13,15 @@
static bool gOnce = false;
static DWORD gTlsIndex;
SK_DECLARE_STATIC_MUTEX(gMutex);
void* SkTLS::PlatformGetSpecific(bool forceCreateTheSlot) {
static SkMutex& mutex = *(new SkMutex);
if (!forceCreateTheSlot && !gOnce) {
return nullptr;
}
if (!gOnce) {
SkAutoMutexAcquire tmp(gMutex);
SkAutoMutexExclusive tmp(mutex);
if (!gOnce) {
gTlsIndex = TlsAlloc();
gOnce = true;

View File

@ -357,12 +357,11 @@ static void showPathOpPath(const char* testName, const SkPath& one, const SkPath
drawAsciiPaths(scaledOne, scaledTwo, true);
}
SK_DECLARE_STATIC_MUTEX(compareDebugOut3);
static int comparePaths(skiatest::Reporter* reporter, const char* testName, const SkPath& one,
const SkPath& scaledOne, const SkPath& two, const SkPath& scaledTwo, SkBitmap& bitmap,
const SkPath& a, const SkPath& b, const SkPathOp shapeOp, const SkMatrix& scale,
ExpectMatch expectMatch) {
static SkMutex& compareDebugOut3 = *(new SkMutex);
int errors2x2;
const int MAX_ERRORS = 8;
(void) pathsDrawTheSame(bitmap, scaledOne, scaledTwo, errors2x2);
@ -376,7 +375,7 @@ static int comparePaths(skiatest::Reporter* reporter, const char* testName, cons
return 0;
}
if (ExpectMatch::kYes == expectMatch && errors2x2 >= MAX_ERRORS) {
SkAutoMutexAcquire autoM(compareDebugOut3);
SkAutoMutexExclusive autoM(compareDebugOut3);
showPathOpPath(testName, one, two, a, b, scaledOne, scaledTwo, shapeOp, scale);
SkDebugf("\n/*");
REPORTER_ASSERT(reporter, 0);
@ -450,10 +449,9 @@ void markTestFlakyForPathKit() {
}
}
SK_DECLARE_STATIC_MUTEX(simplifyDebugOut);
bool testSimplify(SkPath& path, bool useXor, SkPath& out, PathOpsThreadState& state,
const char* pathStr) {
static SkMutex& simplifyDebugOut = *(new SkMutex);
SkPath::FillType fillType = useXor ? SkPath::kEvenOdd_FillType : SkPath::kWinding_FillType;
path.setFillType(fillType);
state.fReporter->bumpTestCount();
@ -467,7 +465,7 @@ bool testSimplify(SkPath& path, bool useXor, SkPath& out, PathOpsThreadState& st
}
int result = comparePaths(state.fReporter, nullptr, path, out, *state.fBitmap);
if (result) {
SkAutoMutexAcquire autoM(simplifyDebugOut);
SkAutoMutexExclusive autoM(simplifyDebugOut);
std::string str;
const char* pathPrefix = nullptr;
const char* nameSuffix = nullptr;
@ -751,11 +749,10 @@ bool testPathOpFail(skiatest::Reporter* reporter, const SkPath& a, const SkPath&
return true;
}
SK_DECLARE_STATIC_MUTEX(gMutex);
void initializeTests(skiatest::Reporter* reporter, const char* test) {
static SkMutex& mu = *(new SkMutex);
if (reporter->verbose()) {
SkAutoMutexAcquire lock(gMutex);
SkAutoMutexExclusive lock(mu);
testName = test;
size_t testNameSize = strlen(test);
SkFILEStream inFile("../../experimental/Intersection/op.htm");