aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/SkSemaphore.cpp23
-rw-r--r--src/core/SkSharedMutex.cpp60
2 files changed, 80 insertions, 3 deletions
diff --git a/src/core/SkSemaphore.cpp b/src/core/SkSemaphore.cpp
index f8f6e165ad..6ad10c4317 100644
--- a/src/core/SkSemaphore.cpp
+++ b/src/core/SkSemaphore.cpp
@@ -10,6 +10,17 @@
#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
+ // semaphore_signal() and semaphore_wait().
+ #if __has_feature(thread_sanitizer)
+ extern "C" void AnnotateHappensBefore(const char*, int, void*);
+ extern "C" void AnnotateHappensAfter (const char*, int, void*);
+ #else
+ static void AnnotateHappensBefore(const char*, int, void*) {}
+ static void AnnotateHappensAfter (const char*, int, void*) {}
+ #endif
+
struct SkBaseSemaphore::OSSemaphore {
semaphore_t fSemaphore;
@@ -18,8 +29,16 @@
}
~OSSemaphore() { semaphore_destroy(mach_task_self(), fSemaphore); }
- void signal(int n) { while (n --> 0) { semaphore_signal(fSemaphore); } }
- void wait() { semaphore_wait(fSemaphore); }
+ void signal(int n) {
+ while (n --> 0) {
+ AnnotateHappensBefore(__FILE__, __LINE__, &fSemaphore);
+ semaphore_signal(fSemaphore);
+ }
+ }
+ void wait() {
+ semaphore_wait(fSemaphore);
+ AnnotateHappensAfter(__FILE__, __LINE__, &fSemaphore);
+ }
};
#elif defined(SK_BUILD_FOR_WIN32)
struct SkBaseSemaphore::OSSemaphore {
diff --git a/src/core/SkSharedMutex.cpp b/src/core/SkSharedMutex.cpp
index 8d6738f9e4..17714a7185 100644
--- a/src/core/SkSharedMutex.cpp
+++ b/src/core/SkSharedMutex.cpp
@@ -8,10 +8,68 @@
#include "SkSharedMutex.h"
#include "SkAtomics.h"
-#include "SkTSAN.h"
#include "SkTypes.h"
#include "SkSemaphore.h"
+#if !defined(__has_feature)
+ #define __has_feature(x) 0
+#endif
+
+#if __has_feature(thread_sanitizer)
+
+ /* Report that a lock has been created at address "lock". */
+ #define ANNOTATE_RWLOCK_CREATE(lock) \
+ AnnotateRWLockCreate(__FILE__, __LINE__, lock)
+
+ /* Report that the lock at address "lock" is about to be destroyed. */
+ #define ANNOTATE_RWLOCK_DESTROY(lock) \
+ AnnotateRWLockDestroy(__FILE__, __LINE__, lock)
+
+ /* Report that the lock at address "lock" has been acquired.
+ is_w=1 for writer lock, is_w=0 for reader lock. */
+ #define ANNOTATE_RWLOCK_ACQUIRED(lock, is_w) \
+ AnnotateRWLockAcquired(__FILE__, __LINE__, lock, is_w)
+
+ /* Report that the lock at address "lock" is about to be released. */
+ #define ANNOTATE_RWLOCK_RELEASED(lock, is_w) \
+ AnnotateRWLockReleased(__FILE__, __LINE__, lock, is_w)
+
+ #if defined(DYNAMIC_ANNOTATIONS_WANT_ATTRIBUTE_WEAK)
+ #if defined(__GNUC__)
+ #define DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK __attribute__((weak))
+ #else
+ /* TODO(glider): for Windows support we may want to change this macro in order
+ to prepend __declspec(selectany) to the annotations' declarations. */
+ #error weak annotations are not supported for your compiler
+ #endif
+ #else
+ #define DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK
+ #endif
+
+ extern "C" {
+ void AnnotateRWLockCreate(
+ const char *file, int line,
+ const volatile void *lock) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+ void AnnotateRWLockDestroy(
+ const char *file, int line,
+ const volatile void *lock) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+ void AnnotateRWLockAcquired(
+ const char *file, int line,
+ const volatile void *lock, long is_w) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+ void AnnotateRWLockReleased(
+ const char *file, int line,
+ const volatile void *lock, long is_w) DYNAMIC_ANNOTATIONS_ATTRIBUTE_WEAK;
+ }
+
+#else
+
+ #define ANNOTATE_RWLOCK_CREATE(lock)
+ #define ANNOTATE_RWLOCK_DESTROY(lock)
+ #define ANNOTATE_RWLOCK_ACQUIRED(lock, is_w)
+ #define ANNOTATE_RWLOCK_RELEASED(lock, is_w)
+
+#endif
+
#ifdef SK_DEBUG
#include "SkThreadID.h"