1603c4be006d8c53905d736bf1f19a49f5ce98276Alexey Samsonov//===-- tsan_mutex.cc -----------------------------------------------------===// 27ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// 37ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// The LLVM Compiler Infrastructure 47ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// 57ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// This file is distributed under the University of Illinois Open Source 67ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// License. See LICENSE.TXT for details. 77ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// 87ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany//===----------------------------------------------------------------------===// 97ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// 107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// This file is a part of ThreadSanitizer (TSan), a race detector. 117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// 127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany//===----------------------------------------------------------------------===// 130969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov#include "sanitizer_common/sanitizer_libc.h" 147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_mutex.h" 157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_platform.h" 167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_rtl.h" 177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanynamespace __tsan { 197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// Simple reader-writer spin-mutex. Optimized for not-so-contended case. 217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// Readers have preference, can possibly starvate writers. 227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// The table fixes what mutexes can be locked under what mutexes. 247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// E.g. if the row for MutexTypeThreads contains MutexTypeReport, 257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// then Report mutex can be locked while under Threads mutex. 267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// The leaf mutexes can be locked under any other mutexes. 277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// Recursive locking is not supported. 2886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#if SANITIZER_DEBUG && !SANITIZER_GO 297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyconst MutexType MutexTypeLeaf = (MutexType)-1; 307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic MutexType CanLockTab[MutexTypeCount][MutexTypeCount] = { 31f4e4f9393ed1cf9cbefaafc6ea8fd9b89fea4bcfDmitry Vyukov /*0 MutexTypeInvalid*/ {}, 32f4e4f9393ed1cf9cbefaafc6ea8fd9b89fea4bcfDmitry Vyukov /*1 MutexTypeTrace*/ {MutexTypeLeaf}, 33f4e4f9393ed1cf9cbefaafc6ea8fd9b89fea4bcfDmitry Vyukov /*2 MutexTypeThreads*/ {MutexTypeReport}, 346a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines /*3 MutexTypeReport*/ {MutexTypeSyncVar, 3594d8b448e046f3976b13ab79130c389115754022Dmitry Vyukov MutexTypeMBlock, MutexTypeJavaMBlock}, 362d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines /*4 MutexTypeSyncVar*/ {MutexTypeDDetector}, 376a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines /*5 MutexTypeSyncTab*/ {}, // unused 38f4e4f9393ed1cf9cbefaafc6ea8fd9b89fea4bcfDmitry Vyukov /*6 MutexTypeSlab*/ {MutexTypeLeaf}, 39f4e4f9393ed1cf9cbefaafc6ea8fd9b89fea4bcfDmitry Vyukov /*7 MutexTypeAnnotations*/ {}, 406a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines /*8 MutexTypeAtExit*/ {MutexTypeSyncVar}, 41f4e4f9393ed1cf9cbefaafc6ea8fd9b89fea4bcfDmitry Vyukov /*9 MutexTypeMBlock*/ {MutexTypeSyncVar}, 42f4e4f9393ed1cf9cbefaafc6ea8fd9b89fea4bcfDmitry Vyukov /*10 MutexTypeJavaMBlock*/ {MutexTypeSyncVar}, 432d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines /*11 MutexTypeDDetector*/ {}, 443d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar /*12 MutexTypeFired*/ {MutexTypeLeaf}, 453d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar /*13 MutexTypeRacy*/ {MutexTypeLeaf}, 467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}; 477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic bool CanLockAdj[MutexTypeCount][MutexTypeCount]; 49d62237995d0fc50697e375ea50f015e996162884Dmitry Vyukov#endif 507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid InitializeMutex() { 5286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#if SANITIZER_DEBUG && !SANITIZER_GO 537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // Build the "can lock" adjacency matrix. 547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // If [i][j]==true, then one can lock mutex j while under mutex i. 557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany const int N = MutexTypeCount; 567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int cnt[N] = {}; 577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany bool leaf[N] = {}; 587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany for (int i = 1; i < N; i++) { 597ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany for (int j = 0; j < N; j++) { 602135d8a7f4ba30fe35ed02d5e6ffd59a95b26219Alexey Samsonov MutexType z = CanLockTab[i][j]; 617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (z == MutexTypeInvalid) 627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany continue; 637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (z == MutexTypeLeaf) { 647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany CHECK(!leaf[i]); 657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany leaf[i] = true; 667ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany continue; 677ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 682135d8a7f4ba30fe35ed02d5e6ffd59a95b26219Alexey Samsonov CHECK(!CanLockAdj[i][(int)z]); 692135d8a7f4ba30fe35ed02d5e6ffd59a95b26219Alexey Samsonov CanLockAdj[i][(int)z] = true; 707ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany cnt[i]++; 717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 737ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany for (int i = 0; i < N; i++) { 747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany CHECK(!leaf[i] || cnt[i] == 0); 757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // Add leaf mutexes. 777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany for (int i = 0; i < N; i++) { 787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (!leaf[i]) 797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany continue; 807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany for (int j = 0; j < N; j++) { 817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (i == j || leaf[j] || j == MutexTypeInvalid) 827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany continue; 837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany CHECK(!CanLockAdj[j][i]); 847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany CanLockAdj[j][i] = true; 857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 877ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // Build the transitive closure. 887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany bool CanLockAdj2[MutexTypeCount][MutexTypeCount]; 897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany for (int i = 0; i < N; i++) { 907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany for (int j = 0; j < N; j++) { 917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany CanLockAdj2[i][j] = CanLockAdj[i][j]; 927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany for (int k = 0; k < N; k++) { 957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany for (int i = 0; i < N; i++) { 967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany for (int j = 0; j < N; j++) { 977ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (CanLockAdj2[i][k] && CanLockAdj2[k][j]) { 987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany CanLockAdj2[i][j] = true; 997ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 1007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 1017ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 1027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 1037ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#if 0 104b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov Printf("Can lock graph:\n"); 1057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany for (int i = 0; i < N; i++) { 1067ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany for (int j = 0; j < N; j++) { 107b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov Printf("%d ", CanLockAdj[i][j]); 1087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 109b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov Printf("\n"); 1107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 111b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov Printf("Can lock graph closure:\n"); 1127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany for (int i = 0; i < N; i++) { 1137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany for (int j = 0; j < N; j++) { 114b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov Printf("%d ", CanLockAdj2[i][j]); 1157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 116b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov Printf("\n"); 1177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 1187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#endif 1197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // Verify that the graph is acyclic. 1207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany for (int i = 0; i < N; i++) { 1217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (CanLockAdj2[i][i]) { 122b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov Printf("Mutex %d participates in a cycle\n", i); 1237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Die(); 1247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 1257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 126d62237995d0fc50697e375ea50f015e996162884Dmitry Vyukov#endif 1277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 1287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1292d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesInternalDeadlockDetector::InternalDeadlockDetector() { 1307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany // Rely on zero initialization because some mutexes can be locked before ctor. 1317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 1327ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 13386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#if SANITIZER_DEBUG && !SANITIZER_GO 1342d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid InternalDeadlockDetector::Lock(MutexType t) { 135b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov // Printf("LOCK %d @%zu\n", t, seq_ + 1); 136ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov CHECK_GT(t, MutexTypeInvalid); 137ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov CHECK_LT(t, MutexTypeCount); 1387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany u64 max_seq = 0; 1397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany u64 max_idx = MutexTypeInvalid; 1407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany for (int i = 0; i != MutexTypeCount; i++) { 1417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (locked_[i] == 0) 1427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany continue; 1437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany CHECK_NE(locked_[i], max_seq); 1447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (max_seq < locked_[i]) { 1457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany max_seq = locked_[i]; 1467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany max_idx = i; 1477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 1487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 1497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany locked_[t] = ++seq_; 1507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (max_idx == MutexTypeInvalid) 1517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return; 152b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov // Printf(" last %d @%zu\n", max_idx, max_seq); 1537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (!CanLockAdj[max_idx][t]) { 154b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov Printf("ThreadSanitizer: internal deadlock detected\n"); 155b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov Printf("ThreadSanitizer: can't lock %d while under %zu\n", 156e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov t, (uptr)max_idx); 157ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov CHECK(0); 1587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 1597ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 1607ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1612d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid InternalDeadlockDetector::Unlock(MutexType t) { 162b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov // Printf("UNLO %d @%zu #%zu\n", t, seq_, locked_[t]); 1637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany CHECK(locked_[t]); 1647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany locked_[t] = 0; 1657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 1666a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines 1676a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hinesvoid InternalDeadlockDetector::CheckNoLocks() { 1686a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines for (int i = 0; i != MutexTypeCount; i++) { 1696a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines CHECK_EQ(locked_[i], 0); 1706a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines } 1716a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines} 1726a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines#endif 1736a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines 1746a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hinesvoid CheckNoLocks(ThreadState *thr) { 17586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#if SANITIZER_DEBUG && !SANITIZER_GO 1766a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines thr->internal_deadlock_detector.CheckNoLocks(); 177d62237995d0fc50697e375ea50f015e996162884Dmitry Vyukov#endif 1786a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines} 1797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyconst uptr kUnlocked = 0; 1817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyconst uptr kWriteLock = 1; 1827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyconst uptr kReadLock = 2; 1837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyclass Backoff { 1857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany public: 1867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany Backoff() 1877ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany : iter_() { 1887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 1897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany bool Do() { 1917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (iter_++ < kActiveSpinIters) 1927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany proc_yield(kActiveSpinCnt); 1937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany else 1940969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov internal_sched_yield(); 1957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return true; 1967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 1977ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 1987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany u64 Contention() const { 1997ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany u64 active = iter_ % kActiveSpinIters; 2007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany u64 passive = iter_ - active; 2017ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return active + 10 * passive; 2027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 2037ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 2047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany private: 2057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany int iter_; 2067ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany static const int kActiveSpinIters = 10; 2077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany static const int kActiveSpinCnt = 20; 2087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}; 2097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 2107ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyMutex::Mutex(MutexType type, StatType stat_type) { 2117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany CHECK_GT(type, MutexTypeInvalid); 2127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany CHECK_LT(type, MutexTypeCount); 21386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#if SANITIZER_DEBUG 2147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany type_ = type; 2157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#endif 2167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#if TSAN_COLLECT_STATS 2177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany stat_type_ = stat_type; 2187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#endif 2197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany atomic_store(&state_, kUnlocked, memory_order_relaxed); 2207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 2217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 2227ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyMutex::~Mutex() { 2237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany CHECK_EQ(atomic_load(&state_, memory_order_relaxed), kUnlocked); 2247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 2257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 2267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid Mutex::Lock() { 22786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#if SANITIZER_DEBUG && !SANITIZER_GO 2282d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines cur_thread()->internal_deadlock_detector.Lock(type_); 2297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#endif 2307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany uptr cmp = kUnlocked; 2317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (atomic_compare_exchange_strong(&state_, &cmp, kWriteLock, 2327ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany memory_order_acquire)) 2337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return; 2347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany for (Backoff backoff; backoff.Do();) { 2357ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (atomic_load(&state_, memory_order_relaxed) == kUnlocked) { 2367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany cmp = kUnlocked; 2377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if (atomic_compare_exchange_weak(&state_, &cmp, kWriteLock, 2387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany memory_order_acquire)) { 23986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#if TSAN_COLLECT_STATS && !SANITIZER_GO 2407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany StatInc(cur_thread(), stat_type_, backoff.Contention()); 2417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#endif 2427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return; 2437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 2447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 2457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 2467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 2477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 2487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid Mutex::Unlock() { 2497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany uptr prev = atomic_fetch_sub(&state_, kWriteLock, memory_order_release); 2507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany (void)prev; 2517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany DCHECK_NE(prev & kWriteLock, 0); 25286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#if SANITIZER_DEBUG && !SANITIZER_GO 2532d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines cur_thread()->internal_deadlock_detector.Unlock(type_); 2547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#endif 2557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 2567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 2577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid Mutex::ReadLock() { 25886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#if SANITIZER_DEBUG && !SANITIZER_GO 2592d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines cur_thread()->internal_deadlock_detector.Lock(type_); 2607ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#endif 2617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany uptr prev = atomic_fetch_add(&state_, kReadLock, memory_order_acquire); 2627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if ((prev & kWriteLock) == 0) 2637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return; 2647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany for (Backoff backoff; backoff.Do();) { 2657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany prev = atomic_load(&state_, memory_order_acquire); 2667ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany if ((prev & kWriteLock) == 0) { 26786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#if TSAN_COLLECT_STATS && !SANITIZER_GO 2687ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany StatInc(cur_thread(), stat_type_, backoff.Contention()); 2697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#endif 2707ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany return; 2717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 2727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany } 2737ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 2747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 2757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid Mutex::ReadUnlock() { 2767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany uptr prev = atomic_fetch_sub(&state_, kReadLock, memory_order_release); 2777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany (void)prev; 2787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany DCHECK_EQ(prev & kWriteLock, 0); 2797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany DCHECK_GT(prev & ~kWriteLock, 0); 28086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#if SANITIZER_DEBUG && !SANITIZER_GO 2812d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines cur_thread()->internal_deadlock_detector.Unlock(type_); 2827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#endif 2837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} 2847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany 285ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukovvoid Mutex::CheckLocked() { 286ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov CHECK_NE(atomic_load(&state_, memory_order_relaxed), 0); 287ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov} 288ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov 2897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany} // namespace __tsan 290