1/* 2 * Copyright 2014 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8#ifndef SkDynamicAnnotations_DEFINED 9#define SkDynamicAnnotations_DEFINED 10 11// This file contains macros used to send out-of-band signals to dynamic instrumentation systems, 12// namely thread sanitizer. This is a cut-down version of the full dynamic_annotations library with 13// only the features used by Skia. 14 15#if SK_DYNAMIC_ANNOTATIONS_ENABLED 16 17extern "C" { 18// TSAN provides these hooks. 19void AnnotateIgnoreReadsBegin(const char* file, int line); 20void AnnotateIgnoreReadsEnd(const char* file, int line); 21void AnnotateIgnoreWritesBegin(const char* file, int line); 22void AnnotateIgnoreWritesEnd(const char* file, int line); 23void AnnotateBenignRaceSized(const char* file, int line, 24 const volatile void* addr, long size, const char* desc); 25} // extern "C" 26 27// SK_ANNOTATE_UNPROTECTED_READ can wrap any variable read to tell TSAN to ignore that it appears to 28// be a racy read. This should be used only when we can make an external guarantee that though this 29// particular read is racy, it is being used as part of a mechanism which is thread safe. Examples: 30// - the first check in double-checked locking; 31// - checking if a ref count is equal to 1. 32// Note that in both these cases, we must still add terrifyingly subtle memory barriers to provide 33// that overall thread safety guarantee. Using this macro to shut TSAN up without providing such an 34// external guarantee is pretty much never correct. 35template <typename T> 36inline T SK_ANNOTATE_UNPROTECTED_READ(const volatile T& x) { 37 AnnotateIgnoreReadsBegin(__FILE__, __LINE__); 38 T read = x; 39 AnnotateIgnoreReadsEnd(__FILE__, __LINE__); 40 return read; 41} 42 43// Like SK_ANNOTATE_UNPROTECTED_READ, but for writes. 44template <typename T> 45inline void SK_ANNOTATE_UNPROTECTED_WRITE(T* ptr, const volatile T& val) { 46 AnnotateIgnoreWritesBegin(__FILE__, __LINE__); 47 *ptr = val; 48 AnnotateIgnoreWritesEnd(__FILE__, __LINE__); 49} 50 51// Ignore racy reads and racy writes to this pointer, indefinitely. 52// If at all possible, use the more precise SK_ANNOTATE_UNPROTECTED_READ. 53template <typename T> 54void SK_ANNOTATE_BENIGN_RACE(T* ptr) { 55 AnnotateBenignRaceSized(__FILE__, __LINE__, ptr, sizeof(*ptr), "SK_ANNOTATE_BENIGN_RACE"); 56} 57 58#else // !SK_DYNAMIC_ANNOTATIONS_ENABLED 59 60#define SK_ANNOTATE_UNPROTECTED_READ(x) (x) 61#define SK_ANNOTATE_UNPROTECTED_WRITE(ptr, val) *(ptr) = (val) 62#define SK_ANNOTATE_BENIGN_RACE(ptr) 63 64#endif 65 66// Can be used to wrap values that are intentionally racy, usually small mutable cached values, e.g. 67// - SkMatrix type mask 68// - SkPixelRef genIDs 69template <typename T> 70class SkTRacy { 71public: 72 operator const T() const { 73 return SK_ANNOTATE_UNPROTECTED_READ(fVal); 74 } 75 76 SkTRacy& operator=(const T& val) { 77 SK_ANNOTATE_UNPROTECTED_WRITE(&fVal, val); 78 return *this; 79 } 80 81private: 82 T fVal; 83}; 84 85// This is like SkTRacy, but allows you to return the value by reference. 86// TSAN is better at suppressing SkTRacy than SkTRacyReffable, so use SkTRacy when possible. 87// 88// We use this for SkPathRef bounds, which is an SkRect we pass around by reference publically. 89template <typename T> 90class SkTRacyReffable { 91public: 92 SkTRacyReffable() { SK_ANNOTATE_BENIGN_RACE(&fVal); } 93 94 operator const T&() const { 95 return fVal; 96 } 97 98 SkTRacyReffable& operator=(const T& val) { 99 fVal = val; 100 return *this; 101 } 102 103 const T* get() const { return &fVal; } 104 T* get() { return &fVal; } 105 106 const T* operator->() const { return &fVal; } 107 T* operator->() { return &fVal; } 108 109private: 110 T fVal; 111}; 112 113#endif//SkDynamicAnnotations_DEFINED 114