skia2/include/core/SkDynamicAnnotations.h
mtklein 0b544ae222 Add SkRacy
SkRacy<T> is a zero-overhead wrapper for a T, except it also
silences race warnings when TSAN is running.

Here we apply in several classes.  In SkMatrix and SkPathRef,
we use it to opportunistically cache some idempotent work.

In SkPixelRef, we wrap the genIDs.  We think the worst that
can happen here is we'll increment the global next-genID a
few times instead of once when we go to get another ID.

BUG=skia:

Committed: https://skia.googlesource.com/skia/+/d5e3e6ae1b3434ad1158f441902ff65f1eeaa3a7

CQ_EXTRA_TRYBOTS=tryserver.skia:Canary-Chrome-Ubuntu13.10-Ninja-x86_64-ToT-Trybot,Canary-Chrome-Win7-Ninja-x86-SharedLib_ToT-Trybot,Test-Ubuntu13.10-GCE-NoGPU-x86_64-Release-TSAN-Trybot
R=reed@google.com, mtklein@google.com

Author: mtklein@chromium.org

Review URL: https://codereview.chromium.org/371363004
2014-07-08 19:37:47 -07:00

84 lines
2.7 KiB
C++

/*
* Copyright 2014 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkDynamicAnnotations_DEFINED
#define SkDynamicAnnotations_DEFINED
// This file contains macros used to send out-of-band signals to dynamic instrumentation systems,
// namely thread sanitizer. This is a cut-down version of the full dynamic_annotations library with
// only the features used by Skia.
#if SK_DYNAMIC_ANNOTATIONS_ENABLED
extern "C" {
// TSAN provides these hooks.
void AnnotateIgnoreReadsBegin(const char* file, int line);
void AnnotateIgnoreReadsEnd(const char* file, int line);
void AnnotateBenignRaceSized(const char* file, int line,
const volatile void* addr, long size, const char* desc);
} // extern "C"
// SK_ANNOTATE_UNPROTECTED_READ can wrap any variable read to tell TSAN to ignore that it appears to
// be a racy read. This should be used only when we can make an external guarantee that though this
// particular read is racy, it is being used as part of a mechanism which is thread safe. Examples:
// - the first check in double-checked locking;
// - checking if a ref count is equal to 1.
// Note that in both these cases, we must still add terrifyingly subtle memory barriers to provide
// that overall thread safety guarantee. Using this macro to shut TSAN up without providing such an
// external guarantee is pretty much never correct.
template <typename T>
inline T SK_ANNOTATE_UNPROTECTED_READ(const volatile T& x) {
AnnotateIgnoreReadsBegin(__FILE__, __LINE__);
T read = x;
AnnotateIgnoreReadsEnd(__FILE__, __LINE__);
return read;
}
// Ignore racy reads and racy writes to this pointer, indefinitely.
// If at all possible, use the more precise SK_ANNOTATE_UNPROTECTED_READ.
template <typename T>
void SK_ANNOTATE_BENIGN_RACE(T* ptr) {
AnnotateBenignRaceSized(__FILE__, __LINE__, ptr, sizeof(*ptr), "SK_ANNOTATE_BENIGN_RACE");
}
#else // !SK_DYNAMIC_ANNOTATIONS_ENABLED
#define SK_ANNOTATE_UNPROTECTED_READ(x) (x)
#define SK_ANNOTATE_BENIGN_RACE(ptr)
#endif
// Can be used to wrap values that are intentionally racy, usually small mutable cached values, e.g.
// - SkMatrix type mask
// - SkPathRef bounds
// - SkPixelRef genIDs
template <typename T>
class SkTRacy {
public:
SkTRacy() { SK_ANNOTATE_BENIGN_RACE(&fVal); }
operator const T&() const {
return fVal;
}
SkTRacy& operator=(const T& val) {
fVal = val;
return *this;
}
const T* get() const { return &fVal; }
T* get() { return &fVal; }
const T* operator->() const { return &fVal; }
T* operator->() { return &fVal; }
private:
T fVal;
};
#endif//SkDynamicAnnotations_DEFINED