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