1ea6e14a3825d6f805527ddfbce4fd6b2bf73a7dfcommit-bot@chromium.org/* 2ea6e14a3825d6f805527ddfbce4fd6b2bf73a7dfcommit-bot@chromium.org * Copyright 2014 Google Inc. 3ea6e14a3825d6f805527ddfbce4fd6b2bf73a7dfcommit-bot@chromium.org * 4ea6e14a3825d6f805527ddfbce4fd6b2bf73a7dfcommit-bot@chromium.org * Use of this source code is governed by a BSD-style license that can be 5ea6e14a3825d6f805527ddfbce4fd6b2bf73a7dfcommit-bot@chromium.org * found in the LICENSE file. 6ea6e14a3825d6f805527ddfbce4fd6b2bf73a7dfcommit-bot@chromium.org */ 7ea6e14a3825d6f805527ddfbce4fd6b2bf73a7dfcommit-bot@chromium.org 8ea6e14a3825d6f805527ddfbce4fd6b2bf73a7dfcommit-bot@chromium.org#ifndef SkDynamicAnnotations_DEFINED 9ea6e14a3825d6f805527ddfbce4fd6b2bf73a7dfcommit-bot@chromium.org#define SkDynamicAnnotations_DEFINED 10ea6e14a3825d6f805527ddfbce4fd6b2bf73a7dfcommit-bot@chromium.org 11ea6e14a3825d6f805527ddfbce4fd6b2bf73a7dfcommit-bot@chromium.org// This file contains macros used to send out-of-band signals to dynamic instrumentation systems, 12ea6e14a3825d6f805527ddfbce4fd6b2bf73a7dfcommit-bot@chromium.org// namely thread sanitizer. This is a cut-down version of the full dynamic_annotations library with 13ea6e14a3825d6f805527ddfbce4fd6b2bf73a7dfcommit-bot@chromium.org// only the features used by Skia. 14ea6e14a3825d6f805527ddfbce4fd6b2bf73a7dfcommit-bot@chromium.org 150b544ae222aab1c5d9122a8dfe2800451b31d979mtklein#if SK_DYNAMIC_ANNOTATIONS_ENABLED 16ea6e14a3825d6f805527ddfbce4fd6b2bf73a7dfcommit-bot@chromium.org 17ea6e14a3825d6f805527ddfbce4fd6b2bf73a7dfcommit-bot@chromium.orgextern "C" { 18ea6e14a3825d6f805527ddfbce4fd6b2bf73a7dfcommit-bot@chromium.org// TSAN provides these hooks. 19ea6e14a3825d6f805527ddfbce4fd6b2bf73a7dfcommit-bot@chromium.orgvoid AnnotateIgnoreReadsBegin(const char* file, int line); 20ea6e14a3825d6f805527ddfbce4fd6b2bf73a7dfcommit-bot@chromium.orgvoid AnnotateIgnoreReadsEnd(const char* file, int line); 21497cda3a6b72b9cb390334e8756d38b4ffac044fmtkleinvoid AnnotateIgnoreWritesBegin(const char* file, int line); 22497cda3a6b72b9cb390334e8756d38b4ffac044fmtkleinvoid AnnotateIgnoreWritesEnd(const char* file, int line); 230b544ae222aab1c5d9122a8dfe2800451b31d979mtkleinvoid AnnotateBenignRaceSized(const char* file, int line, 240b544ae222aab1c5d9122a8dfe2800451b31d979mtklein const volatile void* addr, long size, const char* desc); 25ea6e14a3825d6f805527ddfbce4fd6b2bf73a7dfcommit-bot@chromium.org} // extern "C" 26ea6e14a3825d6f805527ddfbce4fd6b2bf73a7dfcommit-bot@chromium.org 27ea6e14a3825d6f805527ddfbce4fd6b2bf73a7dfcommit-bot@chromium.org// SK_ANNOTATE_UNPROTECTED_READ can wrap any variable read to tell TSAN to ignore that it appears to 28ea6e14a3825d6f805527ddfbce4fd6b2bf73a7dfcommit-bot@chromium.org// be a racy read. This should be used only when we can make an external guarantee that though this 29ea6e14a3825d6f805527ddfbce4fd6b2bf73a7dfcommit-bot@chromium.org// particular read is racy, it is being used as part of a mechanism which is thread safe. Examples: 30ea6e14a3825d6f805527ddfbce4fd6b2bf73a7dfcommit-bot@chromium.org// - the first check in double-checked locking; 31ea6e14a3825d6f805527ddfbce4fd6b2bf73a7dfcommit-bot@chromium.org// - checking if a ref count is equal to 1. 32ea6e14a3825d6f805527ddfbce4fd6b2bf73a7dfcommit-bot@chromium.org// Note that in both these cases, we must still add terrifyingly subtle memory barriers to provide 33ea6e14a3825d6f805527ddfbce4fd6b2bf73a7dfcommit-bot@chromium.org// that overall thread safety guarantee. Using this macro to shut TSAN up without providing such an 34ea6e14a3825d6f805527ddfbce4fd6b2bf73a7dfcommit-bot@chromium.org// external guarantee is pretty much never correct. 35ea6e14a3825d6f805527ddfbce4fd6b2bf73a7dfcommit-bot@chromium.orgtemplate <typename T> 36ea6e14a3825d6f805527ddfbce4fd6b2bf73a7dfcommit-bot@chromium.orginline T SK_ANNOTATE_UNPROTECTED_READ(const volatile T& x) { 37ea6e14a3825d6f805527ddfbce4fd6b2bf73a7dfcommit-bot@chromium.org AnnotateIgnoreReadsBegin(__FILE__, __LINE__); 38ea6e14a3825d6f805527ddfbce4fd6b2bf73a7dfcommit-bot@chromium.org T read = x; 39ea6e14a3825d6f805527ddfbce4fd6b2bf73a7dfcommit-bot@chromium.org AnnotateIgnoreReadsEnd(__FILE__, __LINE__); 40ea6e14a3825d6f805527ddfbce4fd6b2bf73a7dfcommit-bot@chromium.org return read; 41ea6e14a3825d6f805527ddfbce4fd6b2bf73a7dfcommit-bot@chromium.org} 42ea6e14a3825d6f805527ddfbce4fd6b2bf73a7dfcommit-bot@chromium.org 43497cda3a6b72b9cb390334e8756d38b4ffac044fmtklein// Like SK_ANNOTATE_UNPROTECTED_READ, but for writes. 44497cda3a6b72b9cb390334e8756d38b4ffac044fmtkleintemplate <typename T> 4542483d902634f6bfc65dbd8bc999610faf372ef0mtkleininline void SK_ANNOTATE_UNPROTECTED_WRITE(T* ptr, const volatile T& val) { 46497cda3a6b72b9cb390334e8756d38b4ffac044fmtklein AnnotateIgnoreWritesBegin(__FILE__, __LINE__); 47497cda3a6b72b9cb390334e8756d38b4ffac044fmtklein *ptr = val; 48497cda3a6b72b9cb390334e8756d38b4ffac044fmtklein AnnotateIgnoreWritesEnd(__FILE__, __LINE__); 49497cda3a6b72b9cb390334e8756d38b4ffac044fmtklein} 50497cda3a6b72b9cb390334e8756d38b4ffac044fmtklein 510b544ae222aab1c5d9122a8dfe2800451b31d979mtklein// Ignore racy reads and racy writes to this pointer, indefinitely. 520b544ae222aab1c5d9122a8dfe2800451b31d979mtklein// If at all possible, use the more precise SK_ANNOTATE_UNPROTECTED_READ. 530b544ae222aab1c5d9122a8dfe2800451b31d979mtkleintemplate <typename T> 540b544ae222aab1c5d9122a8dfe2800451b31d979mtkleinvoid SK_ANNOTATE_BENIGN_RACE(T* ptr) { 550b544ae222aab1c5d9122a8dfe2800451b31d979mtklein AnnotateBenignRaceSized(__FILE__, __LINE__, ptr, sizeof(*ptr), "SK_ANNOTATE_BENIGN_RACE"); 560b544ae222aab1c5d9122a8dfe2800451b31d979mtklein} 570b544ae222aab1c5d9122a8dfe2800451b31d979mtklein 580b544ae222aab1c5d9122a8dfe2800451b31d979mtklein#else // !SK_DYNAMIC_ANNOTATIONS_ENABLED 59ea6e14a3825d6f805527ddfbce4fd6b2bf73a7dfcommit-bot@chromium.org 60ea6e14a3825d6f805527ddfbce4fd6b2bf73a7dfcommit-bot@chromium.org#define SK_ANNOTATE_UNPROTECTED_READ(x) (x) 61497cda3a6b72b9cb390334e8756d38b4ffac044fmtklein#define SK_ANNOTATE_UNPROTECTED_WRITE(ptr, val) *(ptr) = (val) 620b544ae222aab1c5d9122a8dfe2800451b31d979mtklein#define SK_ANNOTATE_BENIGN_RACE(ptr) 63ea6e14a3825d6f805527ddfbce4fd6b2bf73a7dfcommit-bot@chromium.org 64ea6e14a3825d6f805527ddfbce4fd6b2bf73a7dfcommit-bot@chromium.org#endif 65ea6e14a3825d6f805527ddfbce4fd6b2bf73a7dfcommit-bot@chromium.org 660b544ae222aab1c5d9122a8dfe2800451b31d979mtklein// Can be used to wrap values that are intentionally racy, usually small mutable cached values, e.g. 670b544ae222aab1c5d9122a8dfe2800451b31d979mtklein// - SkMatrix type mask 680b544ae222aab1c5d9122a8dfe2800451b31d979mtklein// - SkPixelRef genIDs 690b544ae222aab1c5d9122a8dfe2800451b31d979mtkleintemplate <typename T> 700b544ae222aab1c5d9122a8dfe2800451b31d979mtkleinclass SkTRacy { 710b544ae222aab1c5d9122a8dfe2800451b31d979mtkleinpublic: 72497cda3a6b72b9cb390334e8756d38b4ffac044fmtklein operator const T() const { 73497cda3a6b72b9cb390334e8756d38b4ffac044fmtklein return SK_ANNOTATE_UNPROTECTED_READ(fVal); 74497cda3a6b72b9cb390334e8756d38b4ffac044fmtklein } 75497cda3a6b72b9cb390334e8756d38b4ffac044fmtklein 76497cda3a6b72b9cb390334e8756d38b4ffac044fmtklein SkTRacy& operator=(const T& val) { 77497cda3a6b72b9cb390334e8756d38b4ffac044fmtklein SK_ANNOTATE_UNPROTECTED_WRITE(&fVal, val); 78497cda3a6b72b9cb390334e8756d38b4ffac044fmtklein return *this; 79497cda3a6b72b9cb390334e8756d38b4ffac044fmtklein } 80497cda3a6b72b9cb390334e8756d38b4ffac044fmtklein 81497cda3a6b72b9cb390334e8756d38b4ffac044fmtkleinprivate: 82497cda3a6b72b9cb390334e8756d38b4ffac044fmtklein T fVal; 83497cda3a6b72b9cb390334e8756d38b4ffac044fmtklein}; 84497cda3a6b72b9cb390334e8756d38b4ffac044fmtklein 85497cda3a6b72b9cb390334e8756d38b4ffac044fmtklein// This is like SkTRacy, but allows you to return the value by reference. 86497cda3a6b72b9cb390334e8756d38b4ffac044fmtklein// TSAN is better at suppressing SkTRacy than SkTRacyReffable, so use SkTRacy when possible. 87497cda3a6b72b9cb390334e8756d38b4ffac044fmtklein// 88497cda3a6b72b9cb390334e8756d38b4ffac044fmtklein// We use this for SkPathRef bounds, which is an SkRect we pass around by reference publically. 89497cda3a6b72b9cb390334e8756d38b4ffac044fmtkleintemplate <typename T> 90497cda3a6b72b9cb390334e8756d38b4ffac044fmtkleinclass SkTRacyReffable { 91497cda3a6b72b9cb390334e8756d38b4ffac044fmtkleinpublic: 92497cda3a6b72b9cb390334e8756d38b4ffac044fmtklein SkTRacyReffable() { SK_ANNOTATE_BENIGN_RACE(&fVal); } 930b544ae222aab1c5d9122a8dfe2800451b31d979mtklein 940b544ae222aab1c5d9122a8dfe2800451b31d979mtklein operator const T&() const { 950b544ae222aab1c5d9122a8dfe2800451b31d979mtklein return fVal; 960b544ae222aab1c5d9122a8dfe2800451b31d979mtklein } 970b544ae222aab1c5d9122a8dfe2800451b31d979mtklein 98497cda3a6b72b9cb390334e8756d38b4ffac044fmtklein SkTRacyReffable& operator=(const T& val) { 990b544ae222aab1c5d9122a8dfe2800451b31d979mtklein fVal = val; 1000b544ae222aab1c5d9122a8dfe2800451b31d979mtklein return *this; 1010b544ae222aab1c5d9122a8dfe2800451b31d979mtklein } 1020b544ae222aab1c5d9122a8dfe2800451b31d979mtklein 1030b544ae222aab1c5d9122a8dfe2800451b31d979mtklein const T* get() const { return &fVal; } 1040b544ae222aab1c5d9122a8dfe2800451b31d979mtklein T* get() { return &fVal; } 1050b544ae222aab1c5d9122a8dfe2800451b31d979mtklein 1060b544ae222aab1c5d9122a8dfe2800451b31d979mtklein const T* operator->() const { return &fVal; } 1070b544ae222aab1c5d9122a8dfe2800451b31d979mtklein T* operator->() { return &fVal; } 1080b544ae222aab1c5d9122a8dfe2800451b31d979mtklein 1090b544ae222aab1c5d9122a8dfe2800451b31d979mtkleinprivate: 1100b544ae222aab1c5d9122a8dfe2800451b31d979mtklein T fVal; 1110b544ae222aab1c5d9122a8dfe2800451b31d979mtklein}; 1120b544ae222aab1c5d9122a8dfe2800451b31d979mtklein 113ea6e14a3825d6f805527ddfbce4fd6b2bf73a7dfcommit-bot@chromium.org#endif//SkDynamicAnnotations_DEFINED 114