Add annotations to SkSharedMutex.

BUG=skia:3997

Review URL: https://codereview.chromium.org/1213663004
diff --git a/src/core/SkSharedMutex.cpp b/src/core/SkSharedMutex.cpp
index 5465e48..3815ec3 100644
--- a/src/core/SkSharedMutex.cpp
+++ b/src/core/SkSharedMutex.cpp
@@ -11,6 +11,62 @@
 #include "SkSemaphore.h"
 #include "SkTypes.h"
 
+
+#if defined(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)
+
+#ifdef DYNAMIC_ANNOTATIONS_WANT_ATTRIBUTE_WEAK
+# ifdef __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
+
 // The fQueueCounts fields holds many counts in an int32_t in order to make managing them atomic.
 // These three counts must be the same size, so each gets 10 bits. The 10 bits represent
 // the log of the count which is 1024.
@@ -31,8 +87,8 @@
     kWaitingSharedMask     = ((1 << kLogThreadCount) - 1) << kWaitingSharedOffset,
 };
 
-SkSharedMutex::SkSharedMutex() : fQueueCounts(0) { }
-
+SkSharedMutex::SkSharedMutex() : fQueueCounts(0) { ANNOTATE_RWLOCK_CREATE(this); }
+SkSharedMutex::~SkSharedMutex() {  ANNOTATE_RWLOCK_DESTROY(this); }
 void SkSharedMutex::acquire() {
     // Increment the count of exclusive queue waiters.
     int32_t oldQueueCounts = fQueueCounts.fetch_add(1 << kWaitingExlusiveOffset,
@@ -43,9 +99,12 @@
     if ((oldQueueCounts & kWaitingExclusiveMask) > 0 || (oldQueueCounts & kSharedMask) > 0) {
         fExclusiveQueue.wait();
     }
+    ANNOTATE_RWLOCK_ACQUIRED(this, 1);
 }
 
 void SkSharedMutex::release() {
+    ANNOTATE_RWLOCK_RELEASED(this, 1);
+
     int32_t oldQueueCounts = fQueueCounts.load(sk_memory_order_relaxed);
     int32_t waitingShared;
     int32_t newQueueCounts;
@@ -101,9 +160,13 @@
     if ((newQueueCounts & kWaitingExclusiveMask) > 0) {
         fSharedQueue.wait();
     }
+    ANNOTATE_RWLOCK_ACQUIRED(this, 0);
+   
 }
 
 void SkSharedMutex::releaseShared() {
+    ANNOTATE_RWLOCK_RELEASED(this, 0);
+
     // Decrement the shared count.
     int32_t oldQueueCounts = fQueueCounts.fetch_add(-1 << kSharedOffset,
                                                     sk_memory_order_release);
diff --git a/src/core/SkSharedMutex.h b/src/core/SkSharedMutex.h
index a020f9e..a3535dc 100644
--- a/src/core/SkSharedMutex.h
+++ b/src/core/SkSharedMutex.h
@@ -11,7 +11,7 @@
 #include "SkAtomics.h"
 #include "SkSemaphore.h"
 #include "SkTypes.h"
-
+    
 // This is a shared lock implementation similar to pthreads rwlocks. This implementation is
 // cribbed from Preshing's article:
 // http://preshing.com/20150316/semaphores-are-surprisingly-versatile/
@@ -21,7 +21,7 @@
 class SkSharedMutex {
 public:
     SkSharedMutex();
-
+    ~SkSharedMutex();
     // Acquire lock for exclusive use.
     void acquire();