• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright (c) 2008-2010, Google Inc.
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Neither the name of Google Inc. nor the names of its
11  * contributors may be used to endorse or promote products derived from
12  * this software without specific prior written permission.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
18  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
20  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26 
27 // This file is part of ThreadSanitizer, a dynamic data race detector.
28 // Author: Konstantin Serebryany.
29 // Author: Timur Iskhodzhanov.
30 
31 // You can find the details on this tool at
32 // http://code.google.com/p/data-race-test
33 
34 #include "thread_sanitizer.h"
35 #include "common_util.h"
36 #include "suppressions.h"
37 #include "ignore.h"
38 #include "ts_lock.h"
39 #include "ts_atomic_int.h"
40 #include "dense_multimap.h"
41 #include <stdarg.h>
42 // -------- Constants --------------- {{{1
43 // Segment ID (SID)      is in range [1, kMaxSID-1]
44 // Segment Set ID (SSID) is in range [-kMaxSID+1, -1]
45 // This is not a compile-time constant, but it can only be changed at startup.
46 int kMaxSID = (1 << 23);
47 // Flush state after so many SIDs have been allocated. Set by command line flag.
48 int kMaxSIDBeforeFlush;
49 
50 // Lock ID (LID)      is in range [1, kMaxLID-1]
51 // Lock Set ID (LSID) is in range [-kMaxLID+1, -1]
52 const int kMaxLID = (1 << 23);
53 
54 // This is not a compile-time constant, but it can be changed only at startup.
55 int kSizeOfHistoryStackTrace = 10;
56 
57 // Maximal number of segments in a SegmentSet.
58 // If you change this constant, you also need to change several places
59 // in SegmentSet code.
60 const int kMaxSegmentSetSize = 4;
61 
62 // -------- Globals --------------- {{{1
63 
64 // If true, ignore all accesses in all threads.
65 bool global_ignore;
66 
67 bool g_so_far_only_one_thread = false;
68 bool g_has_entered_main = false;
69 bool g_has_exited_main = false;
70 
71 size_t g_last_flush_time;
72 
73 // Incremented on each Lock and Unlock. Used by LockHistory.
74 uint32_t g_lock_era = 0;
75 
76 uintptr_t g_nacl_mem_start = (uintptr_t)-1;
77 uintptr_t g_nacl_mem_end = (uintptr_t)-1;
78 
79 bool g_race_verifier_active = false;
80 
81 bool debug_expected_races = false;
82 bool debug_benign_races = false;
83 bool debug_malloc = false;
84 bool debug_free = false;
85 bool debug_thread = false;
86 bool debug_ignore = false;
87 bool debug_rtn = false;
88 bool debug_lock = false;
89 bool debug_wrap = false;
90 bool debug_ins = false;
91 bool debug_shadow_stack = false;
92 bool debug_happens_before = false;
93 bool debug_cache = false;
94 bool debug_race_verifier = false;
95 bool debug_atomic = false;
96 
97 #define PrintfIf(flag, ...) \
98   do { if ((flag)) Printf(__VA_ARGS__); } while ((void)0, 0)
99 
100 // -------- TIL --------------- {{{1
101 // ThreadSanitizer Internal lock (scoped).
102 class TIL {
103  public:
TIL(TSLock * lock,int lock_site,bool need_locking=true)104   TIL(TSLock *lock, int lock_site, bool need_locking = true) :
105     lock_(lock),
106     need_locking_(need_locking) {
107     DCHECK(lock_);
108     if (need_locking_ && (TS_SERIALIZED == 0)) {
109       lock_->Lock();
110       G_stats->lock_sites[lock_site]++;
111     }
112   }
~TIL()113   ~TIL() {
114     if (need_locking_ && (TS_SERIALIZED == 0))
115       lock_->Unlock();
116   }
117  private:
118   TSLock *lock_;
119   bool need_locking_;
120 };
121 
122 static TSLock *ts_lock;
123 static TSLock *ts_ignore_below_lock;
124 
125 #ifdef TS_LLVM
ThreadSanitizerLockAcquire()126 void ThreadSanitizerLockAcquire() {
127   ts_lock->Lock();
128 }
129 
ThreadSanitizerLockRelease()130 void ThreadSanitizerLockRelease() {
131   ts_lock->Unlock();
132 }
133 #endif
134 
AssertTILHeld()135 static INLINE void AssertTILHeld() {
136   if (TS_SERIALIZED == 0 && DEBUG_MODE) {
137     ts_lock->AssertHeld();
138   }
139 }
140 
141 // -------- Util ----------------------------- {{{1
142 
143 // Can't use ANNOTATE_UNPROTECTED_READ, it may get instrumented.
144 template <class T>
INTERNAL_ANNOTATE_UNPROTECTED_READ(const volatile T & x)145 inline T INTERNAL_ANNOTATE_UNPROTECTED_READ(const volatile T &x) {
146   ANNOTATE_IGNORE_READS_BEGIN();
147   T res = x;
148   ANNOTATE_IGNORE_READS_END();
149   return res;
150 }
151 
RemoveFilePrefix(string str)152 static string RemoveFilePrefix(string str) {
153   for (size_t i = 0; i < G_flags->file_prefix_to_cut.size(); i++) {
154     string prefix_to_cut = G_flags->file_prefix_to_cut[i];
155     size_t pos = str.find(prefix_to_cut);
156     if (pos != string::npos) {
157       str = str.substr(pos + prefix_to_cut.size());
158     }
159   }
160   if (str.find("./") == 0) {  // remove leading ./
161     str = str.substr(2);
162   }
163   return str;
164 }
165 
PcToRtnNameAndFilePos(uintptr_t pc)166 string PcToRtnNameAndFilePos(uintptr_t pc) {
167   G_stats->pc_to_strings++;
168   string img_name;
169   string file_name;
170   string rtn_name;
171   int line_no = -1;
172   PcToStrings(pc, G_flags->demangle, &img_name, &rtn_name,
173               &file_name, &line_no);
174   if (G_flags->demangle && !G_flags->full_stack_frames)
175     rtn_name = NormalizeFunctionName(rtn_name);
176   file_name = RemoveFilePrefix(file_name);
177   if (file_name == "") {
178     return rtn_name + " " + RemoveFilePrefix(img_name);
179   }
180   char buff[10];
181   snprintf(buff, sizeof(buff), "%d", line_no);
182   return rtn_name + " " + file_name + ":" + buff;
183 }
184 
185 // -------- ID ---------------------- {{{1
186 // We wrap int32_t into ID class and then inherit various ID type from ID.
187 // This is done in an attempt to implement type safety of IDs, i.e.
188 // to make it impossible to make implicit cast from one ID type to another.
189 class ID {
190  public:
191   typedef int32_t T;
ID(T id)192   explicit ID(T id) : id_(id) {}
ID(const ID & id)193   ID(const ID &id) : id_(id.id_) {}
operator ==(const ID & id) const194   INLINE bool operator ==  (const ID &id) const { return id_ == id.id_; }
operator !=(const ID & id) const195   bool operator !=  (const ID &id) const { return id_ != id.id_; }
operator <(const ID & id) const196   bool operator <  (const ID &id) const { return id_ < id.id_; }
operator >(const ID & id) const197   bool operator >  (const ID &id) const { return id_ > id.id_; }
operator >=(const ID & id) const198   bool operator >=  (const ID &id) const { return id_ >= id.id_; }
operator <=(const ID & id) const199   bool operator <=  (const ID &id) const { return id_ <= id.id_; }
200 
IsValid() const201   bool IsValid() const { return id_ >= 0; }
202 
operator =(const ID & id)203   const ID &operator = (const ID &id) {
204     this->id_ = id.id_;
205     return *this;
206   }
raw() const207   T raw() const { return id_; }
208 
209  private:
210   T id_;
211 };
212 
213 // Thread ID.
214 // id >= 0
215 class TID: public ID {
216  public:
217   static const int32_t kInvalidTID;
218 
TID(T id)219   explicit TID(T id) : ID(id) {}
TID()220   TID() : ID(kInvalidTID) {}
valid() const221   bool valid() const { return raw() >= 0; }
222 };
223 
224 const int32_t TID::kInvalidTID = -1;
225 
226 // Segment ID.
227 // id > 0 && id < kMaxSID
228 class SID: public ID {
229  public:
SID(T id)230   explicit SID(T id) : ID(id) {}
SID()231   SID() : ID(0) {}
valid() const232   bool valid() const { return raw() > 0 && raw() < kMaxSID; }
233 };
234 
235 // Lock ID.
236 // id > 0 && id < kMaxLID
237 class LID: public ID {
238  public:
LID(T id)239   explicit LID(T id) : ID(id) {}
LID()240   LID() : ID(0) {}
valid() const241   bool valid() const { return raw() > 0 && raw() < kMaxLID; }
242 };
243 
244 // LockSet ID.
245 // Empty lockset: id == 0
246 // Singleton:     id > 0 (id == Lock's id)
247 // Tuple:         id < 0
248 class LSID: public ID {
249  public:
LSID(T id)250   explicit LSID(T id) : ID(id) {}
LSID()251   LSID() : ID(INT_MAX) {}
valid() const252   bool valid() const {
253     return raw() < kMaxLID && raw() > -(kMaxLID);
254   }
IsEmpty() const255   bool IsEmpty() const { return raw() == 0; }
IsSingleton() const256   bool IsSingleton() const { return raw() > 0; }
GetSingleton() const257   LID GetSingleton() const { return LID(raw()); }
258 };
259 
260 // SegmentSet ID.
261 // Empty SegmentSet: id == 0
262 // Singleton:        id > 0 (id == Segment's id)
263 // Tuple:            id < 0
264 class SSID: public ID {
265  public:
SSID(T id)266   explicit SSID(T id) : ID(id) {}
SSID(SID sid)267   explicit SSID(SID sid) : ID(sid.raw()) {}
SSID()268   SSID(): ID(INT_MAX) {}
valid() const269   bool valid() const {
270     return raw() != 0 && raw() < kMaxSID && raw() > -kMaxSID;
271   }
IsValidOrEmpty()272   bool IsValidOrEmpty() { return raw() < kMaxSID && raw() > -kMaxSID; }
IsEmpty() const273   bool IsEmpty() const { return raw() == 0; }
IsSingleton() const274   bool IsSingleton() const {return raw() > 0; }
IsTuple() const275   bool IsTuple() const {return raw() < 0; }
GetSingleton() const276   SID  GetSingleton() const {
277     DCHECK(IsSingleton());
278     return SID(raw());
279   }
280   // TODO(timurrrr): need to start SegmentSetArray indices from 1
281   // to avoid "int ???() { return -raw() - 1; }"
282 };
283 
284 // -------- Colors ----------------------------- {{{1
285 // Colors for ansi terminals and for html.
286 const char *c_bold    = "";
287 const char *c_red     = "";
288 const char *c_green   = "";
289 const char *c_magenta = "";
290 const char *c_cyan    = "";
291 const char *c_blue    = "";
292 const char *c_yellow  = "";
293 const char *c_default = "";
294 
295 
296 // -------- Forward decls ------ {{{1
297 static void ForgetAllStateAndStartOver(TSanThread *thr, const char *reason);
298 static void FlushStateIfOutOfSegments(TSanThread *thr);
299 static int32_t raw_tid(TSanThread *t);
300 // -------- Simple Cache ------ {{{1
301 #include "ts_simple_cache.h"
302 // -------- PairCache & IntPairToIntCache ------ {{{1
303 template <typename A, typename B, typename Ret,
304          int kHtableSize, int kArraySize = 8>
305 class PairCache {
306  public:
PairCache()307   PairCache() {
308     CHECK(kHtableSize >= 0);
309     CHECK(sizeof(Entry) == sizeof(A) + sizeof(B) + sizeof(Ret));
310     Flush();
311   }
312 
Flush()313   void Flush() {
314     memset(this, 0, sizeof(*this));
315 
316     // Change the first hashtable entry so it doesn't match (0,0) on Lookup.
317     if (kHtableSize != 0)
318       memset(&htable_[0], 1, sizeof(Entry));
319 
320     // Any Lookup should fail now.
321     for (int i = 0; i < kHtableSize; i++) {
322       Ret tmp;
323       DCHECK(!Lookup(htable_[i].a, htable_[i].b, &tmp));
324     }
325     CHECK(array_pos_    == 0);
326     CHECK(array_filled_ == false);
327   }
328 
Insert(A a,B b,Ret v)329   void Insert(A a, B b, Ret v) {
330     // fill the hash table
331     if (kHtableSize != 0) {
332       uint32_t idx  = compute_idx(a, b);
333       htable_[idx].Fill(a, b, v);
334     }
335 
336     // fill the array
337     Ret dummy;
338     if (kArraySize != 0 && !ArrayLookup(a, b, &dummy)) {
339       array_[array_pos_ % kArraySize].Fill(a, b, v);
340       array_pos_ = (array_pos_ + 1) % kArraySize;
341       if (array_pos_ > kArraySize)
342         array_filled_ = true;
343     }
344   }
345 
Lookup(A a,B b,Ret * v)346   INLINE bool Lookup(A a, B b, Ret *v) {
347     // check the array
348     if (kArraySize != 0 && ArrayLookup(a, b, v)) {
349       G_stats->ls_cache_fast++;
350       return true;
351     }
352     // check the hash table.
353     if (kHtableSize != 0) {
354       uint32_t idx  = compute_idx(a, b);
355       Entry & prev_e = htable_[idx];
356       if (prev_e.Match(a, b)) {
357         *v = prev_e.v;
358         return true;
359       }
360     }
361     return false;
362   }
363 
364  private:
365   struct Entry {
366     A a;
367     B b;
368     Ret v;
FillPairCache::Entry369     void Fill(A a, B b, Ret v) {
370       this->a = a;
371       this->b = b;
372       this->v = v;
373     }
MatchPairCache::Entry374     bool Match(A a, B b) const {
375       return this->a == a && this->b == b;
376     }
377   };
378 
ArrayLookup(A a,B b,Ret * v)379   INLINE bool ArrayLookup(A a, B b, Ret *v) {
380     for (int i = 0; i < (array_filled_ ? kArraySize : array_pos_); i++) {
381       Entry & entry = array_[i];
382       if (entry.Match(a, b)) {
383         *v = entry.v;
384         return true;
385       }
386     }
387     return false;
388   }
389 
compute_idx(A a,B b)390   uint32_t compute_idx(A a, B b) {
391     if (kHtableSize == 0)
392       return 0;
393     else
394       return combine2(a, b) % kHtableSize;
395   }
396 
combine2(int a,int b)397   static uint32_t combine2(int a, int b) {
398     return (a << 16) ^ b;
399   }
400 
combine2(SSID a,SID b)401   static uint32_t combine2(SSID a, SID b) {
402     return combine2(a.raw(), b.raw());
403   }
404 
405   Entry htable_[kHtableSize];
406 
407   Entry array_[kArraySize];
408 
409   // array_pos_    - next element to write to the array_ (mod kArraySize)
410   // array_filled_ - set to true once we write the last element of the array
411   int array_pos_;
412   bool array_filled_;
413 };
414 
415 template<int kHtableSize, int kArraySize = 8>
416 class IntPairToIntCache
417   : public PairCache<int, int, int, kHtableSize, kArraySize> {};
418 
419 
420 
421 // -------- FreeList --------------- {{{1
422 class FreeList {
423  public:
FreeList(int obj_size,int chunk_size)424   FreeList(int obj_size, int chunk_size)
425     : list_(0),
426       obj_size_(obj_size),
427       chunk_size_(chunk_size) {
428     CHECK_GE(obj_size_, static_cast<int>(sizeof(NULL)));
429     CHECK((obj_size_ % sizeof(NULL)) == 0);
430     CHECK_GE(chunk_size_, 1);
431   }
432 
Allocate()433   void *Allocate() {
434     if (!list_)
435       AllocateNewChunk();
436     CHECK(list_);
437     List *head = list_;
438     list_ = list_->next;
439     return reinterpret_cast<void*>(head);
440   }
441 
Deallocate(void * ptr)442   void Deallocate(void *ptr) {
443     if (DEBUG_MODE) {
444       memset(ptr, 0xac, obj_size_);
445     }
446     List *new_head = reinterpret_cast<List*>(ptr);
447     new_head->next = list_;
448     list_ = new_head;
449   }
450 
451  private:
AllocateNewChunk()452   void AllocateNewChunk() {
453     CHECK(list_ == NULL);
454     uint8_t *new_mem = new uint8_t[obj_size_ * chunk_size_];
455     if (DEBUG_MODE) {
456       memset(new_mem, 0xab, obj_size_ * chunk_size_);
457     }
458     for (int i = 0; i < chunk_size_; i++) {
459       List *new_head = reinterpret_cast<List*>(new_mem + obj_size_ * i);
460       new_head->next = list_;
461       list_ = new_head;
462     }
463   }
464   struct List {
465     struct List *next;
466   };
467   List *list_;
468 
469 
470   const int obj_size_;
471   const int chunk_size_;
472 };
473 // -------- StackTrace -------------- {{{1
474 class StackTraceFreeList {
475  public:
GetNewMemForStackTrace(size_t capacity)476   uintptr_t *GetNewMemForStackTrace(size_t capacity) {
477     DCHECK(capacity <= (size_t)G_flags->num_callers);
478     return reinterpret_cast<uintptr_t*>(free_lists_[capacity]->Allocate());
479   }
480 
TakeStackTraceBack(uintptr_t * mem,size_t capacity)481   void TakeStackTraceBack(uintptr_t *mem, size_t capacity) {
482     DCHECK(capacity <= (size_t)G_flags->num_callers);
483     free_lists_[capacity]->Deallocate(mem);
484   }
485 
StackTraceFreeList()486   StackTraceFreeList() {
487     size_t n = G_flags->num_callers + 1;
488     free_lists_ = new FreeList *[n];
489     free_lists_[0] = NULL;
490     for (size_t i = 1; i < n; i++) {
491       free_lists_[i] = new FreeList((i+2) * sizeof(uintptr_t), 1024);
492     }
493   }
494 
495  private:
496   FreeList **free_lists_;  // Array of G_flags->num_callers lists.
497 };
498 
499 static StackTraceFreeList *g_stack_trace_free_list;
500 
501 class StackTrace {
502  public:
CreateNewEmptyStackTrace(size_t size,size_t capacity=0)503   static StackTrace *CreateNewEmptyStackTrace(size_t size,
504                                               size_t capacity = 0) {
505     ScopedMallocCostCenter cc("StackTrace::CreateNewEmptyStackTrace()");
506     DCHECK(g_stack_trace_free_list);
507     DCHECK(size != 0);
508     if (capacity == 0)
509       capacity = size;
510     uintptr_t *mem = g_stack_trace_free_list->GetNewMemForStackTrace(capacity);
511     DCHECK(mem);
512     StackTrace *res = new(mem) StackTrace(size, capacity);
513     return res;
514   }
515 
Delete(StackTrace * trace)516   static void Delete(StackTrace *trace) {
517     if (!trace) return;
518     DCHECK(g_stack_trace_free_list);
519     g_stack_trace_free_list->TakeStackTraceBack(
520         reinterpret_cast<uintptr_t*>(trace), trace->capacity());
521   }
522 
size() const523   size_t size() const { return size_; }
capacity() const524   size_t capacity() const { return capacity_; }
525 
set_size(size_t size)526   void set_size(size_t size) {
527     CHECK(size <= capacity());
528     size_ = size;
529   }
530 
531 
Set(size_t i,uintptr_t pc)532   void Set(size_t i, uintptr_t pc) {
533     arr_[i] = pc;
534   }
535 
Get(size_t i) const536   uintptr_t Get(size_t i) const {
537     return arr_[i];
538   }
539 
CutStackBelowFunc(const string func_name)540   static bool CutStackBelowFunc(const string func_name) {
541     for (size_t i = 0; i < G_flags->cut_stack_below.size(); i++) {
542       if (StringMatch(G_flags->cut_stack_below[i], func_name)) {
543         return true;
544       }
545     }
546     return false;
547   }
548 
EmbeddedStackTraceToString(const uintptr_t * emb_trace,size_t n,const char * indent="    ")549   static string EmbeddedStackTraceToString(const uintptr_t *emb_trace, size_t n,
550                                            const char *indent = "    ") {
551     string res = "";
552     const int kBuffSize = 10000;
553     char *buff = new char [kBuffSize];
554     for (size_t i = 0; i < n; i++) {
555       if (!emb_trace[i]) break;
556       string rtn_and_file = PcToRtnNameAndFilePos(emb_trace[i]);
557       if (rtn_and_file.find("(below main) ") == 0 ||
558           rtn_and_file.find("ThreadSanitizerStartThread ") == 0)
559         break;
560 
561       if (i == 0) res += c_bold;
562       if (G_flags->show_pc) {
563         snprintf(buff, kBuffSize, "%s#%-2d %p: ",
564                  indent, static_cast<int>(i),
565                  reinterpret_cast<void*>(emb_trace[i]));
566       } else {
567         snprintf(buff, kBuffSize, "%s#%-2d ", indent, static_cast<int>(i));
568       }
569       res += buff;
570 
571       res += rtn_and_file;
572       if (i == 0) res += c_default;
573       res += "\n";
574 
575       // don't print after main ...
576       if (rtn_and_file.find("main ") == 0)
577         break;
578       // ... and after some default functions (see ThreadSanitizerParseFlags())
579       // and some more functions specified via command line flag.
580       string rtn = NormalizeFunctionName(PcToRtnName(emb_trace[i], true));
581       if (CutStackBelowFunc(rtn))
582         break;
583     }
584     delete [] buff;
585     return res;
586   }
587 
ToString(const char * indent="    ") const588   string ToString(const char *indent = "    ") const {
589     if (!this) return "NO STACK TRACE\n";
590     if (size() == 0) return "EMPTY STACK TRACE\n";
591     return EmbeddedStackTraceToString(arr_, size(), indent);
592   }
593 
PrintRaw() const594   void PrintRaw() const {
595     for (size_t i = 0; i < size(); i++) {
596       Printf("%p ", arr_[i]);
597     }
598     Printf("\n");
599   }
600 
Equals(const StackTrace * t1,const StackTrace * t2)601   static bool Equals(const StackTrace *t1, const StackTrace *t2) {
602     if (t1->size_ != t2->size_) return false;
603     for (size_t i = 0; i < t1->size_; i++) {
604       if (t1->arr_[i] != t2->arr_[i]) return false;
605     }
606     return true;
607   }
608 
609   struct Less {
operator ()StackTrace::Less610     bool operator() (const StackTrace *t1, const StackTrace *t2) const {
611       size_t size = min(t1->size_, t2->size_);
612       for (size_t i = 0; i < size; i++) {
613         if (t1->arr_[i] != t2->arr_[i]) {
614           return (t1->arr_[i] < t2->arr_[i]);
615         }
616       }
617       return t1->size_ < t2->size_;
618     }
619   };
620 
621  private:
StackTrace(size_t size,size_t capacity)622   StackTrace(size_t size, size_t capacity)
623     : size_(size),
624       capacity_(capacity) {
625   }
626 
~StackTrace()627   ~StackTrace() {}
628 
629   size_t size_;
630   size_t capacity_;
631   uintptr_t arr_[];
632 };
633 
634 
635 
636 // -------- Lock -------------------- {{{1
637 const char *kLockAllocCC = "kLockAllocCC";
638 class Lock {
639  public:
640 
Create(uintptr_t lock_addr)641   static Lock *Create(uintptr_t lock_addr) {
642     ScopedMallocCostCenter cc("LockLookup");
643 //    Printf("Lock::Create: %p\n", lock_addr);
644     // Destroy(lock_addr);
645 
646     // CHECK(Lookup(lock_addr) == NULL);
647     Lock *res = LookupOrCreate(lock_addr);
648     res->rd_held_ = 0;
649     res->wr_held_ = 0;
650     res->is_pure_happens_before_ = G_flags->pure_happens_before;
651     res->last_lock_site_ = NULL;
652     return res;
653   }
654 
Destroy(uintptr_t lock_addr)655   static void Destroy(uintptr_t lock_addr) {
656 //    Printf("Lock::Destroy: %p\n", lock_addr);
657   //  map_.erase(lock_addr);
658   }
659 
LookupOrCreate(uintptr_t lock_addr)660   static NOINLINE Lock *LookupOrCreate(uintptr_t lock_addr) {
661     ScopedMallocCostCenter cc("LockLookup");
662     Lock **lock = &(*map_)[lock_addr];
663     if (*lock == NULL) {
664 //      Printf("Lock::LookupOrCreate: %p\n", lock_addr);
665       ScopedMallocCostCenter cc_lock("new Lock");
666       *lock = new Lock(lock_addr, map_->size());
667     }
668     return *lock;
669   }
670 
Lookup(uintptr_t lock_addr)671   static NOINLINE Lock *Lookup(uintptr_t lock_addr) {
672     ScopedMallocCostCenter cc("LockLookup");
673     Map::iterator it = map_->find(lock_addr);
674     if (it == map_->end()) return NULL;
675     return it->second;
676   }
677 
rd_held() const678   int       rd_held()   const { return rd_held_; }
wr_held() const679   int       wr_held()   const { return wr_held_; }
lock_addr() const680   uintptr_t lock_addr() const { return lock_addr_; }
lid() const681   LID       lid()       const { return lid_; }
is_pure_happens_before() const682   bool is_pure_happens_before() const { return is_pure_happens_before_; }
683 
684   // When a lock is pure happens-before, we need to create hb arcs
685   // between all Unlock/Lock pairs except RdUnlock/RdLock.
686   // For that purpose have two IDs on which we signal/wait.
687   // One id is the lock_addr itself, the second id is derived
688   // from lock_addr.
wr_signal_addr() const689   uintptr_t wr_signal_addr() const { return lock_addr(); }
rd_signal_addr() const690   uintptr_t rd_signal_addr() const { return lock_addr() + 1; }
691 
692 
set_is_pure_happens_before(bool x)693   void set_is_pure_happens_before(bool x) { is_pure_happens_before_ = x; }
694 
WrLock(TID tid,StackTrace * lock_site)695   void WrLock(TID tid, StackTrace *lock_site) {
696     CHECK(!rd_held_);
697     if (wr_held_ == 0) {
698       thread_holding_me_in_write_mode_ = tid;
699     } else {
700       CHECK(thread_holding_me_in_write_mode_ == tid);
701     }
702     wr_held_++;
703     StackTrace::Delete(last_lock_site_);
704     last_lock_site_ = lock_site;
705   }
706 
WrUnlock()707   void WrUnlock() {
708     CHECK(!rd_held_);
709     CHECK(wr_held_ > 0);
710     wr_held_--;
711   }
712 
RdLock(StackTrace * lock_site)713   void RdLock(StackTrace *lock_site) {
714     CHECK(!wr_held_);
715     rd_held_++;
716     StackTrace::Delete(last_lock_site_);
717     last_lock_site_ = lock_site;
718   }
719 
RdUnlock()720   void RdUnlock() {
721     CHECK(!wr_held_);
722     CHECK(rd_held_);
723     rd_held_--;
724   }
725 
set_name(const char * name)726   void set_name(const char *name) { name_ = name; }
name() const727   const char *name() const { return name_; }
728 
ToString() const729   string ToString() const {
730     string res;
731     char buff[100];
732     snprintf(buff, sizeof(buff), "L%d", lid_.raw());
733     // do we need to print the address?
734     // reinterpret_cast<void*>(lock_addr()));
735     res = buff;
736     if (name()) {
737       res += string(" ") + name();
738     }
739     return res;
740   }
741 
LIDtoLock(LID lid)742   static Lock *LIDtoLock(LID lid) {
743     // slow, but needed only for reports.
744     for (Map::iterator it = map_->begin(); it != map_->end(); ++it) {
745       Lock *l = it->second;
746       if (l->lid_ == lid) {
747         return l;
748       }
749     }
750     return NULL;
751   }
752 
ToString(LID lid)753   static string ToString(LID lid) {
754     Lock *lock = LIDtoLock(lid);
755     CHECK(lock);
756     return lock->ToString();
757   }
758 
ReportLockWithOrWithoutContext(LID lid,bool with_context)759   static void ReportLockWithOrWithoutContext(LID lid, bool with_context) {
760     if (!with_context) {
761       Report("   L%d\n", lid.raw());
762       return;
763     }
764     Lock *lock = LIDtoLock(lid);
765     CHECK(lock);
766     if (lock->last_lock_site_) {
767       Report("   %s (%p)\n%s",
768              lock->ToString().c_str(),
769              lock->lock_addr_,
770              lock->last_lock_site_->ToString().c_str());
771     } else {
772       Report("   %s. This lock was probably destroyed"
773                  " w/o calling Unlock()\n", lock->ToString().c_str());
774     }
775   }
776 
InitClassMembers()777   static void InitClassMembers() {
778     map_ = new Lock::Map;
779   }
780 
781  private:
Lock(uintptr_t lock_addr,int32_t lid)782   Lock(uintptr_t lock_addr, int32_t lid)
783     : lock_addr_(lock_addr),
784       lid_(lid),
785       rd_held_(0),
786       wr_held_(0),
787       is_pure_happens_before_(G_flags->pure_happens_before),
788       last_lock_site_(0),
789       name_(NULL) {
790   }
791 
792   // Data members
793   uintptr_t lock_addr_;
794   LID       lid_;
795   int       rd_held_;
796   int       wr_held_;
797   bool      is_pure_happens_before_;
798   StackTrace *last_lock_site_;
799   const char *name_;
800   TID       thread_holding_me_in_write_mode_;
801 
802   // Static members
803   typedef map<uintptr_t, Lock*> Map;
804   static Map *map_;
805 };
806 
807 
808 Lock::Map *Lock::map_;
809 
810 // Returns a string like "L123,L234".
SetOfLocksToString(const set<LID> & locks)811 static string SetOfLocksToString(const set<LID> &locks) {
812   string res;
813   for (set<LID>::const_iterator it = locks.begin();
814        it != locks.end(); ++it) {
815     LID lid = *it;
816     char buff[100];
817     snprintf(buff, sizeof(buff), "L%d", lid.raw());
818     if (it != locks.begin())
819       res += ", ";
820     res += buff;
821   }
822   return res;
823 }
824 
825 // -------- FixedArray--------------- {{{1
826 template <typename T, size_t SizeLimit = 1024>
827 class FixedArray {
828  public:
FixedArray(size_t array_size)829   explicit INLINE FixedArray(size_t array_size)
830       : size_(array_size),
831         array_((array_size <= SizeLimit
832                 ? alloc_space_
833                 : new T[array_size])) { }
834 
~FixedArray()835   ~FixedArray() {
836     if (array_ != alloc_space_) {
837       delete[] array_;
838     }
839   }
840 
begin()841   T* begin() { return array_; }
operator [](int i)842   T& operator[](int i)             { return array_[i]; }
843 
844  private:
845   const size_t size_;
846   T* array_;
847   T alloc_space_[SizeLimit];
848 };
849 
850 // -------- LockSet ----------------- {{{1
851 class LockSet {
852  public:
Add(LSID lsid,Lock * lock)853   NOINLINE static LSID Add(LSID lsid, Lock *lock) {
854     ScopedMallocCostCenter cc("LockSetAdd");
855     LID lid = lock->lid();
856     if (lsid.IsEmpty()) {
857       // adding to an empty lock set
858       G_stats->ls_add_to_empty++;
859       return LSID(lid.raw());
860     }
861     int cache_res;
862     if (ls_add_cache_->Lookup(lsid.raw(), lid.raw(), &cache_res)) {
863       G_stats->ls_add_cache_hit++;
864       return LSID(cache_res);
865     }
866     LSID res;
867     if (lsid.IsSingleton()) {
868       LSSet set(lsid.GetSingleton(), lid);
869       G_stats->ls_add_to_singleton++;
870       res = ComputeId(set);
871     } else {
872       LSSet set(Get(lsid), lid);
873       G_stats->ls_add_to_multi++;
874       res = ComputeId(set);
875     }
876     ls_add_cache_->Insert(lsid.raw(), lid.raw(), res.raw());
877     return res;
878   }
879 
880   // If lock is present in lsid, set new_lsid to (lsid \ lock) and return true.
881   // Otherwise set new_lsid to lsid and return false.
Remove(LSID lsid,Lock * lock,LSID * new_lsid)882   NOINLINE static bool Remove(LSID lsid, Lock *lock, LSID *new_lsid) {
883     *new_lsid = lsid;
884     if (lsid.IsEmpty()) return false;
885     LID lid = lock->lid();
886 
887     if (lsid.IsSingleton()) {
888       // removing the only lock -> LSID(0)
889       if (lsid.GetSingleton() != lid) return false;
890       G_stats->ls_remove_from_singleton++;
891       *new_lsid = LSID(0);
892       return true;
893     }
894 
895     int cache_res;
896     if (ls_rem_cache_->Lookup(lsid.raw(), lid.raw(), &cache_res)) {
897       G_stats->ls_rem_cache_hit++;
898       *new_lsid = LSID(cache_res);
899       return true;
900     }
901 
902     LSSet &prev_set = Get(lsid);
903     if (!prev_set.has(lid)) return false;
904     LSSet set(prev_set, LSSet::REMOVE, lid);
905     CHECK(set.size() == prev_set.size() - 1);
906     G_stats->ls_remove_from_multi++;
907     LSID res = ComputeId(set);
908     ls_rem_cache_->Insert(lsid.raw(), lid.raw(), res.raw());
909     *new_lsid = res;
910     return true;
911   }
912 
IntersectionIsEmpty(LSID lsid1,LSID lsid2)913   NOINLINE static bool IntersectionIsEmpty(LSID lsid1, LSID lsid2) {
914     // at least one empty
915     if (lsid1.IsEmpty() || lsid2.IsEmpty())
916       return true;  // empty
917 
918     // both singletons
919     if (lsid1.IsSingleton() && lsid2.IsSingleton()) {
920       return lsid1 != lsid2;
921     }
922 
923     // first is singleton, second is not
924     if (lsid1.IsSingleton()) {
925       const LSSet &set2 = Get(lsid2);
926       return set2.has(LID(lsid1.raw())) == false;
927     }
928 
929     // second is singleton, first is not
930     if (lsid2.IsSingleton()) {
931       const LSSet &set1 = Get(lsid1);
932       return set1.has(LID(lsid2.raw())) == false;
933     }
934 
935     // LockSets are equal and not empty
936     if (lsid1 == lsid2)
937       return false;
938 
939     // both are not singletons - slow path.
940     bool ret = true,
941          cache_hit = false;
942     DCHECK(lsid2.raw() < 0);
943     if (ls_intersection_cache_->Lookup(lsid1.raw(), -lsid2.raw(), &ret)) {
944       if (!DEBUG_MODE)
945         return ret;
946       cache_hit = true;
947     }
948     const LSSet &set1 = Get(lsid1);
949     const LSSet &set2 = Get(lsid2);
950 
951     FixedArray<LID> intersection(min(set1.size(), set2.size()));
952     LID *end = set_intersection(set1.begin(), set1.end(),
953                             set2.begin(), set2.end(),
954                             intersection.begin());
955     DCHECK(!cache_hit || (ret == (end == intersection.begin())));
956     ret = (end == intersection.begin());
957     ls_intersection_cache_->Insert(lsid1.raw(), -lsid2.raw(), ret);
958     return ret;
959   }
960 
HasNonPhbLocks(LSID lsid)961   static bool HasNonPhbLocks(LSID lsid) {
962     if (lsid.IsEmpty())
963       return false;
964     if (lsid.IsSingleton())
965       return !Lock::LIDtoLock(LID(lsid.raw()))->is_pure_happens_before();
966 
967     LSSet &set = Get(lsid);
968     for (LSSet::const_iterator it = set.begin(); it != set.end(); ++it)
969       if (!Lock::LIDtoLock(*it)->is_pure_happens_before())
970         return true;
971     return false;
972   }
973 
ToString(LSID lsid)974   static string ToString(LSID lsid) {
975     if (lsid.IsEmpty()) {
976       return "{}";
977     } else if (lsid.IsSingleton()) {
978       return "{" + Lock::ToString(lsid.GetSingleton()) + "}";
979     }
980     const LSSet &set = Get(lsid);
981     string res = "{";
982     for (LSSet::const_iterator it = set.begin(); it != set.end(); ++it) {
983       if (it != set.begin()) res += ", ";
984       res += Lock::ToString(*it);
985     }
986     res += "}";
987     return res;
988   }
989 
ReportLockSetWithContexts(LSID lsid,set<LID> * locks_reported,const char * descr)990   static void ReportLockSetWithContexts(LSID lsid,
991                                         set<LID> *locks_reported,
992                                         const char *descr) {
993     if (lsid.IsEmpty()) return;
994     Report("%s%s%s\n", c_green, descr, c_default);
995     if (lsid.IsSingleton()) {
996       LID lid = lsid.GetSingleton();
997       Lock::ReportLockWithOrWithoutContext(lid,
998                                            locks_reported->count(lid) == 0);
999       locks_reported->insert(lid);
1000     } else {
1001       const LSSet &set = Get(lsid);
1002       for (LSSet::const_iterator it = set.begin(); it != set.end(); ++it) {
1003         LID lid = *it;
1004         Lock::ReportLockWithOrWithoutContext(lid,
1005                                      locks_reported->count(lid) == 0);
1006         locks_reported->insert(lid);
1007       }
1008     }
1009   }
1010 
AddLocksToSet(LSID lsid,set<LID> * locks)1011   static void AddLocksToSet(LSID lsid, set<LID> *locks) {
1012     if (lsid.IsEmpty()) return;
1013     if (lsid.IsSingleton()) {
1014       locks->insert(lsid.GetSingleton());
1015     } else {
1016       const LSSet &set = Get(lsid);
1017       for (LSSet::const_iterator it = set.begin(); it != set.end(); ++it) {
1018         locks->insert(*it);
1019       }
1020     }
1021   }
1022 
1023 
InitClassMembers()1024   static void InitClassMembers() {
1025     map_ = new LockSet::Map;
1026     vec_ = new LockSet::Vec;
1027     ls_add_cache_ = new LSCache;
1028     ls_rem_cache_ = new LSCache;
1029     ls_rem_cache_ = new LSCache;
1030     ls_intersection_cache_ = new LSIntersectionCache;
1031   }
1032 
1033  private:
1034   // No instances are allowed.
LockSet()1035   LockSet() { }
1036 
1037   typedef DenseMultimap<LID, 3> LSSet;
1038 
Get(LSID lsid)1039   static LSSet &Get(LSID lsid) {
1040     ScopedMallocCostCenter cc(__FUNCTION__);
1041     int idx = -lsid.raw() - 1;
1042     DCHECK(idx >= 0);
1043     DCHECK(idx < static_cast<int>(vec_->size()));
1044     return (*vec_)[idx];
1045   }
1046 
ComputeId(const LSSet & set)1047   static LSID ComputeId(const LSSet &set) {
1048     CHECK(set.size() > 0);
1049     if (set.size() == 1) {
1050       // signleton lock set has lsid == lid.
1051       return LSID(set.begin()->raw());
1052     }
1053     DCHECK(map_);
1054     DCHECK(vec_);
1055     // multiple locks.
1056     ScopedMallocCostCenter cc("LockSet::ComputeId");
1057     int32_t *id = &(*map_)[set];
1058     if (*id == 0) {
1059       vec_->push_back(set);
1060       *id = map_->size();
1061       if      (set.size() == 2) G_stats->ls_size_2++;
1062       else if (set.size() == 3) G_stats->ls_size_3++;
1063       else if (set.size() == 4) G_stats->ls_size_4++;
1064       else if (set.size() == 5) G_stats->ls_size_5++;
1065       else                      G_stats->ls_size_other++;
1066       if (*id >= 4096 && ((*id & (*id - 1)) == 0)) {
1067         Report("INFO: %d LockSet IDs have been allocated "
1068                "(2: %ld 3: %ld 4: %ld 5: %ld o: %ld)\n",
1069                *id,
1070                G_stats->ls_size_2, G_stats->ls_size_3,
1071                G_stats->ls_size_4, G_stats->ls_size_5,
1072                G_stats->ls_size_other
1073                );
1074       }
1075     }
1076     return LSID(-*id);
1077   }
1078 
1079   typedef map<LSSet, int32_t> Map;
1080   static Map *map_;
1081 
1082   static const char *kLockSetVecAllocCC;
1083   typedef vector<LSSet> Vec;
1084   static Vec *vec_;
1085 
1086 //  static const int kPrimeSizeOfLsCache = 307;
1087 //  static const int kPrimeSizeOfLsCache = 499;
1088   static const int kPrimeSizeOfLsCache = 1021;
1089   typedef IntPairToIntCache<kPrimeSizeOfLsCache> LSCache;
1090   static LSCache *ls_add_cache_;
1091   static LSCache *ls_rem_cache_;
1092   static LSCache *ls_int_cache_;
1093   typedef IntPairToBoolCache<kPrimeSizeOfLsCache> LSIntersectionCache;
1094   static LSIntersectionCache *ls_intersection_cache_;
1095 };
1096 
1097 LockSet::Map *LockSet::map_;
1098 LockSet::Vec *LockSet::vec_;
1099 const char *LockSet::kLockSetVecAllocCC = "kLockSetVecAllocCC";
1100 LockSet::LSCache *LockSet::ls_add_cache_;
1101 LockSet::LSCache *LockSet::ls_rem_cache_;
1102 LockSet::LSCache *LockSet::ls_int_cache_;
1103 LockSet::LSIntersectionCache *LockSet::ls_intersection_cache_;
1104 
1105 
TwoLockSetsToString(LSID rd_lockset,LSID wr_lockset)1106 static string TwoLockSetsToString(LSID rd_lockset, LSID wr_lockset) {
1107   string res;
1108   if (rd_lockset == wr_lockset) {
1109     res = "L";
1110     res += LockSet::ToString(wr_lockset);
1111   } else {
1112     res = "WR-L";
1113     res += LockSet::ToString(wr_lockset);
1114     res += "/RD-L";
1115     res += LockSet::ToString(rd_lockset);
1116   }
1117   return res;
1118 }
1119 
1120 
1121 
1122 
1123 // -------- VTS ------------------ {{{1
1124 class VTS {
1125  public:
MemoryRequiredForOneVts(size_t size)1126   static size_t MemoryRequiredForOneVts(size_t size) {
1127     return sizeof(VTS) + size * sizeof(TS);
1128   }
1129 
RoundUpSizeForEfficientUseOfFreeList(size_t size)1130   static size_t RoundUpSizeForEfficientUseOfFreeList(size_t size) {
1131     if (size < 32) return size;
1132     if (size < 64) return (size + 7) & ~7;
1133     if (size < 128) return (size + 15) & ~15;
1134     return (size + 31) & ~31;
1135   }
1136 
Create(size_t size)1137   static VTS *Create(size_t size) {
1138     DCHECK(size > 0);
1139     void *mem;
1140     size_t rounded_size = RoundUpSizeForEfficientUseOfFreeList(size);
1141     DCHECK(size <= rounded_size);
1142     if (rounded_size <= kNumberOfFreeLists) {
1143       // Small chunk, use FreeList.
1144       ScopedMallocCostCenter cc("VTS::Create (from free list)");
1145       mem = free_lists_[rounded_size]->Allocate();
1146       G_stats->vts_create_small++;
1147     } else {
1148       // Large chunk, use new/delete instead of FreeList.
1149       ScopedMallocCostCenter cc("VTS::Create (from new[])");
1150       mem = new int8_t[MemoryRequiredForOneVts(size)];
1151       G_stats->vts_create_big++;
1152     }
1153     VTS *res = new(mem) VTS(size);
1154     G_stats->vts_total_create += size;
1155     return res;
1156   }
1157 
Unref(VTS * vts)1158   static void Unref(VTS *vts) {
1159     if (!vts) return;
1160     CHECK_GT(vts->ref_count_, 0);
1161     if (AtomicDecrementRefcount(&vts->ref_count_) == 0) {
1162       size_t size = vts->size_;  // can't use vts->size().
1163       size_t rounded_size = RoundUpSizeForEfficientUseOfFreeList(size);
1164       if (rounded_size <= kNumberOfFreeLists) {
1165         free_lists_[rounded_size]->Deallocate(vts);
1166         G_stats->vts_delete_small++;
1167       } else {
1168         G_stats->vts_delete_big++;
1169         delete vts;
1170       }
1171       G_stats->vts_total_delete += rounded_size;
1172     }
1173   }
1174 
CreateSingleton(TID tid,int32_t clk=1)1175   static VTS *CreateSingleton(TID tid, int32_t clk = 1) {
1176     VTS *res = Create(1);
1177     res->arr_[0].tid = tid.raw();
1178     res->arr_[0].clk = clk;
1179     return res;
1180   }
1181 
Clone()1182   VTS *Clone() {
1183     G_stats->vts_clone++;
1184     AtomicIncrementRefcount(&ref_count_);
1185     return this;
1186   }
1187 
CopyAndTick(const VTS * vts,TID id_to_tick)1188   static VTS *CopyAndTick(const VTS *vts, TID id_to_tick) {
1189     CHECK(vts->ref_count_);
1190     VTS *res = Create(vts->size());
1191     bool found = false;
1192     for (size_t i = 0; i < res->size(); i++) {
1193       res->arr_[i] = vts->arr_[i];
1194       if (res->arr_[i].tid == id_to_tick.raw()) {
1195         res->arr_[i].clk++;
1196         found = true;
1197       }
1198     }
1199     CHECK(found);
1200     return res;
1201   }
1202 
Join(const VTS * vts_a,const VTS * vts_b)1203   static VTS *Join(const VTS *vts_a, const VTS *vts_b) {
1204     CHECK(vts_a->ref_count_);
1205     CHECK(vts_b->ref_count_);
1206     FixedArray<TS> result_ts(vts_a->size() + vts_b->size());
1207     TS *t = result_ts.begin();
1208     const TS *a = &vts_a->arr_[0];
1209     const TS *b = &vts_b->arr_[0];
1210     const TS *a_max = a + vts_a->size();
1211     const TS *b_max = b + vts_b->size();
1212     while (a < a_max && b < b_max) {
1213       if (a->tid < b->tid) {
1214         *t = *a;
1215         a++;
1216         t++;
1217       } else if (a->tid > b->tid) {
1218         *t = *b;
1219         b++;
1220         t++;
1221       } else {
1222         if (a->clk >= b->clk) {
1223           *t = *a;
1224         } else {
1225           *t = *b;
1226         }
1227         a++;
1228         b++;
1229         t++;
1230       }
1231     }
1232     while (a < a_max) {
1233       *t = *a;
1234       a++;
1235       t++;
1236     }
1237     while (b < b_max) {
1238       *t = *b;
1239       b++;
1240       t++;
1241     }
1242 
1243     VTS *res = VTS::Create(t - result_ts.begin());
1244     for (size_t i = 0; i < res->size(); i++) {
1245       res->arr_[i] = result_ts[i];
1246     }
1247     return res;
1248   }
1249 
clk(TID tid) const1250   int32_t clk(TID tid) const {
1251     // TODO(dvyukov): this function is sub-optimal,
1252     // we only need thread's own clock.
1253     for (size_t i = 0; i < size_; i++) {
1254       if (arr_[i].tid == tid.raw()) {
1255         return arr_[i].clk;
1256       }
1257     }
1258     return 0;
1259   }
1260 
FlushHBCache()1261   static INLINE void FlushHBCache() {
1262     hb_cache_->Flush();
1263   }
1264 
HappensBeforeCached(const VTS * vts_a,const VTS * vts_b)1265   static INLINE bool HappensBeforeCached(const VTS *vts_a, const VTS *vts_b) {
1266     bool res = false;
1267     if (hb_cache_->Lookup(vts_a->uniq_id_, vts_b->uniq_id_, &res)) {
1268       G_stats->n_vts_hb_cached++;
1269       DCHECK(res == HappensBefore(vts_a, vts_b));
1270       return res;
1271     }
1272     res = HappensBefore(vts_a, vts_b);
1273     hb_cache_->Insert(vts_a->uniq_id_, vts_b->uniq_id_, res);
1274     return res;
1275   }
1276 
1277   // return true if vts_a happens-before vts_b.
HappensBefore(const VTS * vts_a,const VTS * vts_b)1278   static NOINLINE bool HappensBefore(const VTS *vts_a, const VTS *vts_b) {
1279     CHECK(vts_a->ref_count_);
1280     CHECK(vts_b->ref_count_);
1281     G_stats->n_vts_hb++;
1282     const TS *a = &vts_a->arr_[0];
1283     const TS *b = &vts_b->arr_[0];
1284     const TS *a_max = a + vts_a->size();
1285     const TS *b_max = b + vts_b->size();
1286     bool a_less_than_b = false;
1287     while (a < a_max && b < b_max) {
1288       if (a->tid < b->tid) {
1289         // a->tid is not present in b.
1290         return false;
1291       } else if (a->tid > b->tid) {
1292         // b->tid is not present in a.
1293         a_less_than_b = true;
1294         b++;
1295       } else {
1296         // this tid is present in both VTSs. Compare clocks.
1297         if (a->clk > b->clk) return false;
1298         if (a->clk < b->clk) a_less_than_b = true;
1299         a++;
1300         b++;
1301       }
1302     }
1303     if (a < a_max) {
1304       // Some tids are present in a and not in b
1305       return false;
1306     }
1307     if (b < b_max) {
1308       return true;
1309     }
1310     return a_less_than_b;
1311   }
1312 
size() const1313   size_t size() const {
1314     DCHECK(ref_count_);
1315     return size_;
1316   }
1317 
ToString() const1318   string ToString() const {
1319     DCHECK(ref_count_);
1320     string res = "[";
1321     for (size_t i = 0; i < size(); i++) {
1322       char buff[100];
1323       snprintf(buff, sizeof(buff), "%d:%d;", arr_[i].tid, arr_[i].clk);
1324       if (i) res += " ";
1325       res += buff;
1326     }
1327     return res + "]";
1328   }
1329 
print(const char * name) const1330   void print(const char *name) const {
1331     string str = ToString();
1332     Printf("%s: %s\n", name, str.c_str());
1333   }
1334 
TestHappensBefore()1335   static void TestHappensBefore() {
1336     // TODO(kcc): need more tests here...
1337     const char *test_vts[] = {
1338       "[0:1;]",
1339       "[0:4; 2:1;]",
1340       "[0:4; 2:2; 4:1;]",
1341       "[0:4; 3:2; 4:1;]",
1342       "[0:4; 3:2; 4:2;]",
1343       "[0:4; 3:3; 4:1;]",
1344       NULL
1345     };
1346 
1347     for (int i = 0; test_vts[i]; i++) {
1348       const VTS *vts1 = Parse(test_vts[i]);
1349       for (int j = 0; test_vts[j]; j++) {
1350         const VTS *vts2 = Parse(test_vts[j]);
1351         bool hb  = HappensBefore(vts1, vts2);
1352         Printf("HB = %d\n   %s\n   %s\n", static_cast<int>(hb),
1353                vts1->ToString().c_str(),
1354                vts2->ToString().c_str());
1355         delete vts2;
1356       }
1357       delete vts1;
1358     }
1359   }
1360 
Test()1361   static void Test() {
1362     Printf("VTS::test();\n");
1363     VTS *v1 = CreateSingleton(TID(0));
1364     VTS *v2 = CreateSingleton(TID(1));
1365     VTS *v3 = CreateSingleton(TID(2));
1366     VTS *v4 = CreateSingleton(TID(3));
1367 
1368     VTS *v12 = Join(v1, v2);
1369     v12->print("v12");
1370     VTS *v34 = Join(v3, v4);
1371     v34->print("v34");
1372 
1373     VTS *x1 = Parse("[0:4; 3:6; 4:2;]");
1374     CHECK(x1);
1375     x1->print("x1");
1376     TestHappensBefore();
1377   }
1378 
1379   // Parse VTS string in the form "[0:4; 3:6; 4:2;]".
Parse(const char * str)1380   static VTS *Parse(const char *str) {
1381 #if 1  // TODO(kcc): need sscanf in valgrind
1382     return NULL;
1383 #else
1384     vector<TS> vec;
1385     if (!str) return NULL;
1386     if (str[0] != '[') return NULL;
1387     str++;
1388     int tid = 0, clk = 0;
1389     int consumed = 0;
1390     while (sscanf(str, "%d:%d;%n", &tid, &clk, &consumed) > 0) {
1391       TS ts;
1392       ts.tid = TID(tid);
1393       ts.clk = clk;
1394       vec.push_back(ts);
1395       str += consumed;
1396       // Printf("%d:%d\n", tid, clk);
1397     }
1398     if (*str != ']') return NULL;
1399     VTS *res = Create(vec.size());
1400     for (size_t i = 0; i < vec.size(); i++) {
1401       res->arr_[i] = vec[i];
1402     }
1403     return res;
1404 #endif
1405   }
1406 
InitClassMembers()1407   static void InitClassMembers() {
1408     hb_cache_ = new HBCache;
1409     free_lists_ = new FreeList *[kNumberOfFreeLists+1];
1410     free_lists_[0] = 0;
1411     for (size_t  i = 1; i <= kNumberOfFreeLists; i++) {
1412       free_lists_[i] = new FreeList(MemoryRequiredForOneVts(i),
1413                                     (kNumberOfFreeLists * 4) / i);
1414     }
1415   }
1416 
uniq_id() const1417   int32_t uniq_id() const { return uniq_id_; }
1418 
1419  private:
VTS(size_t size)1420   explicit VTS(size_t size)
1421     : ref_count_(1),
1422       size_(size) {
1423     uniq_id_counter_++;
1424     // If we've got overflow, we are in trouble, need to have 64-bits...
1425     CHECK_GT(uniq_id_counter_, 0);
1426     uniq_id_ = uniq_id_counter_;
1427   }
~VTS()1428   ~VTS() {}
1429 
1430   struct TS {
1431     int32_t tid;
1432     int32_t clk;
1433   };
1434 
1435 
1436   // data members
1437   int32_t ref_count_;
1438   int32_t uniq_id_;
1439   size_t size_;
1440   TS     arr_[];  // array of size_ elements.
1441 
1442 
1443   // static data members
1444   static int32_t uniq_id_counter_;
1445   static const int kCacheSize = 4999;  // Has to be prime.
1446   typedef IntPairToBoolCache<kCacheSize> HBCache;
1447   static HBCache *hb_cache_;
1448 
1449   static const size_t kNumberOfFreeLists = 512;  // Must be power of two.
1450 //  static const size_t kNumberOfFreeLists = 64; // Must be power of two.
1451   static FreeList **free_lists_;  // Array of kNumberOfFreeLists elements.
1452 };
1453 
1454 int32_t VTS::uniq_id_counter_;
1455 VTS::HBCache *VTS::hb_cache_;
1456 FreeList **VTS::free_lists_;
1457 
1458 
1459 // This class is somewhat similar to VTS,
1460 // but it's mutable, not reference counted and not sorted.
1461 class VectorClock {
1462  public:
VectorClock()1463   VectorClock()
1464       : size_(),
1465         clock_()
1466   {
1467   }
1468 
reset()1469   void reset() {
1470     free(clock_);
1471     size_ = 0;
1472     clock_ = NULL;
1473   }
1474 
clock(TID tid) const1475   int32_t clock(TID tid) const {
1476     for (size_t i = 0; i != size_; i += 1) {
1477       if (clock_[i].tid == tid.raw()) {
1478         return clock_[i].clk;
1479       }
1480     }
1481     return 0;
1482   }
1483 
update(TID tid,int32_t clk)1484   void update(TID tid, int32_t clk) {
1485     for (size_t i = 0; i != size_; i += 1) {
1486       if (clock_[i].tid == tid.raw()) {
1487         clock_[i].clk = clk;
1488         return;
1489       }
1490     }
1491     size_ += 1;
1492     clock_ = (TS*)realloc(clock_, size_ * sizeof(TS));
1493     clock_[size_ - 1].tid = tid.raw();
1494     clock_[size_ - 1].clk = clk;
1495   }
1496 
1497  private:
1498   struct TS {
1499     int32_t tid;
1500     int32_t clk;
1501   };
1502 
1503   size_t    size_;
1504   TS*       clock_;
1505 };
1506 
1507 
1508 // -------- Mask -------------------- {{{1
1509 // A bit mask (32-bits on 32-bit arch and 64-bits on 64-bit arch).
1510 class Mask {
1511  public:
1512   static const uintptr_t kOne = 1;
1513   static const uintptr_t kNBits = sizeof(uintptr_t) * 8;
1514   static const uintptr_t kNBitsLog = kNBits == 32 ? 5 : 6;
1515 
Mask()1516   Mask() : m_(0) {}
Mask(const Mask & m)1517   Mask(const Mask &m) : m_(m.m_) { }
Mask(uintptr_t m)1518   explicit Mask(uintptr_t m) : m_(m) { }
Get(uintptr_t idx) const1519   INLINE bool Get(uintptr_t idx) const   { return m_ & (kOne << idx); }
Set(uintptr_t idx)1520   INLINE void Set(uintptr_t idx)   { m_ |= kOne << idx; }
Clear(uintptr_t idx)1521   INLINE void Clear(uintptr_t idx) { m_ &= ~(kOne << idx); }
Empty() const1522   INLINE bool Empty() const {return m_ == 0; }
1523 
1524   // Clear bits in range [a,b) and return old [a,b) range.
ClearRangeAndReturnOld(uintptr_t a,uintptr_t b)1525   INLINE Mask ClearRangeAndReturnOld(uintptr_t a, uintptr_t b) {
1526     DCHECK(a < b);
1527     DCHECK(b <= kNBits);
1528     uintptr_t res;
1529     uintptr_t n_bits_in_mask = (b - a);
1530     if (n_bits_in_mask == kNBits) {
1531       res = m_;
1532       m_ = 0;
1533     } else {
1534       uintptr_t t = (kOne << n_bits_in_mask);
1535       uintptr_t mask = (t - 1) << a;
1536       res = m_ & mask;
1537       m_ &= ~mask;
1538     }
1539     return Mask(res);
1540   }
1541 
ClearRange(uintptr_t a,uintptr_t b)1542   INLINE void ClearRange(uintptr_t a, uintptr_t b) {
1543     ClearRangeAndReturnOld(a, b);
1544   }
1545 
SetRange(uintptr_t a,uintptr_t b)1546   INLINE void SetRange(uintptr_t a, uintptr_t b) {
1547     DCHECK(a < b);
1548     DCHECK(b <= kNBits);
1549     uintptr_t n_bits_in_mask = (b - a);
1550     if (n_bits_in_mask == kNBits) {
1551       m_ = ~0;
1552     } else {
1553       uintptr_t t = (kOne << n_bits_in_mask);
1554       uintptr_t mask = (t - 1) << a;
1555       m_ |= mask;
1556     }
1557   }
1558 
GetRange(uintptr_t a,uintptr_t b) const1559   INLINE uintptr_t GetRange(uintptr_t a, uintptr_t b) const {
1560     // a bug was fixed here
1561     DCHECK(a < b);
1562     DCHECK(b <= kNBits);
1563     uintptr_t n_bits_in_mask = (b - a);
1564     if (n_bits_in_mask == kNBits) {
1565       return m_;
1566     } else {
1567       uintptr_t t = (kOne << n_bits_in_mask);
1568       uintptr_t mask = (t - 1) << a;
1569       return m_ & mask;
1570     }
1571   }
1572 
1573   // Get index of some set bit (asumes mask is non zero).
GetSomeSetBit()1574   size_t GetSomeSetBit() {
1575     DCHECK(m_);
1576     size_t ret;
1577 #ifdef __GNUC__
1578     ret =  __builtin_ctzl(m_);
1579 #elif defined(_MSC_VER)
1580     unsigned long index;
1581     DCHECK(sizeof(uintptr_t) == 4);
1582     _BitScanReverse(&index, m_);
1583     ret = index;
1584 #else
1585 # error "Unsupported"
1586 #endif
1587     DCHECK(this->Get(ret));
1588     return ret;
1589   }
1590 
PopCount()1591   size_t PopCount() {
1592 #ifdef VGO_linux
1593     return __builtin_popcountl(m_);
1594 #else
1595     CHECK(0);
1596     return 0;
1597 #endif
1598   }
1599 
Subtract(Mask m)1600   void Subtract(Mask m) { m_ &= ~m.m_; }
Union(Mask m)1601   void Union(Mask m) { m_ |= m.m_; }
1602 
Intersection(Mask m1,Mask m2)1603   static Mask Intersection(Mask m1, Mask m2) { return Mask(m1.m_ & m2.m_); }
1604 
1605 
Clear()1606   void Clear() { m_ = 0; }
1607 
1608 
ToString() const1609   string ToString() const {
1610     char buff[kNBits+1];
1611     for (uintptr_t i = 0; i < kNBits; i++) {
1612       buff[i] = Get(i) ? '1' : '0';
1613     }
1614     buff[kNBits] = 0;
1615     return buff;
1616   }
1617 
Test()1618   static void Test() {
1619     Mask m;
1620     m.Set(2);
1621     Printf("%s\n", m.ToString().c_str());
1622     m.ClearRange(0, kNBits);
1623     Printf("%s\n", m.ToString().c_str());
1624   }
1625 
1626  private:
1627   uintptr_t m_;
1628 };
1629 
1630 // -------- BitSet -------------------{{{1
1631 // Poor man's sparse bit set.
1632 class BitSet {
1633  public:
1634   // Add range [a,b). The range should be within one line (kNBitsLog).
Add(uintptr_t a,uintptr_t b)1635   void Add(uintptr_t a, uintptr_t b) {
1636     uintptr_t line = a & ~(Mask::kNBits - 1);
1637     DCHECK(a < b);
1638     DCHECK(a - line < Mask::kNBits);
1639     if (!(b - line <= Mask::kNBits)) {
1640       Printf("XXXXX %p %p %p b-line=%ld size=%ld a-line=%ld\n", a, b, line,
1641              b - line, b - a, a - line);
1642       return;
1643     }
1644     DCHECK(b - line <= Mask::kNBits);
1645     DCHECK(line == ((b - 1) & ~(Mask::kNBits - 1)));
1646     Mask &mask= map_[line];
1647     mask.SetRange(a - line, b - line);
1648   }
1649 
empty()1650   bool empty() { return map_.empty(); }
1651 
size()1652   size_t size() {
1653     size_t res = 0;
1654     for (Map::iterator it = map_.begin(); it != map_.end(); ++it) {
1655       res += it->second.PopCount();
1656     }
1657     return res;
1658   }
1659 
ToString()1660   string ToString() {
1661     char buff[100];
1662     string res;
1663     int lines = 0;
1664     snprintf(buff, sizeof(buff), " %ld lines %ld bits:",
1665              (long)map_.size(), (long)size());
1666     res += buff;
1667     for (Map::iterator it = map_.begin(); it != map_.end(); ++it) {
1668       Mask mask = it->second;
1669       snprintf(buff, sizeof(buff), " l%d (%ld):", lines++, (long)mask.PopCount());
1670       res += buff;
1671       uintptr_t line = it->first;
1672       bool is_in = false;
1673       for (size_t i = 0; i < Mask::kNBits; i++) {
1674         uintptr_t addr = line + i;
1675         if (mask.Get(i)) {
1676           if (!is_in) {
1677             snprintf(buff, sizeof(buff), " [%lx,", (long)addr);
1678             res += buff;
1679             is_in = true;
1680           }
1681         } else {
1682           if (is_in) {
1683             snprintf(buff, sizeof(buff), "%lx);", (long)addr);
1684             res += buff;
1685             is_in = false;
1686           }
1687         }
1688       }
1689       if (is_in) {
1690         snprintf(buff, sizeof(buff), "%lx);", (long)(line + Mask::kNBits));
1691         res += buff;
1692       }
1693     }
1694     return res;
1695   }
1696 
Clear()1697   void Clear() { map_.clear(); }
1698  private:
1699   typedef map<uintptr_t, Mask> Map;
1700   Map map_;
1701 };
1702 
1703 // -------- Segment -------------------{{{1
1704 class Segment {
1705  public:
1706   // for debugging...
ProfileSeg(SID sid)1707   static bool ProfileSeg(SID sid) {
1708     // return (sid.raw() % (1 << 14)) == 0;
1709     return false;
1710   }
1711 
1712   // non-static methods
1713 
vts() const1714   VTS *vts() const { return vts_; }
tid() const1715   TID tid() const { return TID(tid_); }
lsid(bool is_w) const1716   LSID  lsid(bool is_w) const { return lsid_[is_w]; }
lock_era() const1717   uint32_t lock_era() const { return lock_era_; }
1718 
1719   // static methods
1720 
embedded_stack_trace(SID sid)1721   static INLINE uintptr_t *embedded_stack_trace(SID sid) {
1722     DCHECK(sid.valid());
1723     DCHECK(kSizeOfHistoryStackTrace > 0);
1724     size_t chunk_idx = (unsigned)sid.raw() / kChunkSizeForStacks;
1725     size_t idx       = (unsigned)sid.raw() % kChunkSizeForStacks;
1726     DCHECK(chunk_idx < n_stack_chunks_);
1727     DCHECK(all_stacks_[chunk_idx] != NULL);
1728     return &all_stacks_[chunk_idx][idx * kSizeOfHistoryStackTrace];
1729   }
1730 
ensure_space_for_stack_trace(SID sid)1731   static void ensure_space_for_stack_trace(SID sid) {
1732     ScopedMallocCostCenter malloc_cc(__FUNCTION__);
1733     DCHECK(sid.valid());
1734     DCHECK(kSizeOfHistoryStackTrace > 0);
1735     size_t chunk_idx = (unsigned)sid.raw() / kChunkSizeForStacks;
1736     DCHECK(chunk_idx < n_stack_chunks_);
1737     if (all_stacks_[chunk_idx])
1738       return;
1739     for (size_t i = 0; i <= chunk_idx; i++) {
1740       if (all_stacks_[i]) continue;
1741       all_stacks_[i] = new uintptr_t[
1742           kChunkSizeForStacks * kSizeOfHistoryStackTrace];
1743       // we don't clear this memory, it will be clreared later lazily.
1744       // We also never delete it because it will be used until the very end.
1745     }
1746   }
1747 
StackTraceString(SID sid)1748   static string StackTraceString(SID sid) {
1749     DCHECK(kSizeOfHistoryStackTrace > 0);
1750     return StackTrace::EmbeddedStackTraceToString(
1751         embedded_stack_trace(sid), kSizeOfHistoryStackTrace);
1752   }
1753 
1754   // Allocate `n` fresh segments, put SIDs into `fresh_sids`.
AllocateFreshSegments(size_t n,SID * fresh_sids)1755   static INLINE void AllocateFreshSegments(size_t n, SID *fresh_sids) {
1756     ScopedMallocCostCenter malloc_cc(__FUNCTION__);
1757     size_t i = 0;
1758     size_t n_reusable = min(n, reusable_sids_->size());
1759     // First, allocate from reusable_sids_.
1760     for (; i < n_reusable; i++) {
1761       G_stats->seg_reuse++;
1762       DCHECK(!reusable_sids_->empty());
1763       SID sid = reusable_sids_->back();
1764       reusable_sids_->pop_back();
1765       Segment *seg = GetInternal(sid);
1766       DCHECK(!seg->seg_ref_count_);
1767       DCHECK(!seg->vts());
1768       DCHECK(!seg->tid().valid());
1769       CHECK(sid.valid());
1770       if (ProfileSeg(sid)) {
1771        Printf("Segment: reused SID %d\n", sid.raw());
1772       }
1773       fresh_sids[i] = sid;
1774     }
1775     // allocate the rest from new sids.
1776     for (; i < n; i++) {
1777       G_stats->seg_create++;
1778       CHECK(n_segments_ < kMaxSID);
1779       Segment *seg = GetSegmentByIndex(n_segments_);
1780 
1781       // This VTS may not be empty due to ForgetAllState().
1782       VTS::Unref(seg->vts_);
1783       seg->vts_ = 0;
1784       seg->seg_ref_count_ = 0;
1785 
1786       if (ProfileSeg(SID(n_segments_))) {
1787        Printf("Segment: allocated SID %d\n", n_segments_);
1788       }
1789 
1790       SID sid = fresh_sids[i] = SID(n_segments_);
1791       if (kSizeOfHistoryStackTrace > 0) {
1792         ensure_space_for_stack_trace(sid);
1793       }
1794       n_segments_++;
1795     }
1796   }
1797 
1798   // Initialize the contents of the given segment.
SetupFreshSid(SID sid,TID tid,VTS * vts,LSID rd_lockset,LSID wr_lockset)1799   static INLINE void SetupFreshSid(SID sid, TID tid, VTS *vts,
1800                                    LSID rd_lockset, LSID wr_lockset) {
1801     DCHECK(vts);
1802     DCHECK(tid.valid());
1803     DCHECK(sid.valid());
1804     Segment *seg = GetInternal(sid);
1805     DCHECK(seg);
1806     DCHECK(seg->seg_ref_count_ == 0);
1807     seg->seg_ref_count_ = 0;
1808     seg->tid_ = tid;
1809     seg->lsid_[0] = rd_lockset;
1810     seg->lsid_[1] = wr_lockset;
1811     seg->vts_ = vts;
1812     seg->lock_era_ = g_lock_era;
1813     if (kSizeOfHistoryStackTrace) {
1814       embedded_stack_trace(sid)[0] = 0;
1815     }
1816   }
1817 
AddNewSegment(TID tid,VTS * vts,LSID rd_lockset,LSID wr_lockset)1818   static INLINE SID AddNewSegment(TID tid, VTS *vts,
1819                            LSID rd_lockset, LSID wr_lockset) {
1820     ScopedMallocCostCenter malloc_cc("Segment::AddNewSegment()");
1821     SID sid;
1822     AllocateFreshSegments(1, &sid);
1823     SetupFreshSid(sid, tid, vts, rd_lockset, wr_lockset);
1824     return sid;
1825   }
1826 
Alive(SID sid)1827   static bool Alive(SID sid) {
1828     Segment *seg = GetInternal(sid);
1829     return seg->vts() != NULL;
1830   }
1831 
AssertLive(SID sid,int line)1832   static void AssertLive(SID sid, int line) {
1833     if (DEBUG_MODE) {
1834       if (!(sid.raw() < INTERNAL_ANNOTATE_UNPROTECTED_READ(n_segments_))) {
1835         Printf("Segment::AssertLive: failed on sid=%d n_segments = %dline=%d\n",
1836                sid.raw(), n_segments_, line);
1837       }
1838       Segment *seg = GetInternal(sid);
1839       if (!seg->vts()) {
1840         Printf("Segment::AssertLive: failed on sid=%d line=%d\n",
1841                sid.raw(), line);
1842       }
1843       DCHECK(seg->vts());
1844       DCHECK(seg->tid().valid());
1845     }
1846   }
1847 
Get(SID sid)1848   static INLINE Segment *Get(SID sid) {
1849     AssertLive(sid, __LINE__);
1850     Segment *res = GetInternal(sid);
1851     DCHECK(res->vts());
1852     DCHECK(res->tid().valid());
1853     return res;
1854   }
1855 
RecycleOneFreshSid(SID sid)1856   static INLINE void RecycleOneFreshSid(SID sid) {
1857     Segment *seg = GetInternal(sid);
1858     seg->tid_ = TID();
1859     seg->vts_ = NULL;
1860     reusable_sids_->push_back(sid);
1861     if (ProfileSeg(sid)) {
1862       Printf("Segment: recycled SID %d\n", sid.raw());
1863     }
1864   }
1865 
RecycleOneSid(SID sid)1866   static bool RecycleOneSid(SID sid) {
1867     ScopedMallocCostCenter malloc_cc("Segment::RecycleOneSid()");
1868     Segment *seg = GetInternal(sid);
1869     DCHECK(seg->seg_ref_count_ == 0);
1870     DCHECK(sid.raw() < n_segments_);
1871     if (!seg->vts()) return false;  // Already recycled.
1872     VTS::Unref(seg->vts_);
1873     RecycleOneFreshSid(sid);
1874     return true;
1875   }
1876 
ref_count() const1877   int32_t ref_count() const {
1878     return INTERNAL_ANNOTATE_UNPROTECTED_READ(seg_ref_count_);
1879   }
1880 
Ref(SID sid,const char * where)1881   static void INLINE Ref(SID sid, const char *where) {
1882     Segment *seg = GetInternal(sid);
1883     if (ProfileSeg(sid)) {
1884       Printf("SegRef   : %d ref=%d %s; tid=%d\n", sid.raw(),
1885              seg->seg_ref_count_, where, seg->tid().raw());
1886     }
1887     DCHECK(seg->seg_ref_count_ >= 0);
1888     AtomicIncrementRefcount(&seg->seg_ref_count_);
1889   }
1890 
UnrefNoRecycle(SID sid,const char * where)1891   static INLINE intptr_t UnrefNoRecycle(SID sid, const char *where) {
1892     Segment *seg = GetInternal(sid);
1893     if (ProfileSeg(sid)) {
1894       Printf("SegUnref : %d ref=%d %s\n", sid.raw(), seg->seg_ref_count_, where);
1895     }
1896     DCHECK(seg->seg_ref_count_ > 0);
1897     return AtomicDecrementRefcount(&seg->seg_ref_count_);
1898   }
1899 
Unref(SID sid,const char * where)1900   static void INLINE Unref(SID sid, const char *where) {
1901     if (UnrefNoRecycle(sid, where) == 0) {
1902       RecycleOneSid(sid);
1903     }
1904   }
1905 
1906 
ForgetAllState()1907   static void ForgetAllState() {
1908     n_segments_ = 1;
1909     reusable_sids_->clear();
1910     // vts_'es will be freed in AddNewSegment.
1911   }
1912 
ToString(SID sid)1913   static string ToString(SID sid) {
1914     char buff[100];
1915     snprintf(buff, sizeof(buff), "T%d/S%d", Get(sid)->tid().raw(), sid.raw());
1916     return buff;
1917   }
1918 
ToStringTidOnly(SID sid)1919   static string ToStringTidOnly(SID sid) {
1920     char buff[100];
1921     snprintf(buff, sizeof(buff), "T%d", Get(sid)->tid().raw());
1922     return buff;
1923   }
1924 
ToStringWithLocks(SID sid)1925   static string ToStringWithLocks(SID sid) {
1926     char buff[100];
1927     Segment *seg = Get(sid);
1928     snprintf(buff, sizeof(buff), "T%d/S%d ", seg->tid().raw(), sid.raw());
1929     string res = buff;
1930     res += TwoLockSetsToString(seg->lsid(false), seg->lsid(true));
1931     return res;
1932   }
1933 
HappensBeforeOrSameThread(SID a,SID b)1934   static bool INLINE HappensBeforeOrSameThread(SID a, SID b) {
1935     if (a == b) return true;
1936     if (Get(a)->tid() == Get(b)->tid()) return true;
1937     return HappensBefore(a, b);
1938   }
1939 
HappensBefore(SID a,SID b)1940   static bool INLINE HappensBefore(SID a, SID b) {
1941     DCHECK(a != b);
1942     G_stats->n_seg_hb++;
1943     bool res = false;
1944     const Segment *seg_a = Get(a);
1945     const Segment *seg_b = Get(b);
1946     DCHECK(seg_a->tid() != seg_b->tid());
1947     const VTS *vts_a = seg_a->vts();
1948     const VTS *vts_b = seg_b->vts();
1949     res = VTS::HappensBeforeCached(vts_a, vts_b);
1950 #if 0
1951     if (DEBUG_MODE) {
1952       Printf("HB = %d\n  %s\n  %s\n", res,
1953            vts_a->ToString().c_str(), vts_b->ToString().c_str());
1954     }
1955 #endif
1956     return res;
1957   }
1958 
NumberOfSegments()1959   static int32_t NumberOfSegments() { return n_segments_; }
1960 
ShowSegmentStats()1961   static void ShowSegmentStats() {
1962     Printf("Segment::ShowSegmentStats:\n");
1963     Printf("n_segments_: %d\n", n_segments_);
1964     Printf("reusable_sids_: %ld\n", reusable_sids_->size());
1965     map<int, int> ref_to_freq_map;
1966     for (int i = 1; i < n_segments_; i++) {
1967       Segment *seg = GetInternal(SID(i));
1968       int32_t refcount = seg->seg_ref_count_;
1969       if (refcount > 10) refcount = 10;
1970       ref_to_freq_map[refcount]++;
1971     }
1972     for (map<int, int>::iterator it = ref_to_freq_map.begin();
1973          it != ref_to_freq_map.end(); ++it) {
1974       Printf("ref %d => freq %d\n", it->first, it->second);
1975     }
1976   }
1977 
InitClassMembers()1978   static void InitClassMembers() {
1979     if (G_flags->keep_history == 0)
1980       kSizeOfHistoryStackTrace = 0;
1981     Report("INFO: Allocating %ldMb (%ld * %ldM) for Segments.\n",
1982            (sizeof(Segment) * kMaxSID) >> 20,
1983            sizeof(Segment), kMaxSID >> 20);
1984     if (kSizeOfHistoryStackTrace) {
1985       Report("INFO: Will allocate up to %ldMb for 'previous' stack traces.\n",
1986              (kSizeOfHistoryStackTrace * sizeof(uintptr_t) * kMaxSID) >> 20);
1987     }
1988 
1989     all_segments_  = new Segment[kMaxSID];
1990     // initialization all segments to 0.
1991     memset(all_segments_, 0, kMaxSID * sizeof(Segment));
1992     // initialize all_segments_[0] with garbage
1993     memset(all_segments_, -1, sizeof(Segment));
1994 
1995     if (kSizeOfHistoryStackTrace > 0) {
1996       n_stack_chunks_ = kMaxSID / kChunkSizeForStacks;
1997       if (n_stack_chunks_ * kChunkSizeForStacks < (size_t)kMaxSID)
1998         n_stack_chunks_++;
1999       all_stacks_ = new uintptr_t*[n_stack_chunks_];
2000       memset(all_stacks_, 0, sizeof(uintptr_t*) * n_stack_chunks_);
2001     }
2002     n_segments_    = 1;
2003     reusable_sids_ = new vector<SID>;
2004   }
2005 
2006  private:
GetSegmentByIndex(int32_t index)2007   static INLINE Segment *GetSegmentByIndex(int32_t index) {
2008     return &all_segments_[index];
2009   }
GetInternal(SID sid)2010   static INLINE Segment *GetInternal(SID sid) {
2011     DCHECK(sid.valid());
2012     DCHECK(sid.raw() < INTERNAL_ANNOTATE_UNPROTECTED_READ(n_segments_));
2013     Segment *res = GetSegmentByIndex(sid.raw());
2014     return res;
2015   }
2016 
2017   // Data members.
2018   int32_t seg_ref_count_;
2019   LSID     lsid_[2];
2020   TID      tid_;
2021   uint32_t lock_era_;
2022   VTS *vts_;
2023 
2024   // static class members.
2025 
2026   // One large array of segments. The size is set by a command line (--max-sid)
2027   // and never changes. Once we are out of vacant segments, we flush the state.
2028   static Segment *all_segments_;
2029   // We store stack traces separately because their size is unknown
2030   // at compile time and because they are needed less often.
2031   // The stacks are stored as an array of chunks, instead of one array,
2032   // so that for small tests we do not require too much RAM.
2033   // We don't use vector<> or another resizable array to avoid expensive
2034   // resizing.
2035   enum { kChunkSizeForStacks = DEBUG_MODE ? 512 : 1 * 1024 * 1024 };
2036   static uintptr_t **all_stacks_;
2037   static size_t      n_stack_chunks_;
2038 
2039   static int32_t n_segments_;
2040   static vector<SID> *reusable_sids_;
2041 };
2042 
2043 Segment          *Segment::all_segments_;
2044 uintptr_t       **Segment::all_stacks_;
2045 size_t            Segment::n_stack_chunks_;
2046 int32_t           Segment::n_segments_;
2047 vector<SID>      *Segment::reusable_sids_;
2048 
2049 // -------- SegmentSet -------------- {{{1
2050 class SegmentSet {
2051  public:
2052   static NOINLINE SSID AddSegmentToSS(SSID old_ssid, SID new_sid);
2053   static NOINLINE SSID RemoveSegmentFromSS(SSID old_ssid, SID sid_to_remove);
2054 
2055   static INLINE SSID AddSegmentToTupleSS(SSID ssid, SID new_sid);
2056   static INLINE SSID RemoveSegmentFromTupleSS(SSID old_ssid, SID sid_to_remove);
2057 
ComputeSSID()2058   SSID ComputeSSID() {
2059     SSID res = map_->GetIdOrZero(this);
2060     CHECK_NE(res.raw(), 0);
2061     return res;
2062   }
2063 
ref_count() const2064   int ref_count() const { return ref_count_; }
2065 
AssertLive(SSID ssid,int line)2066   static void AssertLive(SSID ssid, int line) {
2067     DCHECK(ssid.valid());
2068     if (DEBUG_MODE) {
2069       if (ssid.IsSingleton()) {
2070         Segment::AssertLive(ssid.GetSingleton(), line);
2071       } else {
2072         DCHECK(ssid.IsTuple());
2073         int idx = -ssid.raw()-1;
2074         DCHECK(idx < static_cast<int>(vec_->size()));
2075         DCHECK(idx >= 0);
2076         SegmentSet *res = (*vec_)[idx];
2077         DCHECK(res);
2078         DCHECK(res->ref_count_ >= 0);
2079         res->Validate(line);
2080 
2081         if (!res) {
2082           Printf("SegmentSet::AssertLive failed at line %d (ssid=%d)\n",
2083                  line, ssid.raw());
2084           DCHECK(0);
2085         }
2086       }
2087     }
2088   }
2089 
Get(SSID ssid)2090   static SegmentSet *Get(SSID ssid) {
2091     DCHECK(ssid.valid());
2092     DCHECK(!ssid.IsSingleton());
2093     int idx = -ssid.raw()-1;
2094     ANNOTATE_IGNORE_READS_BEGIN();
2095     DCHECK(idx < static_cast<int>(vec_->size()) && idx >= 0);
2096     ANNOTATE_IGNORE_READS_END();
2097     SegmentSet *res = (*vec_)[idx];
2098     DCHECK(res);
2099     DCHECK(res->size() >= 2);
2100     return res;
2101   }
2102 
RecycleOneSegmentSet(SSID ssid)2103   void RecycleOneSegmentSet(SSID ssid) {
2104     DCHECK(ref_count_ == 0);
2105     DCHECK(ssid.valid());
2106     DCHECK(!ssid.IsSingleton());
2107     int idx = -ssid.raw()-1;
2108     DCHECK(idx < static_cast<int>(vec_->size()) && idx >= 0);
2109     CHECK((*vec_)[idx] == this);
2110     // Printf("SegmentSet::RecycleOneSegmentSet: %d\n", ssid.raw());
2111     //
2112     // Recycle segments
2113     for (int i = 0; i < kMaxSegmentSetSize; i++) {
2114       SID sid = this->GetSID(i);
2115       if (sid.raw() == 0) break;
2116       Segment::Unref(sid, "SegmentSet::Recycle");
2117     }
2118     ref_count_ = -1;
2119 
2120     map_->Erase(this);
2121     ready_to_be_reused_->push_back(ssid);
2122     G_stats->ss_recycle++;
2123   }
2124 
Ref(SSID ssid,const char * where)2125   static void INLINE Ref(SSID ssid, const char *where) {
2126     AssertTILHeld(); // The reference counting logic below is not thread-safe
2127     DCHECK(ssid.valid());
2128     if (ssid.IsSingleton()) {
2129       Segment::Ref(ssid.GetSingleton(), where);
2130     } else {
2131       SegmentSet *sset = Get(ssid);
2132       // Printf("SSRef   : %d ref=%d %s\n", ssid.raw(), sset->ref_count_, where);
2133       DCHECK(sset->ref_count_ >= 0);
2134       sset->ref_count_++;
2135     }
2136   }
2137 
Unref(SSID ssid,const char * where)2138   static void INLINE Unref(SSID ssid, const char *where) {
2139     AssertTILHeld(); // The reference counting logic below is not thread-safe
2140     DCHECK(ssid.valid());
2141     if (ssid.IsSingleton()) {
2142       Segment::Unref(ssid.GetSingleton(), where);
2143     } else {
2144       SegmentSet *sset = Get(ssid);
2145       // Printf("SSUnref : %d ref=%d %s\n", ssid.raw(), sset->ref_count_, where);
2146       DCHECK(sset->ref_count_ > 0);
2147       sset->ref_count_--;
2148       if (sset->ref_count_ == 0) {
2149         // We don't delete unused SSID straightaway due to performance reasons
2150         // (to avoid flushing caches too often and because SSID may be reused
2151         // again soon)
2152         //
2153         // Instead, we use two queues (deques):
2154         //    ready_to_be_recycled_ and ready_to_be_reused_.
2155         // The algorithm is following:
2156         // 1) When refcount_ becomes zero, we push the SSID into
2157         //    ready_to_be_recycled_.
2158         // 2) When ready_to_be_recycled_ becomes too large, we call
2159         //    FlushRecycleQueue().
2160         //    In FlushRecycleQueue(), we pop the first half of
2161         //    ready_to_be_recycled_ and for each popped SSID we do
2162         //     * if "refcount_ > 0", do nothing (this SSID is in use again)
2163         //     * otherwise, we recycle this SSID (delete its VTS, etc) and push
2164         //       it into ready_to_be_reused_
2165         // 3) When a new SegmentSet is about to be created, we re-use SSID from
2166         //    ready_to_be_reused_ (if available)
2167         ready_to_be_recycled_->push_back(ssid);
2168         if (UNLIKELY(ready_to_be_recycled_->size() >
2169                      2 * G_flags->segment_set_recycle_queue_size)) {
2170           FlushRecycleQueue();
2171         }
2172       }
2173     }
2174   }
2175 
FlushRecycleQueue()2176   static void FlushRecycleQueue() {
2177     while (ready_to_be_recycled_->size() >
2178         G_flags->segment_set_recycle_queue_size) {
2179       SSID rec_ssid = ready_to_be_recycled_->front();
2180       ready_to_be_recycled_->pop_front();
2181       int idx = -rec_ssid.raw()-1;
2182       SegmentSet *rec_ss = (*vec_)[idx];
2183       DCHECK(rec_ss);
2184       DCHECK(rec_ss == Get(rec_ssid));
2185       // We should check that this SSID haven't been referenced again.
2186       if (rec_ss->ref_count_ == 0) {
2187         rec_ss->RecycleOneSegmentSet(rec_ssid);
2188       }
2189     }
2190 
2191     // SSIDs will be reused soon - need to flush some caches.
2192     FlushCaches();
2193   }
2194 
2195   string ToString() const;
Print()2196   void Print() {
2197     Printf("SS%d:%s\n", -ComputeSSID().raw(), ToString().c_str());
2198   }
2199 
ToString(SSID ssid)2200   static string ToString(SSID ssid) {
2201     CHECK(ssid.IsValidOrEmpty());
2202     if (ssid.IsSingleton()) {
2203       return "{" +  Segment::ToStringTidOnly(SID(ssid.raw())) + "}";
2204     } else if (ssid.IsEmpty()) {
2205       return "{}";
2206     } else {
2207       AssertLive(ssid, __LINE__);
2208       return Get(ssid)->ToString();
2209     }
2210   }
2211 
2212 
2213   static string ToStringWithLocks(SSID ssid);
2214 
FlushCaches()2215   static void FlushCaches() {
2216     add_segment_cache_->Flush();
2217     remove_segment_cache_->Flush();
2218   }
2219 
ForgetAllState()2220   static void ForgetAllState() {
2221     for (size_t i = 0; i < vec_->size(); i++) {
2222       delete (*vec_)[i];
2223     }
2224     map_->Clear();
2225     vec_->clear();
2226     ready_to_be_reused_->clear();
2227     ready_to_be_recycled_->clear();
2228     FlushCaches();
2229   }
2230 
2231 
2232   static void Test();
2233 
Size(SSID ssid)2234   static int32_t Size(SSID ssid) {
2235     if (ssid.IsEmpty()) return 0;
2236     if (ssid.IsSingleton()) return 1;
2237     return Get(ssid)->size();
2238   }
2239 
GetSID(int32_t i) const2240   SID GetSID(int32_t i) const {
2241     DCHECK(i >= 0 && i < kMaxSegmentSetSize);
2242     DCHECK(i == 0 || sids_[i-1].raw() != 0);
2243     return sids_[i];
2244   }
2245 
SetSID(int32_t i,SID sid)2246   void SetSID(int32_t i, SID sid) {
2247     DCHECK(i >= 0 && i < kMaxSegmentSetSize);
2248     DCHECK(i == 0 || sids_[i-1].raw() != 0);
2249     sids_[i] = sid;
2250   }
2251 
GetSID(SSID ssid,int32_t i,int line)2252   static SID GetSID(SSID ssid, int32_t i, int line) {
2253     DCHECK(ssid.valid());
2254     if (ssid.IsSingleton()) {
2255       DCHECK(i == 0);
2256       Segment::AssertLive(ssid.GetSingleton(), line);
2257       return ssid.GetSingleton();
2258     } else {
2259       AssertLive(ssid, __LINE__);
2260       SID sid = Get(ssid)->GetSID(i);
2261       Segment::AssertLive(sid, line);
2262       return sid;
2263     }
2264   }
2265 
Contains(SSID ssid,SID seg)2266   static bool INLINE Contains(SSID ssid, SID seg) {
2267     if (LIKELY(ssid.IsSingleton())) {
2268       return ssid.GetSingleton() == seg;
2269     } else if (LIKELY(ssid.IsEmpty())) {
2270       return false;
2271     }
2272 
2273     SegmentSet *ss = Get(ssid);
2274     for (int i = 0; i < kMaxSegmentSetSize; i++) {
2275       SID sid = ss->GetSID(i);
2276       if (sid.raw() == 0) break;
2277       if (sid == seg)
2278         return true;
2279     }
2280     return false;
2281   }
2282 
GetSegmentForNonSingleton(SSID ssid,int32_t i,int line)2283   static Segment *GetSegmentForNonSingleton(SSID ssid, int32_t i, int line) {
2284     return Segment::Get(GetSID(ssid, i, line));
2285   }
2286 
2287   void NOINLINE Validate(int line) const;
2288 
NumberOfSegmentSets()2289   static size_t NumberOfSegmentSets() { return vec_->size(); }
2290 
2291 
InitClassMembers()2292   static void InitClassMembers() {
2293     map_    = new Map;
2294     vec_    = new vector<SegmentSet *>;
2295     ready_to_be_recycled_ = new deque<SSID>;
2296     ready_to_be_reused_ = new deque<SSID>;
2297     add_segment_cache_ = new SsidSidToSidCache;
2298     remove_segment_cache_ = new SsidSidToSidCache;
2299   }
2300 
2301  private:
SegmentSet()2302   SegmentSet()  // Private CTOR
2303     : ref_count_(0) {
2304     // sids_ are filled with zeroes due to SID default CTOR.
2305     if (DEBUG_MODE) {
2306       for (int i = 0; i < kMaxSegmentSetSize; i++)
2307         CHECK_EQ(sids_[i].raw(), 0);
2308     }
2309   }
2310 
size() const2311   int size() const {
2312     for (int i = 0; i < kMaxSegmentSetSize; i++) {
2313       if (sids_[i].raw() == 0) {
2314         CHECK_GE(i, 2);
2315         return i;
2316       }
2317     }
2318     return kMaxSegmentSetSize;
2319   }
2320 
AllocateAndCopy(SegmentSet * ss)2321   static INLINE SSID AllocateAndCopy(SegmentSet *ss) {
2322     DCHECK(ss->ref_count_ == 0);
2323     DCHECK(sizeof(int32_t) == sizeof(SID));
2324     SSID res_ssid;
2325     SegmentSet *res_ss = 0;
2326 
2327     if (!ready_to_be_reused_->empty()) {
2328       res_ssid = ready_to_be_reused_->front();
2329       ready_to_be_reused_->pop_front();
2330       int idx = -res_ssid.raw()-1;
2331       res_ss = (*vec_)[idx];
2332       DCHECK(res_ss);
2333       DCHECK(res_ss->ref_count_ == -1);
2334       G_stats->ss_reuse++;
2335       for (int i = 0; i < kMaxSegmentSetSize; i++) {
2336         res_ss->sids_[i] = SID(0);
2337       }
2338     } else {
2339       // create a new one
2340       ScopedMallocCostCenter cc("SegmentSet::CreateNewSegmentSet");
2341       G_stats->ss_create++;
2342       res_ss = new SegmentSet;
2343       vec_->push_back(res_ss);
2344       res_ssid = SSID(-((int32_t)vec_->size()));
2345       CHECK(res_ssid.valid());
2346     }
2347     DCHECK(res_ss);
2348     res_ss->ref_count_ = 0;
2349     for (int i = 0; i < kMaxSegmentSetSize; i++) {
2350       SID sid = ss->GetSID(i);
2351       if (sid.raw() == 0) break;
2352       Segment::Ref(sid, "SegmentSet::FindExistingOrAlocateAndCopy");
2353       res_ss->SetSID(i, sid);
2354     }
2355     DCHECK(res_ss == Get(res_ssid));
2356     map_->Insert(res_ss, res_ssid);
2357     return res_ssid;
2358   }
2359 
FindExistingOrAlocateAndCopy(SegmentSet * ss)2360   static NOINLINE SSID FindExistingOrAlocateAndCopy(SegmentSet *ss) {
2361     if (DEBUG_MODE) {
2362       int size = ss->size();
2363       if (size == 2) G_stats->ss_size_2++;
2364       if (size == 3) G_stats->ss_size_3++;
2365       if (size == 4) G_stats->ss_size_4++;
2366       if (size > 4) G_stats->ss_size_other++;
2367     }
2368 
2369     // First, check if there is such set already.
2370     SSID ssid = map_->GetIdOrZero(ss);
2371     if (ssid.raw() != 0) {  // Found.
2372       AssertLive(ssid, __LINE__);
2373       G_stats->ss_find++;
2374       return ssid;
2375     }
2376     // If no such set, create one.
2377     return AllocateAndCopy(ss);
2378   }
2379 
DoubletonSSID(SID sid1,SID sid2)2380   static INLINE SSID DoubletonSSID(SID sid1, SID sid2) {
2381     SegmentSet tmp;
2382     tmp.SetSID(0, sid1);
2383     tmp.SetSID(1, sid2);
2384     return FindExistingOrAlocateAndCopy(&tmp);
2385   }
2386 
2387   // testing only
AddSegmentToTupleSS(SegmentSet * ss,SID new_sid)2388   static SegmentSet *AddSegmentToTupleSS(SegmentSet *ss, SID new_sid) {
2389     SSID ssid = AddSegmentToTupleSS(ss->ComputeSSID(), new_sid);
2390     AssertLive(ssid, __LINE__);
2391     return Get(ssid);
2392   }
2393 
Doubleton(SID sid1,SID sid2)2394   static SegmentSet *Doubleton(SID sid1, SID sid2) {
2395     SSID ssid = DoubletonSSID(sid1, sid2);
2396     AssertLive(ssid, __LINE__);
2397     return Get(ssid);
2398   }
2399 
2400   // static data members
2401   struct Less {
operator ()SegmentSet::Less2402     INLINE bool operator() (const SegmentSet *ss1,
2403                             const SegmentSet *ss2) const {
2404       for (int i = 0; i < kMaxSegmentSetSize; i++) {
2405         SID sid1 = ss1->sids_[i],
2406             sid2 = ss2->sids_[i];
2407         if (sid1 != sid2) return sid1 < sid2;
2408       }
2409       return false;
2410     }
2411   };
2412 
2413   struct SSEq {
operator ()SegmentSet::SSEq2414     INLINE bool operator() (const SegmentSet *ss1,
2415                             const SegmentSet *ss2) const {
2416       G_stats->sseq_calls++;
2417 
2418       for (int i = 0; i < kMaxSegmentSetSize; i++) {
2419         SID sid1 = ss1->sids_[i],
2420             sid2 = ss2->sids_[i];
2421         if (sid1 != sid2) return false;
2422       }
2423       return true;
2424     }
2425   };
2426 
2427   struct SSHash {
operator ()SegmentSet::SSHash2428     INLINE size_t operator() (const SegmentSet *ss) const {
2429       uintptr_t res = 0;
2430       uint32_t* sids_array = (uint32_t*)ss->sids_;
2431       // We must have even number of SIDs.
2432       DCHECK((kMaxSegmentSetSize % 2) == 0);
2433 
2434       G_stats->sshash_calls++;
2435       // xor all SIDs together, half of them bswap-ed.
2436       for (int i = 0; i < kMaxSegmentSetSize; i += 2) {
2437         uintptr_t t1 = sids_array[i];
2438         uintptr_t t2 = sids_array[i+1];
2439         if (t2) t2 = tsan_bswap(t2);
2440         res = res ^ t1 ^ t2;
2441       }
2442       return res;
2443     }
2444   };
2445 
2446   struct SSTraits {
2447     enum {
2448       // These values are taken from the hash_compare defaults.
2449       bucket_size = 4,  // Must be greater than zero.
2450       min_buckets = 8,  // Must be power of 2.
2451     };
2452 
operator ()SegmentSet::SSTraits2453     INLINE size_t operator()(const SegmentSet *ss) const {
2454       SSHash sshash;
2455       return sshash(ss);
2456     }
2457 
operator ()SegmentSet::SSTraits2458     INLINE bool operator()(const SegmentSet *ss1, const SegmentSet *ss2) const {
2459       Less less;
2460       return less(ss1, ss2);
2461     }
2462   };
2463 
2464   template <class MapType>
GetIdOrZeroFromMap(MapType * map,SegmentSet * ss)2465   static SSID GetIdOrZeroFromMap(MapType *map, SegmentSet *ss) {
2466     typename MapType::iterator it = map->find(ss);
2467     if (it == map->end())
2468       return SSID(0);
2469     return it->second;
2470   }
2471 
2472   class Map {
2473    public:
GetIdOrZero(SegmentSet * ss)2474     SSID GetIdOrZero(SegmentSet *ss) {
2475       return GetIdOrZeroFromMap(&map_, ss);
2476     }
2477 
Insert(SegmentSet * ss,SSID id)2478     void Insert(SegmentSet *ss, SSID id) {
2479       map_[ss] = id;
2480     }
2481 
Erase(SegmentSet * ss)2482     void Erase(SegmentSet *ss) {
2483       CHECK(map_.erase(ss));
2484     }
2485 
Clear()2486     void Clear() {
2487       map_.clear();
2488     }
2489 
2490    private:
2491     // TODO(timurrrr): consider making a custom hash_table.
2492 #if defined(_MSC_VER)
2493     typedef stdext::hash_map<SegmentSet*, SSID, SSTraits > MapType__;
2494 #elif 1
2495     typedef unordered_map<SegmentSet*, SSID, SSHash, SSEq > MapType__;
2496 #else
2497     // Old code, may be useful for debugging.
2498     typedef map<SegmentSet*, SSID, Less > MapType__;
2499 #endif
2500     MapType__ map_;
2501   };
2502 
2503 //  typedef map<SegmentSet*, SSID, Less> Map;
2504 
2505   static Map                  *map_;
2506   // TODO(kcc): use vector<SegmentSet> instead.
2507   static vector<SegmentSet *> *vec_;
2508   static deque<SSID>         *ready_to_be_reused_;
2509   static deque<SSID>         *ready_to_be_recycled_;
2510 
2511   typedef PairCache<SSID, SID, SSID, 1009, 1> SsidSidToSidCache;
2512   static SsidSidToSidCache    *add_segment_cache_;
2513   static SsidSidToSidCache    *remove_segment_cache_;
2514 
2515   // sids_ contains up to kMaxSegmentSetSize SIDs.
2516   // Contains zeros at the end if size < kMaxSegmentSetSize.
2517   SID     sids_[kMaxSegmentSetSize];
2518   int32_t ref_count_;
2519 };
2520 
2521 SegmentSet::Map      *SegmentSet::map_;
2522 vector<SegmentSet *> *SegmentSet::vec_;
2523 deque<SSID>         *SegmentSet::ready_to_be_reused_;
2524 deque<SSID>         *SegmentSet::ready_to_be_recycled_;
2525 SegmentSet::SsidSidToSidCache    *SegmentSet::add_segment_cache_;
2526 SegmentSet::SsidSidToSidCache    *SegmentSet::remove_segment_cache_;
2527 
2528 
2529 
2530 
RemoveSegmentFromSS(SSID old_ssid,SID sid_to_remove)2531 SSID SegmentSet::RemoveSegmentFromSS(SSID old_ssid, SID sid_to_remove) {
2532   DCHECK(old_ssid.IsValidOrEmpty());
2533   DCHECK(sid_to_remove.valid());
2534   SSID res;
2535   if (remove_segment_cache_->Lookup(old_ssid, sid_to_remove, &res)) {
2536     return res;
2537   }
2538 
2539   if (old_ssid.IsEmpty()) {
2540     res = old_ssid;  // Nothing to remove.
2541   } else if (LIKELY(old_ssid.IsSingleton())) {
2542     SID sid = old_ssid.GetSingleton();
2543     if (Segment::HappensBeforeOrSameThread(sid, sid_to_remove))
2544       res = SSID(0);  // Empty.
2545     else
2546       res = old_ssid;
2547   } else {
2548     res = RemoveSegmentFromTupleSS(old_ssid, sid_to_remove);
2549   }
2550   remove_segment_cache_->Insert(old_ssid, sid_to_remove, res);
2551   return res;
2552 }
2553 
2554 
2555 // static
2556 //
2557 // This method returns a SSID of a SegmentSet containing "new_sid" and all those
2558 // segments from "old_ssid" which do not happen-before "new_sid".
2559 //
2560 // For details, see
2561 // http://code.google.com/p/data-race-test/wiki/ThreadSanitizerAlgorithm#State_machine
AddSegmentToSS(SSID old_ssid,SID new_sid)2562 SSID SegmentSet::AddSegmentToSS(SSID old_ssid, SID new_sid) {
2563   DCHECK(old_ssid.raw() == 0 || old_ssid.valid());
2564   DCHECK(new_sid.valid());
2565   Segment::AssertLive(new_sid, __LINE__);
2566   SSID res;
2567 
2568   // These two TIDs will only be used if old_ssid.IsSingleton() == true.
2569   TID old_tid;
2570   TID new_tid;
2571 
2572   if (LIKELY(old_ssid.IsSingleton())) {
2573     SID old_sid(old_ssid.raw());
2574     DCHECK(old_sid.valid());
2575     Segment::AssertLive(old_sid, __LINE__);
2576 
2577     if (UNLIKELY(old_sid == new_sid)) {
2578       // The new segment equals the old one - nothing has changed.
2579       return old_ssid;
2580     }
2581 
2582     old_tid = Segment::Get(old_sid)->tid();
2583     new_tid = Segment::Get(new_sid)->tid();
2584     if (LIKELY(old_tid == new_tid)) {
2585       // The new segment is in the same thread - just replace the SID.
2586       return SSID(new_sid);
2587     }
2588 
2589     if (Segment::HappensBefore(old_sid, new_sid)) {
2590       // The new segment is in another thread, but old segment
2591       // happens before the new one - just replace the SID.
2592       return SSID(new_sid);
2593     }
2594 
2595     DCHECK(!Segment::HappensBefore(new_sid, old_sid));
2596     // The only other case is Signleton->Doubleton transition, see below.
2597   } else if (LIKELY(old_ssid.IsEmpty())) {
2598     return SSID(new_sid);
2599   }
2600 
2601   // Lookup the cache.
2602   if (add_segment_cache_->Lookup(old_ssid, new_sid, &res)) {
2603     SegmentSet::AssertLive(res, __LINE__);
2604     return res;
2605   }
2606 
2607   if (LIKELY(old_ssid.IsSingleton())) {
2608     // Signleton->Doubleton transition.
2609     // These two TIDs were initialized before cache lookup (see above).
2610     DCHECK(old_tid.valid());
2611     DCHECK(new_tid.valid());
2612 
2613     SID old_sid(old_ssid.raw());
2614     DCHECK(old_sid.valid());
2615 
2616     DCHECK(!Segment::HappensBefore(new_sid, old_sid));
2617     DCHECK(!Segment::HappensBefore(old_sid, new_sid));
2618     res = (old_tid < new_tid
2619       ? DoubletonSSID(old_sid, new_sid)
2620       : DoubletonSSID(new_sid, old_sid));
2621     SegmentSet::AssertLive(res, __LINE__);
2622   } else {
2623     res = AddSegmentToTupleSS(old_ssid, new_sid);
2624     SegmentSet::AssertLive(res, __LINE__);
2625   }
2626 
2627   // Put the result into cache.
2628   add_segment_cache_->Insert(old_ssid, new_sid, res);
2629 
2630   return res;
2631 }
2632 
RemoveSegmentFromTupleSS(SSID ssid,SID sid_to_remove)2633 SSID SegmentSet::RemoveSegmentFromTupleSS(SSID ssid, SID sid_to_remove) {
2634   DCHECK(ssid.IsTuple());
2635   DCHECK(ssid.valid());
2636   AssertLive(ssid, __LINE__);
2637   SegmentSet *ss = Get(ssid);
2638 
2639   int32_t old_size = 0, new_size = 0;
2640   SegmentSet tmp;
2641   SID * tmp_sids = tmp.sids_;
2642   CHECK(sizeof(int32_t) == sizeof(SID));
2643 
2644   for (int i = 0; i < kMaxSegmentSetSize; i++, old_size++) {
2645     SID sid = ss->GetSID(i);
2646     if (sid.raw() == 0) break;
2647     DCHECK(sid.valid());
2648     Segment::AssertLive(sid, __LINE__);
2649     if (Segment::HappensBeforeOrSameThread(sid, sid_to_remove))
2650       continue;  // Skip this segment from the result.
2651     tmp_sids[new_size++] = sid;
2652   }
2653 
2654   if (new_size == old_size) return ssid;
2655   if (new_size == 0) return SSID(0);
2656   if (new_size == 1) return SSID(tmp_sids[0]);
2657 
2658   if (DEBUG_MODE) tmp.Validate(__LINE__);
2659 
2660   SSID res = FindExistingOrAlocateAndCopy(&tmp);
2661   if (DEBUG_MODE) Get(res)->Validate(__LINE__);
2662   return res;
2663 }
2664 
2665 //  static
AddSegmentToTupleSS(SSID ssid,SID new_sid)2666 SSID SegmentSet::AddSegmentToTupleSS(SSID ssid, SID new_sid) {
2667   DCHECK(ssid.IsTuple());
2668   DCHECK(ssid.valid());
2669   AssertLive(ssid, __LINE__);
2670   SegmentSet *ss = Get(ssid);
2671 
2672   Segment::AssertLive(new_sid, __LINE__);
2673   const Segment *new_seg = Segment::Get(new_sid);
2674   TID            new_tid = new_seg->tid();
2675 
2676   int32_t old_size = 0, new_size = 0;
2677   SID tmp_sids[kMaxSegmentSetSize + 1];
2678   CHECK(sizeof(int32_t) == sizeof(SID));
2679   bool inserted_new_sid = false;
2680   // traverse all SID in current ss. tids are ordered.
2681   for (int i = 0; i < kMaxSegmentSetSize; i++, old_size++) {
2682     SID sid = ss->GetSID(i);
2683     if (sid.raw() == 0) break;
2684     DCHECK(sid.valid());
2685     Segment::AssertLive(sid, __LINE__);
2686     const Segment *seg = Segment::Get(sid);
2687     TID            tid = seg->tid();
2688 
2689     if (sid == new_sid) {
2690       // we are trying to insert a sid which is already there.
2691       // SS will not change.
2692       return ssid;
2693     }
2694 
2695     if (tid == new_tid) {
2696       if (seg->vts() == new_seg->vts() &&
2697           seg->lsid(true) == new_seg->lsid(true) &&
2698           seg->lsid(false) == new_seg->lsid(false)) {
2699         // Optimization: if a segment with the same VTS and LS
2700         // as in the current is already inside SS, don't modify the SS.
2701         // Improves performance with --keep-history >= 1.
2702         return ssid;
2703       }
2704       // we have another segment from the same thread => replace it.
2705       tmp_sids[new_size++] = new_sid;
2706       inserted_new_sid = true;
2707       continue;
2708     }
2709 
2710     if (tid > new_tid && !inserted_new_sid) {
2711       // there was no segment with this tid, put it now.
2712       tmp_sids[new_size++] = new_sid;
2713       inserted_new_sid = true;
2714     }
2715 
2716     if (!Segment::HappensBefore(sid, new_sid)) {
2717       DCHECK(!Segment::HappensBefore(new_sid, sid));
2718       tmp_sids[new_size++] = sid;
2719     }
2720   }
2721 
2722   if (!inserted_new_sid) {
2723     tmp_sids[new_size++] = new_sid;
2724   }
2725 
2726   CHECK_GT(new_size, 0);
2727   if (new_size == 1) {
2728     return SSID(new_sid.raw());  // Singleton.
2729   }
2730 
2731   if (new_size > kMaxSegmentSetSize) {
2732     CHECK(new_size == kMaxSegmentSetSize + 1);
2733     // we need to forget one segment. Which? The oldest one.
2734     int seg_to_forget = 0;
2735     Segment *oldest_segment = NULL;
2736     for (int i = 0; i < new_size; i++) {
2737       SID sid = tmp_sids[i];
2738       if (sid == new_sid) continue;
2739       Segment *s = Segment::Get(tmp_sids[i]);
2740       if (oldest_segment == NULL ||
2741           oldest_segment->vts()->uniq_id() > s->vts()->uniq_id()) {
2742         oldest_segment = s;
2743         seg_to_forget = i;
2744       }
2745     }
2746     DCHECK(oldest_segment);
2747 
2748     // Printf("seg_to_forget: %d T%d\n", tmp_sids[seg_to_forget].raw(),
2749     //        oldest_segment->tid().raw());
2750     for (int i = seg_to_forget; i < new_size - 1; i++) {
2751       tmp_sids[i] = tmp_sids[i+1];
2752     }
2753     new_size--;
2754   }
2755 
2756   CHECK(new_size <= kMaxSegmentSetSize);
2757   SegmentSet tmp;
2758   for (int i = 0; i < new_size; i++)
2759     tmp.sids_[i] = tmp_sids[i];  // TODO(timurrrr): avoid copying?
2760   if (DEBUG_MODE) tmp.Validate(__LINE__);
2761 
2762   SSID res = FindExistingOrAlocateAndCopy(&tmp);
2763   if (DEBUG_MODE) Get(res)->Validate(__LINE__);
2764   return res;
2765 }
2766 
2767 
2768 
Validate(int line) const2769 void NOINLINE SegmentSet::Validate(int line) const {
2770   // This is expensive!
2771   int my_size = size();
2772   for (int i = 0; i < my_size; i++) {
2773     SID sid1 = GetSID(i);
2774     CHECK(sid1.valid());
2775     Segment::AssertLive(sid1, __LINE__);
2776 
2777     for (int j = i + 1; j < my_size; j++) {
2778       SID sid2 = GetSID(j);
2779       CHECK(sid2.valid());
2780       Segment::AssertLive(sid2, __LINE__);
2781 
2782       bool hb1 = Segment::HappensBefore(sid1, sid2);
2783       bool hb2 = Segment::HappensBefore(sid2, sid1);
2784       if (hb1 || hb2) {
2785         Printf("BAD at line %d: %d %d %s %s\n   %s\n   %s\n",
2786                line, static_cast<int>(hb1), static_cast<int>(hb2),
2787                Segment::ToString(sid1).c_str(),
2788                Segment::ToString(sid2).c_str(),
2789                Segment::Get(sid1)->vts()->ToString().c_str(),
2790                Segment::Get(sid2)->vts()->ToString().c_str());
2791       }
2792       CHECK(!Segment::HappensBefore(GetSID(i), GetSID(j)));
2793       CHECK(!Segment::HappensBefore(GetSID(j), GetSID(i)));
2794       CHECK(Segment::Get(sid1)->tid() < Segment::Get(sid2)->tid());
2795     }
2796   }
2797 
2798   for (int i = my_size; i < kMaxSegmentSetSize; i++) {
2799     CHECK_EQ(sids_[i].raw(), 0);
2800   }
2801 }
2802 
ToStringWithLocks(SSID ssid)2803 string SegmentSet::ToStringWithLocks(SSID ssid) {
2804   if (ssid.IsEmpty()) return "";
2805   string res = "";
2806   for (int i = 0; i < Size(ssid); i++) {
2807     SID sid = GetSID(ssid, i, __LINE__);
2808     if (i) res += ", ";
2809     res += Segment::ToStringWithLocks(sid);
2810   }
2811   return res;
2812 }
2813 
ToString() const2814 string SegmentSet::ToString() const {
2815   Validate(__LINE__);
2816   string res = "{";
2817   for (int i = 0; i < size(); i++) {
2818     SID sid = GetSID(i);
2819     if (i) res += ", ";
2820     CHECK(sid.valid());
2821     Segment::AssertLive(sid, __LINE__);
2822     res += Segment::ToStringTidOnly(sid).c_str();
2823   }
2824   res += "}";
2825   return res;
2826 }
2827 
2828 // static
Test()2829 void SegmentSet::Test() {
2830   LSID ls(0);  // dummy
2831   SID sid1 = Segment::AddNewSegment(TID(0), VTS::Parse("[0:2;]"), ls, ls);
2832   SID sid2 = Segment::AddNewSegment(TID(1), VTS::Parse("[0:1; 1:1]"), ls, ls);
2833   SID sid3 = Segment::AddNewSegment(TID(2), VTS::Parse("[0:1; 2:1]"), ls, ls);
2834   SID sid4 = Segment::AddNewSegment(TID(3), VTS::Parse("[0:1; 3:1]"), ls, ls);
2835   SID sid5 = Segment::AddNewSegment(TID(4), VTS::Parse("[0:3; 2:2; 3:2;]"),
2836                                     ls, ls);
2837   SID sid6 = Segment::AddNewSegment(TID(4), VTS::Parse("[0:3; 1:2; 2:2; 3:2;]"),
2838                                     ls, ls);
2839 
2840 
2841   // SS1:{T0/S1, T2/S3}
2842   SegmentSet *d1 = SegmentSet::Doubleton(sid1, sid3);
2843   d1->Print();
2844   CHECK(SegmentSet::Doubleton(sid1, sid3) == d1);
2845   // SS2:{T0/S1, T1/S2, T2/S3}
2846   SegmentSet *d2 = SegmentSet::AddSegmentToTupleSS(d1, sid2);
2847   CHECK(SegmentSet::AddSegmentToTupleSS(d1, sid2) == d2);
2848   d2->Print();
2849 
2850   // SS3:{T0/S1, T2/S3, T3/S4}
2851   SegmentSet *d3 = SegmentSet::AddSegmentToTupleSS(d1, sid4);
2852   CHECK(SegmentSet::AddSegmentToTupleSS(d1, sid4) == d3);
2853   d3->Print();
2854 
2855   // SS4:{T0/S1, T1/S2, T2/S3, T3/S4}
2856   SegmentSet *d4 = SegmentSet::AddSegmentToTupleSS(d2, sid4);
2857   CHECK(SegmentSet::AddSegmentToTupleSS(d2, sid4) == d4);
2858   CHECK(SegmentSet::AddSegmentToTupleSS(d3, sid2) == d4);
2859   d4->Print();
2860 
2861   // SS5:{T1/S2, T4/S5}
2862   SegmentSet *d5 = SegmentSet::AddSegmentToTupleSS(d4, sid5);
2863   d5->Print();
2864 
2865   SSID ssid6 = SegmentSet::AddSegmentToTupleSS(d4->ComputeSSID(), sid6);
2866   CHECK(ssid6.IsSingleton());
2867   Printf("%s\n", ToString(ssid6).c_str());
2868   CHECK_EQ(sid6.raw(), 6);
2869   CHECK_EQ(ssid6.raw(), 6);
2870 }
2871 
2872 // -------- Shadow Value ------------ {{{1
2873 class ShadowValue {
2874  public:
ShadowValue()2875   ShadowValue() {
2876     if (DEBUG_MODE) {
2877       rd_ssid_ = 0xDEADBEEF;
2878       wr_ssid_ = 0xDEADBEEF;
2879     }
2880   }
2881 
Clear()2882   void Clear() {
2883     rd_ssid_ = 0;
2884     wr_ssid_ = 0;
2885   }
2886 
IsNew() const2887   INLINE bool IsNew() const { return rd_ssid_ == 0 && wr_ssid_ == 0; }
2888   // new experimental state machine.
rd_ssid() const2889   SSID rd_ssid() const { return SSID(rd_ssid_); }
wr_ssid() const2890   SSID wr_ssid() const { return SSID(wr_ssid_); }
set(SSID rd_ssid,SSID wr_ssid)2891   INLINE void set(SSID rd_ssid, SSID wr_ssid) {
2892     rd_ssid_ = rd_ssid.raw();
2893     wr_ssid_ = wr_ssid.raw();
2894   }
2895 
2896   // comparison
operator ==(const ShadowValue & sval) const2897   INLINE bool operator == (const ShadowValue &sval) const {
2898     return rd_ssid_ == sval.rd_ssid_ &&
2899         wr_ssid_ == sval.wr_ssid_;
2900   }
operator !=(const ShadowValue & sval) const2901   bool operator != (const ShadowValue &sval) const {
2902     return !(*this == sval);
2903   }
operator <(const ShadowValue & sval) const2904   bool operator <  (const ShadowValue &sval) const {
2905     if (rd_ssid_ < sval.rd_ssid_) return true;
2906     if (rd_ssid_ == sval.rd_ssid_ && wr_ssid_ < sval.wr_ssid_) return true;
2907     return false;
2908   }
2909 
Ref(const char * where)2910   void Ref(const char *where) {
2911     if (!rd_ssid().IsEmpty()) {
2912       DCHECK(rd_ssid().valid());
2913       SegmentSet::Ref(rd_ssid(), where);
2914     }
2915     if (!wr_ssid().IsEmpty()) {
2916       DCHECK(wr_ssid().valid());
2917       SegmentSet::Ref(wr_ssid(), where);
2918     }
2919   }
2920 
Unref(const char * where)2921   void Unref(const char *where) {
2922     if (!rd_ssid().IsEmpty()) {
2923       DCHECK(rd_ssid().valid());
2924       SegmentSet::Unref(rd_ssid(), where);
2925     }
2926     if (!wr_ssid().IsEmpty()) {
2927       DCHECK(wr_ssid().valid());
2928       SegmentSet::Unref(wr_ssid(), where);
2929     }
2930   }
2931 
ToString() const2932   string ToString() const {
2933     char buff[1000];
2934     if (IsNew()) {
2935       return "{New}";
2936     }
2937     snprintf(buff, sizeof(buff), "R: %s; W: %s",
2938             SegmentSet::ToStringWithLocks(rd_ssid()).c_str(),
2939             SegmentSet::ToStringWithLocks(wr_ssid()).c_str());
2940     return buff;
2941   }
2942 
2943  private:
2944   int32_t rd_ssid_;
2945   int32_t wr_ssid_;
2946 };
2947 
2948 // -------- CacheLine --------------- {{{1
2949 // The CacheLine is a set of Mask::kNBits (32 or 64) Shadow Values.
2950 // The shadow values in a cache line are grouped in subsets of 8 values.
2951 // If a particular address of memory is always accessed by aligned 8-byte
2952 // read/write instructions, only the shadow value correspoding to the
2953 // first byte is set, the rest shadow values are not used.
2954 // Ditto to aligned 4- and 2-byte accesses.
2955 // If a memory was accessed as 8 bytes and then it was accesed as 4 bytes,
2956 // (e.g. someone used a C union) we need to split the shadow value into two.
2957 // If the memory was accessed as 4 bytes and is now accessed as 8 bytes,
2958 // we need to try joining the shadow values.
2959 //
2960 // Hence the concept of granularity_mask (which is a string of 16 bits).
2961 // 0000000000000000 -- no accesses were observed to these 8 bytes.
2962 // 0000000000000001 -- all accesses were 8 bytes (aligned).
2963 // 0000000000000110 -- all accesses were 4 bytes (aligned).
2964 // 0000000001111000 -- all accesses were 2 bytes (aligned).
2965 // 0111111110000000 -- all accesses were 1 byte.
2966 // 0110000000100010 -- First 4 bytes were accessed by 4 byte insns,
2967 //   next 2 bytes by 2 byte insns, last 2 bytes by 1 byte insns.
2968 
2969 
GranularityIs8(uintptr_t off,uint16_t gr)2970 INLINE bool GranularityIs8(uintptr_t off, uint16_t gr) {
2971   return gr & 1;
2972 }
2973 
GranularityIs4(uintptr_t off,uint16_t gr)2974 INLINE bool GranularityIs4(uintptr_t off, uint16_t gr) {
2975   uintptr_t off_within_8_bytes = (off >> 2) & 1;  // 0 or 1.
2976   return ((gr >> (1 + off_within_8_bytes)) & 1);
2977 }
2978 
GranularityIs2(uintptr_t off,uint16_t gr)2979 INLINE bool GranularityIs2(uintptr_t off, uint16_t gr) {
2980   uintptr_t off_within_8_bytes = (off >> 1) & 3;  // 0, 1, 2, or 3
2981   return ((gr >> (3 + off_within_8_bytes)) & 1);
2982 }
2983 
GranularityIs1(uintptr_t off,uint16_t gr)2984 INLINE bool GranularityIs1(uintptr_t off, uint16_t gr) {
2985   uintptr_t off_within_8_bytes = (off) & 7;       // 0, ..., 7
2986   return ((gr >> (7 + off_within_8_bytes)) & 1);
2987 }
2988 
2989 class CacheLine {
2990  public:
2991   static const uintptr_t kLineSizeBits = Mask::kNBitsLog;  // Don't change this.
2992   static const uintptr_t kLineSize = Mask::kNBits;
2993 
CreateNewCacheLine(uintptr_t tag)2994   static CacheLine *CreateNewCacheLine(uintptr_t tag) {
2995     ScopedMallocCostCenter cc("CreateNewCacheLine");
2996     void *mem = free_list_->Allocate();
2997     DCHECK(mem);
2998     return new (mem) CacheLine(tag);
2999   }
3000 
Delete(CacheLine * line)3001   static void Delete(CacheLine *line) {
3002     free_list_->Deallocate(line);
3003   }
3004 
has_shadow_value() const3005   const Mask &has_shadow_value() const { return has_shadow_value_;  }
traced()3006   Mask &traced() { return traced_; }
published()3007   Mask &published() { return published_; }
racey()3008   Mask &racey()  { return racey_; }
tag()3009   uintptr_t tag() { return tag_; }
3010 
DebugTrace(uintptr_t off,const char * where_str,int where_int)3011   void DebugTrace(uintptr_t off, const char *where_str, int where_int) {
3012     (void)off;
3013     (void)where_str;
3014     (void)where_int;
3015 #if 0
3016     if (DEBUG_MODE && tag() == G_flags->trace_addr) {
3017       uintptr_t off8 = off & ~7;
3018       Printf("CacheLine %p, off=%ld off8=%ld gr=%d "
3019              "has_sval: %d%d%d%d%d%d%d%d (%s:%d)\n",
3020              tag(), off, off8,
3021              granularity_[off/8],
3022              has_shadow_value_.Get(off8 + 0),
3023              has_shadow_value_.Get(off8 + 1),
3024              has_shadow_value_.Get(off8 + 2),
3025              has_shadow_value_.Get(off8 + 3),
3026              has_shadow_value_.Get(off8 + 4),
3027              has_shadow_value_.Get(off8 + 5),
3028              has_shadow_value_.Get(off8 + 6),
3029              has_shadow_value_.Get(off8 + 7),
3030              where_str, where_int
3031              );
3032     }
3033 #endif
3034   }
3035 
3036   // Add a new shadow value to a place where there was no shadow value before.
AddNewSvalAtOffset(uintptr_t off)3037   ShadowValue *AddNewSvalAtOffset(uintptr_t off) {
3038     DebugTrace(off, __FUNCTION__, __LINE__);
3039     CHECK(!has_shadow_value().Get(off));
3040     has_shadow_value_.Set(off);
3041     published_.Clear(off);
3042     ShadowValue *res = GetValuePointer(off);
3043     res->Clear();
3044     DebugTrace(off, __FUNCTION__, __LINE__);
3045     return res;
3046   }
3047 
3048   // Return true if this line has no useful information in it.
Empty()3049   bool Empty() {
3050     // The line has shadow values.
3051     if (!has_shadow_value().Empty()) return false;
3052     // If the line is traced, racey or published, we want to keep it.
3053     if (!traced().Empty()) return false;
3054     if (!racey().Empty()) return false;
3055     if (!published().Empty()) return false;
3056     return true;
3057   }
3058 
ClearRangeAndReturnOldUsed(uintptr_t from,uintptr_t to)3059   INLINE Mask ClearRangeAndReturnOldUsed(uintptr_t from, uintptr_t to) {
3060     traced_.ClearRange(from, to);
3061     published_.ClearRange(from, to);
3062     racey_.ClearRange(from, to);
3063     for (uintptr_t x = (from + 7) / 8; x < to / 8; x++) {
3064       granularity_[x] = 0;
3065     }
3066     return has_shadow_value_.ClearRangeAndReturnOld(from, to);
3067   }
3068 
Clear()3069   void Clear() {
3070     has_shadow_value_.Clear();
3071     traced_.Clear();
3072     published_.Clear();
3073     racey_.Clear();
3074     for (size_t i = 0; i < TS_ARRAY_SIZE(granularity_); i++)
3075       granularity_[i] = 0;
3076   }
3077 
GetValuePointer(uintptr_t offset)3078   ShadowValue *GetValuePointer(uintptr_t offset) {
3079     DCHECK(offset < kLineSize);
3080     return  &vals_[offset];
3081   }
GetValue(uintptr_t offset)3082   ShadowValue  GetValue(uintptr_t offset) { return *GetValuePointer(offset); }
3083 
ComputeOffset(uintptr_t a)3084   static uintptr_t ComputeOffset(uintptr_t a) {
3085     return a & (kLineSize - 1);
3086   }
ComputeTag(uintptr_t a)3087   static uintptr_t ComputeTag(uintptr_t a) {
3088     return a & ~(kLineSize - 1);
3089   }
ComputeNextTag(uintptr_t a)3090   static uintptr_t ComputeNextTag(uintptr_t a) {
3091     return ComputeTag(a) + kLineSize;
3092   }
3093 
granularity_mask(uintptr_t off)3094   uint16_t *granularity_mask(uintptr_t off) {
3095     DCHECK(off < kLineSize);
3096     return &granularity_[off / 8];
3097   }
3098 
Split_8_to_4(uintptr_t off)3099   void Split_8_to_4(uintptr_t off) {
3100     DebugTrace(off, __FUNCTION__, __LINE__);
3101     uint16_t gr = *granularity_mask(off);
3102     if (GranularityIs8(off, gr)) {
3103       DCHECK(!GranularityIs4(off, gr));
3104       DCHECK(!GranularityIs2(off, gr));
3105       DCHECK(!GranularityIs1(off, gr));
3106       uintptr_t off_8_aligned = off & ~7;
3107       if (has_shadow_value_.Get(off_8_aligned)) {
3108         ShadowValue sval = GetValue(off_8_aligned);
3109         sval.Ref("Split_8_to_4");
3110         DCHECK(!has_shadow_value_.Get(off_8_aligned + 4));
3111         *AddNewSvalAtOffset(off_8_aligned + 4) = sval;
3112       }
3113       *granularity_mask(off) = gr = 3 << 1;
3114       DCHECK(GranularityIs4(off, gr));
3115       DebugTrace(off, __FUNCTION__, __LINE__);
3116     }
3117   }
3118 
Split_4_to_2(uintptr_t off)3119   void Split_4_to_2(uintptr_t off) {
3120     DebugTrace(off, __FUNCTION__, __LINE__);
3121     uint16_t gr = *granularity_mask(off);
3122     if (GranularityIs4(off, gr)) {
3123       DCHECK(!GranularityIs8(off, gr));
3124       DCHECK(!GranularityIs2(off, gr));
3125       DCHECK(!GranularityIs1(off, gr));
3126       uint16_t off_4_aligned = off & ~3;
3127       if (has_shadow_value_.Get(off_4_aligned)) {
3128         ShadowValue sval = GetValue(off_4_aligned);
3129         sval.Ref("Split_4_to_2");
3130         DCHECK(!has_shadow_value_.Get(off_4_aligned + 2));
3131         *AddNewSvalAtOffset(off_4_aligned + 2) = sval;
3132       }
3133       // Clear this 4-granularity bit.
3134       uintptr_t off_within_8_bytes = (off >> 2) & 1;  // 0 or 1.
3135       gr &= ~(1 << (1 + off_within_8_bytes));
3136       // Set two 2-granularity bits.
3137       gr |= 3 << (3 + 2 * off_within_8_bytes);
3138       *granularity_mask(off) = gr;
3139       DebugTrace(off, __FUNCTION__, __LINE__);
3140     }
3141   }
3142 
Split_2_to_1(uintptr_t off)3143   void Split_2_to_1(uintptr_t off) {
3144     DebugTrace(off, __FUNCTION__, __LINE__);
3145     uint16_t gr = *granularity_mask(off);
3146     if (GranularityIs2(off, gr)) {
3147       DCHECK(!GranularityIs8(off, gr));
3148       DCHECK(!GranularityIs4(off, gr));
3149       DCHECK(!GranularityIs1(off, gr));
3150       uint16_t off_2_aligned = off & ~1;
3151       if (has_shadow_value_.Get(off_2_aligned)) {
3152         ShadowValue sval = GetValue(off_2_aligned);
3153         sval.Ref("Split_2_to_1");
3154         DCHECK(!has_shadow_value_.Get(off_2_aligned + 1));
3155         *AddNewSvalAtOffset(off_2_aligned + 1) = sval;
3156       }
3157       // Clear this 2-granularity bit.
3158       uintptr_t off_within_8_bytes = (off >> 1) & 3;  // 0, 1, 2, or 3
3159       gr &= ~(1 << (3 + off_within_8_bytes));
3160       // Set two 1-granularity bits.
3161       gr |= 3 << (7 + 2 * off_within_8_bytes);
3162       *granularity_mask(off) = gr;
3163       DebugTrace(off, __FUNCTION__, __LINE__);
3164     }
3165   }
3166 
Join_1_to_2(uintptr_t off)3167   void Join_1_to_2(uintptr_t off) {
3168     DebugTrace(off, __FUNCTION__, __LINE__);
3169     DCHECK((off & 1) == 0);
3170     uint16_t gr = *granularity_mask(off);
3171     if (GranularityIs1(off, gr)) {
3172       DCHECK(GranularityIs1(off + 1, gr));
3173       if (has_shadow_value_.Get(off) && has_shadow_value_.Get(off + 1)) {
3174         if (GetValue(off) == GetValue(off + 1)) {
3175           ShadowValue *sval_p = GetValuePointer(off + 1);
3176           sval_p->Unref("Join_1_to_2");
3177           sval_p->Clear();
3178           has_shadow_value_.Clear(off + 1);
3179           uintptr_t off_within_8_bytes = (off >> 1) & 3;  // 0, 1, 2, or 3
3180           // Clear two 1-granularity bits.
3181           gr &= ~(3 << (7 + 2 * off_within_8_bytes));
3182           // Set one 2-granularity bit.
3183           gr |= 1 << (3 + off_within_8_bytes);
3184           *granularity_mask(off) = gr;
3185           DebugTrace(off, __FUNCTION__, __LINE__);
3186         }
3187       }
3188     }
3189   }
3190 
Join_2_to_4(uintptr_t off)3191   void Join_2_to_4(uintptr_t off) {
3192     DebugTrace(off, __FUNCTION__, __LINE__);
3193     DCHECK((off & 3) == 0);
3194     uint16_t gr = *granularity_mask(off);
3195     if (GranularityIs2(off, gr) && GranularityIs2(off + 2, gr)) {
3196       if (has_shadow_value_.Get(off) && has_shadow_value_.Get(off + 2)) {
3197         if (GetValue(off) == GetValue(off + 2)) {
3198           ShadowValue *sval_p = GetValuePointer(off + 2);
3199           sval_p->Unref("Join_2_to_4");
3200           sval_p->Clear();
3201           has_shadow_value_.Clear(off + 2);
3202           uintptr_t off_within_8_bytes = (off >> 2) & 1;  // 0 or 1.
3203           // Clear two 2-granularity bits.
3204           gr &= ~(3 << (3 + 2 * off_within_8_bytes));
3205           // Set one 4-granularity bit.
3206           gr |= 1 << (1 + off_within_8_bytes);
3207           *granularity_mask(off) = gr;
3208           DebugTrace(off, __FUNCTION__, __LINE__);
3209         }
3210       }
3211     }
3212   }
3213 
Join_4_to_8(uintptr_t off)3214   void Join_4_to_8(uintptr_t off) {
3215     DebugTrace(off, __FUNCTION__, __LINE__);
3216     DCHECK((off & 7) == 0);
3217     uint16_t gr = *granularity_mask(off);
3218     if (GranularityIs4(off, gr) && GranularityIs4(off + 4, gr)) {
3219       if (has_shadow_value_.Get(off) && has_shadow_value_.Get(off + 4)) {
3220         if (GetValue(off) == GetValue(off + 4)) {
3221           ShadowValue *sval_p = GetValuePointer(off + 4);
3222           sval_p->Unref("Join_4_to_8");
3223           sval_p->Clear();
3224           has_shadow_value_.Clear(off + 4);
3225           *granularity_mask(off) = 1;
3226           DebugTrace(off, __FUNCTION__, __LINE__);
3227         }
3228       }
3229     }
3230   }
3231 
InitClassMembers()3232   static void InitClassMembers() {
3233     if (DEBUG_MODE) {
3234       Printf("sizeof(CacheLine) = %ld\n", sizeof(CacheLine));
3235     }
3236     free_list_ = new FreeList(sizeof(CacheLine), 1024);
3237   }
3238 
3239  private:
CacheLine(uintptr_t tag)3240   explicit CacheLine(uintptr_t tag) {
3241     tag_ = tag;
3242     Clear();
3243   }
~CacheLine()3244   ~CacheLine() { }
3245 
3246   uintptr_t tag_;
3247 
3248   // data members
3249   Mask has_shadow_value_;
3250   Mask traced_;
3251   Mask racey_;
3252   Mask published_;
3253   uint16_t granularity_[kLineSize / 8];
3254   ShadowValue vals_[kLineSize];
3255 
3256   // static data members.
3257   static FreeList *free_list_;
3258 };
3259 
3260 FreeList *CacheLine::free_list_;
3261 
3262 // If range [a,b) fits into one line, return that line's tag.
3263 // Else range [a,b) is broken into these ranges:
3264 //   [a, line1_tag)
3265 //   [line1_tag, line2_tag)
3266 //   [line2_tag, b)
3267 // and 0 is returned.
GetCacheLinesForRange(uintptr_t a,uintptr_t b,uintptr_t * line1_tag,uintptr_t * line2_tag)3268 uintptr_t GetCacheLinesForRange(uintptr_t a, uintptr_t b,
3269                                 uintptr_t *line1_tag, uintptr_t *line2_tag) {
3270   uintptr_t a_tag = CacheLine::ComputeTag(a);
3271   uintptr_t next_tag = CacheLine::ComputeNextTag(a);
3272   if (b < next_tag) {
3273     return a_tag;
3274   }
3275   *line1_tag = next_tag;
3276   *line2_tag = CacheLine::ComputeTag(b);
3277   return 0;
3278 }
3279 
3280 
3281 // -------- Cache ------------------ {{{1
3282 class Cache {
3283  public:
Cache()3284   Cache() {
3285     memset(lines_, 0, sizeof(lines_));
3286     ANNOTATE_BENIGN_RACE_SIZED(lines_, sizeof(lines_),
3287                                "Cache::lines_ accessed without a lock");
3288   }
3289 
kLineIsLocked()3290   INLINE static CacheLine *kLineIsLocked() {
3291     return (CacheLine*)1;
3292   }
3293 
LineIsNullOrLocked(CacheLine * line)3294   INLINE static bool LineIsNullOrLocked(CacheLine *line) {
3295     return (uintptr_t)line <= 1;
3296   }
3297 
TidMagic(int32_t tid)3298   INLINE CacheLine *TidMagic(int32_t tid) {
3299     return kLineIsLocked();
3300   }
3301 
3302   // Try to get a CacheLine for exclusive use.
3303   // May return NULL or kLineIsLocked.
TryAcquireLine(TSanThread * thr,uintptr_t a,int call_site)3304   INLINE CacheLine *TryAcquireLine(TSanThread *thr, uintptr_t a, int call_site) {
3305     uintptr_t cli = ComputeCacheLineIndexInCache(a);
3306     CacheLine **addr = &lines_[cli];
3307     CacheLine *res = (CacheLine*)AtomicExchange(
3308            (uintptr_t*)addr, (uintptr_t)kLineIsLocked());
3309     if (DEBUG_MODE && debug_cache) {
3310       uintptr_t tag = CacheLine::ComputeTag(a);
3311       if (res && res != kLineIsLocked())
3312         Printf("TryAcquire %p empty=%d tag=%lx cli=%lx site=%d\n",
3313                res, res->Empty(), res->tag(), cli, call_site);
3314       else
3315         Printf("TryAcquire tag=%lx cli=%d site=%d\n", tag, cli, call_site);
3316     }
3317     if (res) {
3318       ANNOTATE_HAPPENS_AFTER((void*)cli);
3319     }
3320     return res;
3321   }
3322 
AcquireLine(TSanThread * thr,uintptr_t a,int call_site)3323   INLINE CacheLine *AcquireLine(TSanThread *thr, uintptr_t a, int call_site) {
3324     CacheLine *line = NULL;
3325     int iter = 0;
3326     const int max_iter = 1 << 30;
3327     for (;;) {
3328       line = TryAcquireLine(thr, a, call_site);
3329       if (line != kLineIsLocked())
3330         break;
3331       iter++;
3332       if ((iter % (1 << 6)) == 0) {
3333         YIELD();
3334         G_stats->try_acquire_line_spin++;
3335         if (DEBUG_MODE && debug_cache && ((iter & (iter - 1)) == 0)) {
3336           Printf("T%d %s a=%p iter=%d\n", raw_tid(thr), __FUNCTION__, a, iter);
3337         }
3338       } else {
3339         for (int active_spin = 0; active_spin != 10; active_spin += 1) {
3340           PROCESSOR_YIELD();
3341         }
3342       }
3343       if (DEBUG_MODE && debug_cache && iter == max_iter) {
3344         Printf("Failed to acquire a cache line: T%d a=%p site=%d\n",
3345                raw_tid(thr), a, call_site);
3346         CHECK(iter < max_iter);
3347       }
3348     }
3349     DCHECK(lines_[ComputeCacheLineIndexInCache(a)] == TidMagic(raw_tid(thr)));
3350     return line;
3351   }
3352 
3353   // Release a CacheLine from exclusive use.
ReleaseLine(TSanThread * thr,uintptr_t a,CacheLine * line,int call_site)3354   INLINE void ReleaseLine(TSanThread *thr, uintptr_t a, CacheLine *line, int call_site) {
3355     if (TS_SERIALIZED) return;
3356     DCHECK(line != kLineIsLocked());
3357     uintptr_t cli = ComputeCacheLineIndexInCache(a);
3358     DCHECK(line == NULL ||
3359            cli == ComputeCacheLineIndexInCache(line->tag()));
3360     CacheLine **addr = &lines_[cli];
3361     DCHECK(*addr == TidMagic(raw_tid(thr)));
3362     ReleaseStore((uintptr_t*)addr, (uintptr_t)line);
3363     ANNOTATE_HAPPENS_BEFORE((void*)cli);
3364     if (DEBUG_MODE && debug_cache) {
3365       uintptr_t tag = CacheLine::ComputeTag(a);
3366       if (line)
3367         Printf("Release %p empty=%d tag=%lx cli=%lx site=%d\n",
3368                line, line->Empty(), line->tag(), cli, call_site);
3369       else
3370         Printf("Release tag=%lx cli=%d site=%d\n", tag, cli, call_site);
3371     }
3372   }
3373 
AcquireAllLines(TSanThread * thr)3374   void AcquireAllLines(TSanThread *thr) {
3375     CHECK(TS_SERIALIZED == 0);
3376     for (size_t i = 0; i < (size_t)kNumLines; i++) {
3377       uintptr_t tag = i << CacheLine::kLineSizeBits;
3378       AcquireLine(thr, tag, __LINE__);
3379       CHECK(lines_[i] == kLineIsLocked());
3380     }
3381   }
3382 
3383   // Get a CacheLine. This operation should be performed under a lock
3384   // (whatever that is), but other threads may be acquiring the same line
3385   // concurrently w/o a lock.
3386   // Every call to GetLine() which returns non-null line
3387   // should be followed by a call to ReleaseLine().
GetLine(TSanThread * thr,uintptr_t a,bool create_new_if_need,int call_site)3388   INLINE CacheLine *GetLine(TSanThread *thr, uintptr_t a, bool create_new_if_need, int call_site) {
3389     uintptr_t tag = CacheLine::ComputeTag(a);
3390     DCHECK(tag <= a);
3391     DCHECK(tag + CacheLine::kLineSize > a);
3392     uintptr_t cli = ComputeCacheLineIndexInCache(a);
3393     CacheLine *res = NULL;
3394     CacheLine *line = NULL;
3395 
3396     if (create_new_if_need == false && lines_[cli] == 0) {
3397       // There is no such line in the cache, nor should it be in the storage.
3398       // Check that the storage indeed does not have this line.
3399       // Such DCHECK is racey if tsan is multi-threaded.
3400       DCHECK(TS_SERIALIZED == 0 || storage_.count(tag) == 0);
3401       return NULL;
3402     }
3403 
3404     if (TS_SERIALIZED) {
3405       line = lines_[cli];
3406     } else {
3407       line = AcquireLine(thr, tag, call_site);
3408     }
3409 
3410 
3411     if (LIKELY(line && line->tag() == tag)) {
3412       res = line;
3413     } else {
3414       res = WriteBackAndFetch(thr, line, tag, cli, create_new_if_need);
3415       if (!res) {
3416         ReleaseLine(thr, a, line, call_site);
3417       }
3418     }
3419     if (DEBUG_MODE && debug_cache) {
3420       if (res)
3421         Printf("GetLine %p empty=%d tag=%lx\n", res, res->Empty(), res->tag());
3422       else
3423         Printf("GetLine res=NULL, line=%p tag=%lx cli=%lx\n", line, tag, cli);
3424     }
3425     return res;
3426   }
3427 
GetLineOrCreateNew(TSanThread * thr,uintptr_t a,int call_site)3428   INLINE CacheLine *GetLineOrCreateNew(TSanThread *thr, uintptr_t a, int call_site) {
3429     return GetLine(thr, a, true, call_site);
3430   }
GetLineIfExists(TSanThread * thr,uintptr_t a,int call_site)3431   INLINE CacheLine *GetLineIfExists(TSanThread *thr, uintptr_t a, int call_site) {
3432     return GetLine(thr, a, false, call_site);
3433   }
3434 
ForgetAllState(TSanThread * thr)3435   void ForgetAllState(TSanThread *thr) {
3436     for (int i = 0; i < kNumLines; i++) {
3437       if (TS_SERIALIZED == 0) CHECK(LineIsNullOrLocked(lines_[i]));
3438       lines_[i] = NULL;
3439     }
3440     map<uintptr_t, Mask> racey_masks;
3441     for (Map::iterator i = storage_.begin(); i != storage_.end(); ++i) {
3442       CacheLine *line = i->second;
3443       if (!line->racey().Empty()) {
3444         racey_masks[line->tag()] = line->racey();
3445       }
3446       CacheLine::Delete(line);
3447     }
3448     storage_.clear();
3449     // Restore the racey masks.
3450     for (map<uintptr_t, Mask>::iterator it = racey_masks.begin();
3451          it != racey_masks.end(); it++) {
3452       CacheLine *line = GetLineOrCreateNew(thr, it->first, __LINE__);
3453       line->racey() = it->second;
3454       DCHECK(!line->racey().Empty());
3455       ReleaseLine(thr, line->tag(), line, __LINE__);
3456     }
3457   }
3458 
PrintStorageStats()3459   void PrintStorageStats() {
3460     if (!G_flags->show_stats) return;
3461     set<ShadowValue> all_svals;
3462     map<size_t, int> sizes;
3463     for (Map::iterator it = storage_.begin(); it != storage_.end(); ++it) {
3464       CacheLine *line = it->second;
3465       // uintptr_t cli = ComputeCacheLineIndexInCache(line->tag());
3466       //if (lines_[cli] == line) {
3467         // this line is in cache -- ignore it.
3468       //  continue;
3469       //}
3470       set<ShadowValue> s;
3471       for (uintptr_t i = 0; i < CacheLine::kLineSize; i++) {
3472         if (line->has_shadow_value().Get(i)) {
3473           ShadowValue sval = *(line->GetValuePointer(i));
3474           s.insert(sval);
3475           all_svals.insert(sval);
3476         }
3477       }
3478       size_t size = s.size();
3479       if (size > 10) size = 10;
3480       sizes[size]++;
3481     }
3482     Printf("Storage sizes: %ld\n", storage_.size());
3483     for (size_t size = 0; size <= CacheLine::kLineSize; size++) {
3484       if (sizes[size]) {
3485         Printf("  %ld => %d\n", size, sizes[size]);
3486       }
3487     }
3488     Printf("Different svals: %ld\n", all_svals.size());
3489     set <SSID> all_ssids;
3490     for (set<ShadowValue>::iterator it = all_svals.begin(); it != all_svals.end(); ++it) {
3491       ShadowValue sval = *it;
3492       for (int i = 0; i < 2; i++) {
3493         SSID ssid = i ? sval.rd_ssid() : sval.wr_ssid();
3494         all_ssids.insert(ssid);
3495       }
3496     }
3497     Printf("Different ssids: %ld\n", all_ssids.size());
3498     set <SID> all_sids;
3499     for (set<SSID>::iterator it = all_ssids.begin(); it != all_ssids.end(); ++it) {
3500       int size = SegmentSet::Size(*it);
3501       for (int i = 0; i < size; i++) {
3502         SID sid = SegmentSet::GetSID(*it, i, __LINE__);
3503         all_sids.insert(sid);
3504       }
3505     }
3506     Printf("Different sids: %ld\n", all_sids.size());
3507     for (int i = 1; i < Segment::NumberOfSegments(); i++) {
3508       if (Segment::ProfileSeg(SID(i)) && all_sids.count(SID(i)) == 0) {
3509         // Printf("Segment SID %d: missing in storage; ref=%d\n", i,
3510         // Segment::Get(SID(i))->ref_count());
3511       }
3512     }
3513   }
3514 
3515  private:
ComputeCacheLineIndexInCache(uintptr_t addr)3516   INLINE uintptr_t ComputeCacheLineIndexInCache(uintptr_t addr) {
3517     return (addr >> CacheLine::kLineSizeBits) & (kNumLines - 1);
3518   }
3519 
WriteBackAndFetch(TSanThread * thr,CacheLine * old_line,uintptr_t tag,uintptr_t cli,bool create_new_if_need)3520   NOINLINE CacheLine *WriteBackAndFetch(TSanThread *thr, CacheLine *old_line,
3521                                         uintptr_t tag, uintptr_t cli,
3522                                         bool create_new_if_need) {
3523     ScopedMallocCostCenter cc("Cache::WriteBackAndFetch");
3524     CacheLine *res;
3525     size_t old_storage_size = storage_.size();
3526     (void)old_storage_size;
3527     CacheLine **line_for_this_tag = NULL;
3528     if (create_new_if_need) {
3529       line_for_this_tag = &storage_[tag];
3530     } else {
3531       Map::iterator it = storage_.find(tag);
3532       if (it == storage_.end()) {
3533         if (DEBUG_MODE && debug_cache) {
3534           Printf("WriteBackAndFetch: old_line=%ld tag=%lx cli=%ld\n",
3535                  old_line, tag, cli);
3536         }
3537         return NULL;
3538       }
3539       line_for_this_tag = &(it->second);
3540     }
3541     CHECK(line_for_this_tag);
3542     DCHECK(old_line != kLineIsLocked());
3543     if (*line_for_this_tag == NULL) {
3544       // creating a new cache line
3545       CHECK(storage_.size() == old_storage_size + 1);
3546       res = CacheLine::CreateNewCacheLine(tag);
3547       if (DEBUG_MODE && debug_cache) {
3548         Printf("%s %d new line %p cli=%lx\n", __FUNCTION__, __LINE__, res, cli);
3549       }
3550       *line_for_this_tag = res;
3551       G_stats->cache_new_line++;
3552     } else {
3553       // taking an existing cache line from storage.
3554       res = *line_for_this_tag;
3555       if (DEBUG_MODE && debug_cache) {
3556         Printf("%s %d exi line %p tag=%lx old=%p empty=%d cli=%lx\n",
3557              __FUNCTION__, __LINE__, res, res->tag(), old_line,
3558              res->Empty(), cli);
3559       }
3560       DCHECK(!res->Empty());
3561       G_stats->cache_fetch++;
3562     }
3563 
3564     if (TS_SERIALIZED) {
3565       lines_[cli] = res;
3566     } else {
3567       DCHECK(lines_[cli] == TidMagic(raw_tid(thr)));
3568     }
3569 
3570     if (old_line) {
3571       if (DEBUG_MODE && debug_cache) {
3572         Printf("%s %d old line %p empty=%d\n", __FUNCTION__, __LINE__,
3573                old_line, old_line->Empty());
3574       }
3575       if (old_line->Empty()) {
3576         storage_.erase(old_line->tag());
3577         CacheLine::Delete(old_line);
3578         G_stats->cache_delete_empty_line++;
3579       } else {
3580         if (debug_cache) {
3581           DebugOnlyCheckCacheLineWhichWeReplace(old_line, res);
3582         }
3583       }
3584     }
3585     DCHECK(res->tag() == tag);
3586 
3587     if (G_stats->cache_max_storage_size < storage_.size()) {
3588       G_stats->cache_max_storage_size = storage_.size();
3589     }
3590 
3591     return res;
3592   }
3593 
DebugOnlyCheckCacheLineWhichWeReplace(CacheLine * old_line,CacheLine * new_line)3594   void DebugOnlyCheckCacheLineWhichWeReplace(CacheLine *old_line,
3595                                              CacheLine *new_line) {
3596     static int c = 0;
3597     c++;
3598     if ((c % 1024) == 1) {
3599       set<int64_t> s;
3600       for (uintptr_t i = 0; i < CacheLine::kLineSize; i++) {
3601         if (old_line->has_shadow_value().Get(i)) {
3602           int64_t sval = *reinterpret_cast<int64_t*>(
3603                             old_line->GetValuePointer(i));
3604           s.insert(sval);
3605         }
3606       }
3607       Printf("\n[%d] Cache Size=%ld %s different values: %ld\n", c,
3608              storage_.size(), old_line->has_shadow_value().ToString().c_str(),
3609              s.size());
3610 
3611       Printf("new line: %p %p\n", new_line->tag(), new_line->tag()
3612              + CacheLine::kLineSize);
3613       G_stats->PrintStatsForCache();
3614     }
3615   }
3616 
3617   static const int kNumLines = 1 << (DEBUG_MODE ? 14 : 21);
3618   CacheLine *lines_[kNumLines];
3619 
3620   // tag => CacheLine
3621   typedef unordered_map<uintptr_t, CacheLine*> Map;
3622   Map storage_;
3623 };
3624 
3625 static  Cache *G_cache;
3626 
3627 // -------- Published range -------------------- {{{1
3628 struct PublishInfo {
3629   uintptr_t tag;   // Tag of the cache line where the mem is published.
3630   Mask      mask;  // The bits that are actually published.
3631   VTS      *vts;   // The point where this range has been published.
3632 };
3633 
3634 
3635 typedef multimap<uintptr_t, PublishInfo> PublishInfoMap;
3636 
3637 // Maps 'mem+size' to the PublishInfoMap{mem, size, vts}.
3638 static PublishInfoMap *g_publish_info_map;
3639 
3640 const int kDebugPublish = 0;
3641 
3642 // Get a VTS where 'a' has been published,
3643 // return NULL if 'a' was not published.
GetPublisherVTS(uintptr_t a)3644 static const VTS *GetPublisherVTS(uintptr_t a) {
3645   uintptr_t tag = CacheLine::ComputeTag(a);
3646   uintptr_t off = CacheLine::ComputeOffset(a);
3647   typedef PublishInfoMap::iterator Iter;
3648 
3649   pair<Iter, Iter> eq_range = g_publish_info_map->equal_range(tag);
3650   for (Iter it = eq_range.first; it != eq_range.second; ++it) {
3651     PublishInfo &info = it->second;
3652     DCHECK(info.tag == tag);
3653     if (info.mask.Get(off)) {
3654       G_stats->publish_get++;
3655       // Printf("GetPublisherVTS: a=%p vts=%p\n", a, info.vts);
3656       return info.vts;
3657     }
3658   }
3659   Printf("GetPublisherVTS returned NULL: a=%p\n", a);
3660   return NULL;
3661 }
3662 
CheckSanityOfPublishedMemory(uintptr_t tag,int line)3663 static bool CheckSanityOfPublishedMemory(uintptr_t tag, int line) {
3664   if (!DEBUG_MODE) return true;
3665   if (kDebugPublish)
3666     Printf("CheckSanityOfPublishedMemory: line=%d\n", line);
3667   typedef PublishInfoMap::iterator Iter;
3668   pair<Iter, Iter> eq_range = g_publish_info_map->equal_range(tag);
3669   Mask union_of_masks(0);
3670   // iterate over all entries for this tag
3671   for (Iter it = eq_range.first; it != eq_range.second; ++it) {
3672     PublishInfo &info = it->second;
3673     CHECK(info.tag  == tag);
3674     CHECK(it->first == tag);
3675     CHECK(info.vts);
3676     Mask mask(info.mask);
3677     CHECK(!mask.Empty());  // Mask should not be empty..
3678     // And should not intersect with other masks.
3679     CHECK(Mask::Intersection(union_of_masks, mask).Empty());
3680     union_of_masks.Union(mask);
3681   }
3682   return true;
3683 }
3684 
3685 // Clear the publish attribute for the bytes from 'line' that are set in 'mask'
ClearPublishedAttribute(CacheLine * line,Mask mask)3686 static void ClearPublishedAttribute(CacheLine *line, Mask mask) {
3687   CHECK(CheckSanityOfPublishedMemory(line->tag(), __LINE__));
3688   typedef PublishInfoMap::iterator Iter;
3689   bool deleted_some = true;
3690   if (kDebugPublish)
3691     Printf(" ClearPublishedAttribute: %p %s\n",
3692            line->tag(), mask.ToString().c_str());
3693   while (deleted_some) {
3694     deleted_some = false;
3695     pair<Iter, Iter> eq_range = g_publish_info_map->equal_range(line->tag());
3696     for (Iter it = eq_range.first; it != eq_range.second; ++it) {
3697       PublishInfo &info = it->second;
3698       DCHECK(info.tag == line->tag());
3699       if (kDebugPublish)
3700         Printf("?ClearPublishedAttribute: %p %s\n", line->tag(),
3701                info.mask.ToString().c_str());
3702       info.mask.Subtract(mask);
3703       if (kDebugPublish)
3704         Printf("+ClearPublishedAttribute: %p %s\n", line->tag(),
3705                info.mask.ToString().c_str());
3706       G_stats->publish_clear++;
3707       if (info.mask.Empty()) {
3708         VTS::Unref(info.vts);
3709         g_publish_info_map->erase(it);
3710         deleted_some = true;
3711         break;
3712       }
3713     }
3714   }
3715   CHECK(CheckSanityOfPublishedMemory(line->tag(), __LINE__));
3716 }
3717 
3718 // Publish range [a, b) in addr's CacheLine with vts.
PublishRangeInOneLine(TSanThread * thr,uintptr_t addr,uintptr_t a,uintptr_t b,VTS * vts)3719 static void PublishRangeInOneLine(TSanThread *thr, uintptr_t addr, uintptr_t a,
3720                                   uintptr_t b, VTS *vts) {
3721   ScopedMallocCostCenter cc("PublishRangeInOneLine");
3722   DCHECK(b <= CacheLine::kLineSize);
3723   DCHECK(a < b);
3724   uintptr_t tag = CacheLine::ComputeTag(addr);
3725   CHECK(CheckSanityOfPublishedMemory(tag, __LINE__));
3726   CacheLine *line = G_cache->GetLineOrCreateNew(thr, tag, __LINE__);
3727 
3728   if (1 || line->published().GetRange(a, b)) {
3729     Mask mask(0);
3730     mask.SetRange(a, b);
3731     // TODO(timurrrr): add warning for re-publishing.
3732     ClearPublishedAttribute(line, mask);
3733   }
3734 
3735   line->published().SetRange(a, b);
3736   G_cache->ReleaseLine(thr, tag, line, __LINE__);
3737 
3738   PublishInfo pub_info;
3739   pub_info.tag  = tag;
3740   pub_info.mask.SetRange(a, b);
3741   pub_info.vts  = vts->Clone();
3742   g_publish_info_map->insert(make_pair(tag, pub_info));
3743   G_stats->publish_set++;
3744   if (kDebugPublish)
3745     Printf("PublishRange   : [%p,%p) %p %s vts=%p\n",
3746            a, b, tag, pub_info.mask.ToString().c_str(), vts);
3747   CHECK(CheckSanityOfPublishedMemory(tag, __LINE__));
3748 }
3749 
3750 // Publish memory range [a, b).
PublishRange(TSanThread * thr,uintptr_t a,uintptr_t b,VTS * vts)3751 static void PublishRange(TSanThread *thr, uintptr_t a, uintptr_t b, VTS *vts) {
3752   CHECK(a);
3753   CHECK(a < b);
3754   if (kDebugPublish)
3755     Printf("PublishRange   : [%p,%p), size=%d, tag=%p\n",
3756            a, b, (int)(b - a), CacheLine::ComputeTag(a));
3757   uintptr_t line1_tag = 0, line2_tag = 0;
3758   uintptr_t tag = GetCacheLinesForRange(a, b, &line1_tag, &line2_tag);
3759   if (tag) {
3760     PublishRangeInOneLine(thr, tag, a - tag, b - tag, vts);
3761     return;
3762   }
3763   uintptr_t a_tag = CacheLine::ComputeTag(a);
3764   PublishRangeInOneLine(thr, a, a - a_tag, CacheLine::kLineSize, vts);
3765   for (uintptr_t tag_i = line1_tag; tag_i < line2_tag;
3766        tag_i += CacheLine::kLineSize) {
3767     PublishRangeInOneLine(thr, tag_i, 0, CacheLine::kLineSize, vts);
3768   }
3769   if (b > line2_tag) {
3770     PublishRangeInOneLine(thr, line2_tag, 0, b - line2_tag, vts);
3771   }
3772 }
3773 
3774 // -------- ThreadSanitizerReport -------------- {{{1
3775 struct ThreadSanitizerReport {
3776   // Types of reports.
3777   enum ReportType {
3778     DATA_RACE,
3779     UNLOCK_FOREIGN,
3780     UNLOCK_NONLOCKED,
3781     INVALID_LOCK,
3782     ATOMICITY_VIOLATION,
3783   };
3784 
3785   // Common fields.
3786   ReportType  type;
3787   TID         tid;
3788   StackTrace *stack_trace;
3789 
ReportNameThreadSanitizerReport3790   const char *ReportName() const {
3791     switch (type) {
3792       case DATA_RACE:        return "Race";
3793       case UNLOCK_FOREIGN:   return "UnlockForeign";
3794       case UNLOCK_NONLOCKED: return "UnlockNonLocked";
3795       case INVALID_LOCK:     return "InvalidLock";
3796       case ATOMICITY_VIOLATION: return "AtomicityViolation";
3797     }
3798     CHECK(0);
3799     return NULL;
3800   }
3801 
~ThreadSanitizerReportThreadSanitizerReport3802   virtual ~ThreadSanitizerReport() {
3803     StackTrace::Delete(stack_trace);
3804   }
3805 };
3806 
3807 static bool ThreadSanitizerPrintReport(ThreadSanitizerReport *report);
3808 
3809 // DATA_RACE.
3810 struct ThreadSanitizerDataRaceReport : public ThreadSanitizerReport {
3811   uintptr_t   racey_addr;
3812   string      racey_addr_description;
3813   uintptr_t   last_access_size;
3814   TID         last_access_tid;
3815   SID         last_access_sid;
3816   bool        last_access_is_w;
3817   LSID        last_acces_lsid[2];
3818 
3819   ShadowValue new_sval;
3820   ShadowValue old_sval;
3821 
3822   bool        is_expected;
3823   bool        racey_addr_was_published;
3824 };
3825 
3826 // Report for bad unlock (UNLOCK_FOREIGN, UNLOCK_NONLOCKED).
3827 struct ThreadSanitizerBadUnlockReport : public ThreadSanitizerReport {
3828   LID lid;
3829 };
3830 
3831 // Report for invalid lock addresses (INVALID_LOCK).
3832 struct ThreadSanitizerInvalidLockReport : public ThreadSanitizerReport {
3833   uintptr_t lock_addr;
3834 };
3835 
3836 class AtomicityRegion;
3837 
3838 struct ThreadSanitizerAtomicityViolationReport : public ThreadSanitizerReport {
3839   AtomicityRegion *r1, *r2, *r3;
3840 };
3841 
3842 
3843 // -------- LockHistory ------------- {{{1
3844 // For each thread we store a limited amount of history of locks and unlocks.
3845 // If there is a race report (in hybrid mode) we try to guess a lock
3846 // which might have been used to pass the ownership of the object between
3847 // threads.
3848 //
3849 // Thread1:                    Thread2:
3850 // obj->UpdateMe();
3851 // mu.Lock();
3852 // flag = true;
3853 // mu.Unlock(); // (*)
3854 //                             mu.Lock();  // (**)
3855 //                             bool f = flag;
3856 //                             mu.Unlock();
3857 //                             if (f)
3858 //                                obj->UpdateMeAgain();
3859 //
3860 // For this code a hybrid detector may report a false race.
3861 // LockHistory will find the lock mu and report it.
3862 
3863 struct LockHistory {
3864  public:
3865   // LockHistory which will track no more than `size` recent locks
3866   // and the same amount of unlocks.
LockHistoryLockHistory3867   LockHistory(size_t size): size_(size) { }
3868 
3869   // Record a Lock event.
OnLockLockHistory3870   void OnLock(LID lid) {
3871     g_lock_era++;
3872     Push(LockHistoryElement(lid, g_lock_era), &locks_);
3873   }
3874 
3875   // Record an Unlock event.
OnUnlockLockHistory3876   void OnUnlock(LID lid) {
3877     g_lock_era++;
3878     Push(LockHistoryElement(lid, g_lock_era), &unlocks_);
3879   }
3880 
3881   // Find locks such that:
3882   // - A Lock happend in `l`.
3883   // - An Unlock happened in `u`.
3884   // - Lock's era is greater than Unlock's era.
3885   // - Both eras are greater or equal than min_lock_era.
IntersectLockHistory3886   static bool Intersect(const LockHistory &l, const LockHistory &u,
3887                         int32_t min_lock_era, set<LID> *locks) {
3888     const Queue &lq = l.locks_;
3889     const Queue &uq = u.unlocks_;
3890     for (size_t i = 0; i < lq.size(); i++) {
3891       int32_t l_era = lq[i].lock_era;
3892       if (l_era < min_lock_era) continue;
3893       LID lid = lq[i].lid;
3894       // We don't want to report pure happens-before locks since
3895       // they already create h-b arcs.
3896       if (Lock::LIDtoLock(lid)->is_pure_happens_before()) continue;
3897       for (size_t j = 0; j < uq.size(); j++) {
3898         int32_t u_era = uq[j].lock_era;
3899         if (lid != uq[j].lid) continue;
3900         // Report("LockHistory::Intersect: L%d %d %d %d\n", lid.raw(), min_lock_era, u_era, l_era);
3901         if (u_era < min_lock_era)  continue;
3902         if (u_era > l_era) continue;
3903         locks->insert(lid);
3904       }
3905     }
3906     return !locks->empty();
3907   }
3908 
PrintLocksLockHistory3909   void PrintLocks() const { Print(&locks_); }
PrintUnlocksLockHistory3910   void PrintUnlocks() const { Print(&unlocks_); }
3911 
3912  private:
3913   struct LockHistoryElement {
3914     LID lid;
3915     uint32_t lock_era;
LockHistoryElementLockHistory::LockHistoryElement3916     LockHistoryElement(LID l, uint32_t era)
3917         : lid(l),
3918         lock_era(era) {
3919         }
3920   };
3921 
3922   typedef deque<LockHistoryElement> Queue;
3923 
PushLockHistory3924   void Push(LockHistoryElement e, Queue *q) {
3925     CHECK(q->size() <= size_);
3926     if (q->size() == size_)
3927       q->pop_front();
3928     q->push_back(e);
3929   }
3930 
PrintLockHistory3931   void Print(const Queue *q) const {
3932     set<LID> printed;
3933     for (size_t i = 0; i < q->size(); i++) {
3934       const LockHistoryElement &e = (*q)[i];
3935       if (printed.count(e.lid)) continue;
3936       Report("era %d: \n", e.lock_era);
3937       Lock::ReportLockWithOrWithoutContext(e.lid, true);
3938       printed.insert(e.lid);
3939     }
3940   }
3941 
3942   Queue locks_;
3943   Queue unlocks_;
3944   size_t size_;
3945 };
3946 
3947 // -------- RecentSegmentsCache ------------- {{{1
3948 // For each thread we store a limited amount of recent segments with
3949 // the same VTS and LS as the current segment.
3950 // When a thread enters a new basic block, we can sometimes reuse a
3951 // recent segment if it is the same or not used anymore (see Search()).
3952 //
3953 // We need to flush the cache when current lockset changes or the current
3954 // VTS changes or we do ForgetAllState.
3955 // TODO(timurrrr): probably we can cache segments with different LSes and
3956 // compare their LS with the current LS.
3957 struct RecentSegmentsCache {
3958  public:
RecentSegmentsCacheRecentSegmentsCache3959   RecentSegmentsCache(int cache_size) : cache_size_(cache_size) {}
~RecentSegmentsCacheRecentSegmentsCache3960   ~RecentSegmentsCache() { Clear(); }
3961 
ClearRecentSegmentsCache3962   void Clear() {
3963     ShortenQueue(0);
3964   }
3965 
PushRecentSegmentsCache3966   void Push(SID sid) {
3967     queue_.push_front(sid);
3968     Segment::Ref(sid, "RecentSegmentsCache::ShortenQueue");
3969     ShortenQueue(cache_size_);
3970   }
3971 
ForgetAllStateRecentSegmentsCache3972   void ForgetAllState() {
3973     queue_.clear();  // Don't unref - the segments are already dead.
3974   }
3975 
SearchRecentSegmentsCache3976   INLINE SID Search(CallStack *curr_stack,
3977                     SID curr_sid, /*OUT*/ bool *needs_refill) {
3978     // TODO(timurrrr): we can probably move the matched segment to the head
3979     // of the queue.
3980 
3981     deque<SID>::iterator it = queue_.begin();
3982     for (; it != queue_.end(); it++) {
3983       SID sid = *it;
3984       Segment::AssertLive(sid, __LINE__);
3985       Segment *seg = Segment::Get(sid);
3986 
3987       if (seg->ref_count() == 1 + (sid == curr_sid)) {
3988         // The current segment is not used anywhere else,
3989         // so just replace the stack trace in it.
3990         // The refcount of an unused segment is equal to
3991         // *) 1 if it is stored only in the cache,
3992         // *) 2 if it is the current segment of the Thread.
3993         *needs_refill = true;
3994         return sid;
3995       }
3996 
3997       // Check three top entries of the call stack of the recent segment.
3998       // If they match the current segment stack, don't create a new segment.
3999       // This can probably lead to a little bit wrong stack traces in rare
4000       // occasions but we don't really care that much.
4001       if (kSizeOfHistoryStackTrace > 0) {
4002         size_t n = curr_stack->size();
4003         uintptr_t *emb_trace = Segment::embedded_stack_trace(sid);
4004         if(*emb_trace &&  // This stack trace was filled
4005            curr_stack->size() >= 3 &&
4006            emb_trace[0] == (*curr_stack)[n-1] &&
4007            emb_trace[1] == (*curr_stack)[n-2] &&
4008            emb_trace[2] == (*curr_stack)[n-3]) {
4009           *needs_refill = false;
4010           return sid;
4011         }
4012       }
4013     }
4014 
4015     return SID();
4016   }
4017 
4018  private:
ShortenQueueRecentSegmentsCache4019   void ShortenQueue(size_t flush_to_length) {
4020     while (queue_.size() > flush_to_length) {
4021       SID sid = queue_.back();
4022       Segment::Unref(sid, "RecentSegmentsCache::ShortenQueue");
4023       queue_.pop_back();
4024     }
4025   }
4026 
4027   deque<SID> queue_;
4028   size_t cache_size_;
4029 };
4030 
4031 // -------- TraceInfo ------------------ {{{1
4032 vector<TraceInfo*> *TraceInfo::g_all_traces;
4033 
NewTraceInfo(size_t n_mops,uintptr_t pc)4034 TraceInfo *TraceInfo::NewTraceInfo(size_t n_mops, uintptr_t pc) {
4035   ScopedMallocCostCenter cc("TraceInfo::NewTraceInfo");
4036   size_t mem_size = (sizeof(TraceInfo) + (n_mops - 1) * sizeof(MopInfo));
4037   uint8_t *mem = new uint8_t[mem_size];
4038   memset(mem, 0xab, mem_size);
4039   TraceInfo *res = new (mem) TraceInfo;
4040   res->n_mops_ = n_mops;
4041   res->pc_ = ThreadSanitizerWantToCreateSegmentsOnSblockEntry(pc) ? pc : 0;
4042   res->counter_ = 0;
4043   if (g_all_traces == NULL) {
4044     g_all_traces = new vector<TraceInfo*>;
4045   }
4046   res->literace_storage = NULL;
4047   if (G_flags->literace_sampling != 0) {
4048     ScopedMallocCostCenter cc("TraceInfo::NewTraceInfo::LiteRaceStorage");
4049     size_t index_of_this_trace = g_all_traces->size();
4050     if ((index_of_this_trace % kLiteRaceStorageSize) == 0) {
4051       res->literace_storage = (LiteRaceStorage*)
4052           new LiteRaceCounters [kLiteRaceStorageSize * kLiteRaceNumTids];
4053       memset(res->literace_storage, 0, sizeof(LiteRaceStorage));
4054     } else {
4055       CHECK(index_of_this_trace > 0);
4056       res->literace_storage = (*g_all_traces)[index_of_this_trace - 1]->literace_storage;
4057       CHECK(res->literace_storage);
4058     }
4059     res->storage_index = index_of_this_trace % kLiteRaceStorageSize;
4060   }
4061   g_all_traces->push_back(res);
4062   return res;
4063 }
4064 
PrintTraceProfile()4065 void TraceInfo::PrintTraceProfile() {
4066   if (!G_flags->trace_profile) return;
4067   if (!g_all_traces) return;
4068   int64_t total_counter = 0;
4069   multimap<size_t, TraceInfo*> traces;
4070   for (size_t i = 0; i < g_all_traces->size(); i++) {
4071     TraceInfo *trace = (*g_all_traces)[i];
4072     traces.insert(make_pair(trace->counter(), trace));
4073     total_counter += trace->counter();
4074   }
4075   if (total_counter == 0) return;
4076   Printf("TraceProfile: %ld traces, %lld hits\n",
4077          g_all_traces->size(), total_counter);
4078   int i = 0;
4079   for (multimap<size_t, TraceInfo*>::reverse_iterator it = traces.rbegin();
4080        it != traces.rend(); ++it, i++) {
4081     TraceInfo *trace = it->second;
4082     int64_t c = it->first;
4083     int64_t permile = (c * 1000) / total_counter;
4084     CHECK(trace->n_mops() > 0);
4085     uintptr_t pc = trace->GetMop(0)->pc();
4086     CHECK(pc);
4087     if (permile == 0 || i >= 20) break;
4088     Printf("TR=%p pc: %p %p c=%lld (%lld/1000) n_mops=%ld %s\n",
4089            trace, trace->pc(), pc, c,
4090            permile, trace->n_mops(),
4091            PcToRtnNameAndFilePos(pc).c_str());
4092   }
4093 }
4094 
4095 // -------- Atomicity --------------- {{{1
4096 // An attempt to detect atomicity violations (aka high level races).
4097 // Here we try to find a very restrictive pattern:
4098 // Thread1                    Thread2
4099 //   r1: {
4100 //     mu.Lock();
4101 //     code_r1();
4102 //     mu.Unlock();
4103 //   }
4104 //   r2: {
4105 //     mu.Lock();
4106 //     code_r2();
4107 //     mu.Unlock();
4108 //   }
4109 //                           r3: {
4110 //                             mu.Lock();
4111 //                             code_r3();
4112 //                             mu.Unlock();
4113 //                           }
4114 // We have 3 regions of code such that
4115 // - two of them are in one thread and 3-rd in another thread.
4116 // - all 3 regions have the same lockset,
4117 // - the distance between r1 and r2 is small,
4118 // - there is no h-b arc between r2 and r3,
4119 // - r1 and r2 have different stack traces,
4120 //
4121 // In this situation we report a 'Suspected atomicity violation'.
4122 //
4123 // Current status:
4124 // this code detects atomicity violations on our two motivating examples
4125 // (--gtest_filter=*Atomicity*  --gtest_also_run_disabled_tests) and does
4126 // not overwhelm with false reports.
4127 // However, this functionality is still raw and not tuned for performance.
4128 
4129 // TS_ATOMICITY is on in debug mode or if we enabled it at the build time.
4130 #ifndef TS_ATOMICITY
4131 # define TS_ATOMICITY DEBUG_MODE
4132 #endif
4133 
4134 
4135 struct AtomicityRegion {
4136   int lock_era;
4137   TID tid;
4138   VTS *vts;
4139   StackTrace *stack_trace;
4140   LSID lsid[2];
4141   BitSet access_set[2];
4142   bool used;
4143   int n_mops_since_start;
4144 
PrintAtomicityRegion4145   void Print() {
4146     Report("T%d era=%d nmss=%ld AtomicityRegion:\n  rd: %s\n  wr: %s\n  %s\n%s",
4147            tid.raw(),
4148            lock_era,
4149            n_mops_since_start,
4150            access_set[0].ToString().c_str(),
4151            access_set[1].ToString().c_str(),
4152            TwoLockSetsToString(lsid[false], lsid[true]).c_str(),
4153            stack_trace->ToString().c_str()
4154           );
4155   }
4156 };
4157 
SimilarLockSetForAtomicity(AtomicityRegion * r1,AtomicityRegion * r2)4158 bool SimilarLockSetForAtomicity(AtomicityRegion *r1, AtomicityRegion *r2) {
4159   // Compare only reader locksets (in case one region took reader locks)
4160   return ((r1->lsid[0] == r2->lsid[0]));
4161 }
4162 
4163 static deque<AtomicityRegion *> *g_atomicity_regions;
4164 static map<StackTrace *, int, StackTrace::Less> *reported_atomicity_stacks_;
4165 const size_t kMaxAtomicityRegions = 8;
4166 
HandleAtomicityRegion(AtomicityRegion * atomicity_region)4167 static void HandleAtomicityRegion(AtomicityRegion *atomicity_region) {
4168   if (!g_atomicity_regions) {
4169     g_atomicity_regions = new deque<AtomicityRegion*>;
4170     reported_atomicity_stacks_ = new map<StackTrace *, int, StackTrace::Less>;
4171   }
4172 
4173   if (g_atomicity_regions->size() >= kMaxAtomicityRegions) {
4174     AtomicityRegion *to_delete = g_atomicity_regions->back();
4175     g_atomicity_regions->pop_back();
4176     if (!to_delete->used) {
4177       VTS::Unref(to_delete->vts);
4178       StackTrace::Delete(to_delete->stack_trace);
4179       delete to_delete;
4180     }
4181   }
4182   g_atomicity_regions->push_front(atomicity_region);
4183   size_t n = g_atomicity_regions->size();
4184 
4185   if (0) {
4186     for (size_t i = 0; i < n; i++) {
4187       AtomicityRegion *r = (*g_atomicity_regions)[i];
4188       r->Print();
4189     }
4190   }
4191 
4192   AtomicityRegion *r3 = (*g_atomicity_regions)[0];
4193   for (size_t i = 1; i < n; i++) {
4194     AtomicityRegion *r2 = (*g_atomicity_regions)[i];
4195     if (r2->tid     != r3->tid &&
4196         SimilarLockSetForAtomicity(r2, r3) &&
4197         !VTS::HappensBeforeCached(r2->vts, r3->vts)) {
4198       for (size_t j = i + 1; j < n; j++) {
4199         AtomicityRegion *r1 = (*g_atomicity_regions)[j];
4200         if (r1->tid != r2->tid) continue;
4201         CHECK(r2->lock_era > r1->lock_era);
4202         if (r2->lock_era - r1->lock_era > 2) break;
4203         if (!SimilarLockSetForAtomicity(r1, r2)) continue;
4204         if (StackTrace::Equals(r1->stack_trace, r2->stack_trace)) continue;
4205         if (!(r1->access_set[1].empty() &&
4206               !r2->access_set[1].empty() &&
4207               !r3->access_set[1].empty())) continue;
4208         CHECK(r1->n_mops_since_start <= r2->n_mops_since_start);
4209         if (r2->n_mops_since_start - r1->n_mops_since_start > 5) continue;
4210         if ((*reported_atomicity_stacks_)[r1->stack_trace] > 0) continue;
4211 
4212         (*reported_atomicity_stacks_)[r1->stack_trace]++;
4213         (*reported_atomicity_stacks_)[r2->stack_trace]++;
4214         (*reported_atomicity_stacks_)[r3->stack_trace]++;
4215         r1->used = r2->used = r3->used = true;
4216         ThreadSanitizerAtomicityViolationReport *report =
4217             new ThreadSanitizerAtomicityViolationReport;
4218         report->type = ThreadSanitizerReport::ATOMICITY_VIOLATION;
4219         report->tid = TID(0);
4220         report->stack_trace = r1->stack_trace;
4221         report->r1 = r1;
4222         report->r2 = r2;
4223         report->r3 = r3;
4224         ThreadSanitizerPrintReport(report);
4225         break;
4226       }
4227     }
4228   }
4229 }
4230 
4231 // -------- TSanThread ------------------ {{{1
4232 struct TSanThread {
4233  public:
4234   ThreadLocalStats stats;
4235 
TSanThreadTSanThread4236   TSanThread(TID tid, TID parent_tid, VTS *vts, StackTrace *creation_context,
4237          CallStack *call_stack)
4238     : is_running_(true),
4239       tid_(tid),
4240       sid_(0),
4241       parent_tid_(parent_tid),
4242       max_sp_(0),
4243       min_sp_(0),
4244       stack_size_for_ignore_(0),
4245       fun_r_ignore_(0),
4246       min_sp_for_ignore_(0),
4247       n_mops_since_start_(0),
4248       creation_context_(creation_context),
4249       announced_(false),
4250       rd_lockset_(0),
4251       wr_lockset_(0),
4252       expensive_bits_(0),
4253       vts_at_exit_(NULL),
4254       call_stack_(call_stack),
4255       lock_history_(128),
4256       recent_segments_cache_(G_flags->recent_segments_cache_size),
4257       inside_atomic_op_(),
4258       rand_state_((unsigned)(tid.raw() + (uintptr_t)vts
4259                       + (uintptr_t)creation_context
4260                       + (uintptr_t)call_stack)) {
4261 
4262     NewSegmentWithoutUnrefingOld("TSanThread Creation", vts);
4263     ignore_depth_[0] = ignore_depth_[1] = 0;
4264 
4265     HandleRtnCall(0, 0, IGNORE_BELOW_RTN_UNKNOWN);
4266     ignore_context_[0] = NULL;
4267     ignore_context_[1] = NULL;
4268     if (tid != TID(0) && parent_tid.valid()) {
4269       CHECK(creation_context_);
4270     }
4271 
4272     // Add myself to the array of threads.
4273     CHECK(tid.raw() < G_flags->max_n_threads);
4274     CHECK(all_threads_[tid.raw()] == NULL);
4275     n_threads_ = max(n_threads_, tid.raw() + 1);
4276     all_threads_[tid.raw()] = this;
4277     dead_sids_.reserve(kMaxNumDeadSids);
4278     fresh_sids_.reserve(kMaxNumFreshSids);
4279     ComputeExpensiveBits();
4280   }
4281 
tidTSanThread4282   TID tid() const { return tid_; }
parent_tidTSanThread4283   TID parent_tid() const { return parent_tid_; }
4284 
increment_n_mops_since_startTSanThread4285   void increment_n_mops_since_start() {
4286     n_mops_since_start_++;
4287   }
4288 
4289   // STACK
max_spTSanThread4290   uintptr_t max_sp() const { return max_sp_; }
min_spTSanThread4291   uintptr_t min_sp() const { return min_sp_; }
4292 
randomTSanThread4293   unsigned random() {
4294     return tsan_prng(&rand_state_);
4295   }
4296 
ShouldReportRacesTSanThread4297   bool ShouldReportRaces() const {
4298     return (inside_atomic_op_ == 0);
4299   }
4300 
SetStackTSanThread4301   void SetStack(uintptr_t stack_min, uintptr_t stack_max) {
4302     CHECK(stack_min < stack_max);
4303     // Stay sane. Expect stack less than 64M.
4304     CHECK(stack_max - stack_min <= 64 * 1024 * 1024);
4305     min_sp_ = stack_min;
4306     max_sp_ = stack_max;
4307     if (G_flags->ignore_stack) {
4308       min_sp_for_ignore_ = min_sp_;
4309       stack_size_for_ignore_ = max_sp_ - min_sp_;
4310     } else {
4311       CHECK(min_sp_for_ignore_ == 0 &&
4312             stack_size_for_ignore_ == 0);
4313     }
4314   }
4315 
MemoryIsInStackTSanThread4316   bool MemoryIsInStack(uintptr_t a) {
4317     return a >= min_sp_ && a <= max_sp_;
4318   }
4319 
IgnoreMemoryIfInStackTSanThread4320   bool IgnoreMemoryIfInStack(uintptr_t a) {
4321     return (a - min_sp_for_ignore_) < stack_size_for_ignore_;
4322   }
4323 
4324 
AnnounceTSanThread4325   bool Announce() {
4326     if (announced_) return false;
4327     announced_ = true;
4328     if (tid_ == TID(0)) {
4329       Report("INFO: T0 is program's main thread\n");
4330     } else {
4331       if (G_flags->announce_threads) {
4332         Report("INFO: T%d has been created by T%d at this point: {{{\n%s}}}\n",
4333                tid_.raw(), parent_tid_.raw(),
4334                creation_context_->ToString().c_str());
4335         TSanThread * parent = GetIfExists(parent_tid_);
4336         CHECK(parent);
4337         parent->Announce();
4338       } else {
4339         Report("INFO: T%d has been created by T%d. "
4340                "Use --announce-threads to see the creation stack.\n",
4341                tid_.raw(), parent_tid_.raw());
4342       }
4343     }
4344     return true;
4345   }
4346 
ThreadNameTSanThread4347   string ThreadName() const {
4348     char buff[100];
4349     snprintf(buff, sizeof(buff), "T%d", tid().raw());
4350     string res = buff;
4351     if (thread_name_.length() > 0) {
4352       res += " (";
4353       res += thread_name_;
4354       res += ")";
4355     }
4356     return res;
4357   }
4358 
is_runningTSanThread4359   bool is_running() const { return is_running_; }
4360 
ComputeExpensiveBitsTSanThread4361   INLINE void ComputeExpensiveBits() {
4362     bool has_expensive_flags = G_flags->trace_level > 0 ||
4363         G_flags->show_stats > 1                      ||
4364         G_flags->sample_events > 0;
4365 
4366     expensive_bits_ =
4367         (ignore_depth_[0] != 0) |
4368         ((ignore_depth_[1] != 0) << 1) |
4369         ((has_expensive_flags == true) << 2);
4370   }
4371 
expensive_bitsTSanThread4372   int expensive_bits() { return expensive_bits_; }
ignore_readsTSanThread4373   int ignore_reads() { return expensive_bits() & 1; }
ignore_writesTSanThread4374   int ignore_writes() { return (expensive_bits() >> 1) & 1; }
4375 
4376   // ignore
set_ignore_accessesTSanThread4377   INLINE void set_ignore_accesses(bool is_w, bool on) {
4378     ignore_depth_[is_w] += on ? 1 : -1;
4379     CHECK(ignore_depth_[is_w] >= 0);
4380     ComputeExpensiveBits();
4381     if (on && G_flags->save_ignore_context) {
4382       StackTrace::Delete(ignore_context_[is_w]);
4383       ignore_context_[is_w] = CreateStackTrace(0, 3);
4384     }
4385   }
set_ignore_all_accessesTSanThread4386   INLINE void set_ignore_all_accesses(bool on) {
4387     set_ignore_accesses(false, on);
4388     set_ignore_accesses(true, on);
4389   }
4390 
GetLastIgnoreContextTSanThread4391   StackTrace *GetLastIgnoreContext(bool is_w) {
4392     return ignore_context_[is_w];
4393   }
4394 
sidTSanThread4395   SID sid() const {
4396     return sid_;
4397   }
4398 
segmentTSanThread4399   Segment *segment() const {
4400     CHECK(sid().valid());
4401     Segment::AssertLive(sid(), __LINE__);
4402     return Segment::Get(sid());
4403   }
4404 
vtsTSanThread4405   VTS *vts() const {
4406     return segment()->vts();
4407   }
4408 
set_thread_nameTSanThread4409   void set_thread_name(const char *name) {
4410     thread_name_ = string(name);
4411   }
4412 
HandleThreadEndTSanThread4413   void HandleThreadEnd() {
4414     CHECK(is_running_);
4415     is_running_ = false;
4416     CHECK(!vts_at_exit_);
4417     vts_at_exit_ = vts()->Clone();
4418     CHECK(vts_at_exit_);
4419     FlushDeadSids();
4420     ReleaseFreshSids();
4421     call_stack_ = NULL;
4422   }
4423 
4424   // Return the TID of the joined child and it's vts
HandleThreadJoinAfterTSanThread4425   TID HandleThreadJoinAfter(VTS **vts_at_exit, TID joined_tid) {
4426     CHECK(joined_tid.raw() > 0);
4427     CHECK(GetIfExists(joined_tid) != NULL);
4428     TSanThread* joined_thread  = TSanThread::Get(joined_tid);
4429     // Sometimes the joined thread is not truly dead yet.
4430     // In that case we just take the current vts.
4431     if (joined_thread->is_running_)
4432       *vts_at_exit = joined_thread->vts()->Clone();
4433     else
4434       *vts_at_exit = joined_thread->vts_at_exit_;
4435 
4436     if (*vts_at_exit == NULL) {
4437       Printf("vts_at_exit==NULL; parent=%d, child=%d\n",
4438              tid().raw(), joined_tid.raw());
4439     }
4440     CHECK(*vts_at_exit);
4441     if (0)
4442     Printf("T%d: vts_at_exit_: %s\n", joined_tid.raw(),
4443            (*vts_at_exit)->ToString().c_str());
4444     return joined_tid;
4445   }
4446 
NumberOfThreadsTSanThread4447   static int NumberOfThreads() {
4448     return INTERNAL_ANNOTATE_UNPROTECTED_READ(n_threads_);
4449   }
4450 
GetIfExistsTSanThread4451   static TSanThread *GetIfExists(TID tid) {
4452     if (tid.raw() < NumberOfThreads())
4453       return Get(tid);
4454     return NULL;
4455   }
4456 
GetTSanThread4457   static TSanThread *Get(TID tid) {
4458     DCHECK(tid.raw() < NumberOfThreads());
4459     return all_threads_[tid.raw()];
4460   }
4461 
HandleAccessSetTSanThread4462   void HandleAccessSet() {
4463     BitSet *rd_set = lock_era_access_set(false);
4464     BitSet *wr_set = lock_era_access_set(true);
4465     if (rd_set->empty() && wr_set->empty()) return;
4466     CHECK(G_flags->atomicity && !G_flags->pure_happens_before);
4467     AtomicityRegion *atomicity_region = new AtomicityRegion;
4468     atomicity_region->lock_era = g_lock_era;
4469     atomicity_region->tid = tid();
4470     atomicity_region->vts = vts()->Clone();
4471     atomicity_region->lsid[0] = lsid(0);
4472     atomicity_region->lsid[1] = lsid(1);
4473     atomicity_region->access_set[0] = *rd_set;
4474     atomicity_region->access_set[1] = *wr_set;
4475     atomicity_region->stack_trace = CreateStackTrace();
4476     atomicity_region->used = false;
4477     atomicity_region->n_mops_since_start = this->n_mops_since_start_;
4478     // atomicity_region->Print();
4479     // Printf("----------- %s\n", __FUNCTION__);
4480     // ReportStackTrace(0, 7);
4481     HandleAtomicityRegion(atomicity_region);
4482   }
4483 
4484   // Locks
HandleLockTSanThread4485   void HandleLock(uintptr_t lock_addr, bool is_w_lock) {
4486     Lock *lock = Lock::LookupOrCreate(lock_addr);
4487 
4488     if (debug_lock) {
4489       Printf("T%d lid=%d %sLock   %p; %s\n",
4490            tid_.raw(), lock->lid().raw(),
4491            is_w_lock ? "Wr" : "Rd",
4492            lock_addr,
4493            LockSet::ToString(lsid(is_w_lock)).c_str());
4494 
4495       ReportStackTrace(0, 7);
4496     }
4497 
4498     // NOTE: we assume that all locks can be acquired recurively.
4499     // No warning about recursive locking will be issued.
4500     if (is_w_lock) {
4501       // Recursive locks are properly handled because LockSet is in fact a
4502       // multiset.
4503       wr_lockset_ = LockSet::Add(wr_lockset_, lock);
4504       rd_lockset_ = LockSet::Add(rd_lockset_, lock);
4505       lock->WrLock(tid_, CreateStackTrace());
4506     } else {
4507       if (lock->wr_held()) {
4508         ReportStackTrace();
4509       }
4510       rd_lockset_ = LockSet::Add(rd_lockset_, lock);
4511       lock->RdLock(CreateStackTrace());
4512     }
4513 
4514     if (lock->is_pure_happens_before()) {
4515       if (is_w_lock) {
4516         HandleWait(lock->wr_signal_addr());
4517       } else {
4518         HandleWait(lock->rd_signal_addr());
4519       }
4520     }
4521 
4522     if (G_flags->suggest_happens_before_arcs) {
4523       lock_history_.OnLock(lock->lid());
4524     }
4525     NewSegmentForLockingEvent();
4526     lock_era_access_set_[0].Clear();
4527     lock_era_access_set_[1].Clear();
4528   }
4529 
HandleUnlockTSanThread4530   void HandleUnlock(uintptr_t lock_addr) {
4531     HandleAccessSet();
4532 
4533     Lock *lock = Lock::Lookup(lock_addr);
4534     // If the lock is not found, report an error.
4535     if (lock == NULL) {
4536       ThreadSanitizerInvalidLockReport *report =
4537           new ThreadSanitizerInvalidLockReport;
4538       report->type = ThreadSanitizerReport::INVALID_LOCK;
4539       report->tid = tid();
4540       report->lock_addr = lock_addr;
4541       report->stack_trace = CreateStackTrace();
4542       ThreadSanitizerPrintReport(report);
4543       return;
4544     }
4545     bool is_w_lock = lock->wr_held();
4546 
4547     if (debug_lock) {
4548       Printf("T%d lid=%d %sUnlock %p; %s\n",
4549              tid_.raw(), lock->lid().raw(),
4550              is_w_lock ? "Wr" : "Rd",
4551              lock_addr,
4552              LockSet::ToString(lsid(is_w_lock)).c_str());
4553       ReportStackTrace(0, 7);
4554     }
4555 
4556     if (lock->is_pure_happens_before()) {
4557       // reader unlock signals only to writer lock,
4558       // writer unlock signals to both.
4559       if (is_w_lock) {
4560         HandleSignal(lock->rd_signal_addr());
4561       }
4562       HandleSignal(lock->wr_signal_addr());
4563     }
4564 
4565     if (!lock->wr_held() && !lock->rd_held()) {
4566       ThreadSanitizerBadUnlockReport *report =
4567           new ThreadSanitizerBadUnlockReport;
4568       report->type = ThreadSanitizerReport::UNLOCK_NONLOCKED;
4569       report->tid = tid();
4570       report->lid = lock->lid();
4571       report->stack_trace = CreateStackTrace();
4572       ThreadSanitizerPrintReport(report);
4573       return;
4574     }
4575 
4576     bool removed = false;
4577     if (is_w_lock) {
4578       lock->WrUnlock();
4579       removed =  LockSet::Remove(wr_lockset_, lock, &wr_lockset_)
4580               && LockSet::Remove(rd_lockset_, lock, &rd_lockset_);
4581     } else {
4582       lock->RdUnlock();
4583       removed = LockSet::Remove(rd_lockset_, lock, &rd_lockset_);
4584     }
4585 
4586     if (!removed) {
4587       ThreadSanitizerBadUnlockReport *report =
4588           new ThreadSanitizerBadUnlockReport;
4589       report->type = ThreadSanitizerReport::UNLOCK_FOREIGN;
4590       report->tid = tid();
4591       report->lid = lock->lid();
4592       report->stack_trace = CreateStackTrace();
4593       ThreadSanitizerPrintReport(report);
4594     }
4595 
4596     if (G_flags->suggest_happens_before_arcs) {
4597       lock_history_.OnUnlock(lock->lid());
4598     }
4599 
4600     NewSegmentForLockingEvent();
4601     lock_era_access_set_[0].Clear();
4602     lock_era_access_set_[1].Clear();
4603   }
4604 
4605   // Handles memory access with race reports suppressed.
4606   void HandleAtomicMop(uintptr_t a,
4607                        uintptr_t pc,
4608                        tsan_atomic_op op,
4609                        tsan_memory_order mo,
4610                        size_t size);
4611 
HandleForgetSignallerTSanThread4612   void HandleForgetSignaller(uintptr_t cv) {
4613     SignallerMap::iterator it = signaller_map_->find(cv);
4614     if (it != signaller_map_->end()) {
4615       if (debug_happens_before) {
4616         Printf("T%d: ForgetSignaller: %p:\n    %s\n", tid_.raw(), cv,
4617             (it->second.vts)->ToString().c_str());
4618         if (G_flags->debug_level >= 1) {
4619           ReportStackTrace();
4620         }
4621       }
4622       VTS::Unref(it->second.vts);
4623       signaller_map_->erase(it);
4624     }
4625   }
4626 
lsidTSanThread4627   LSID lsid(bool is_w) {
4628     return is_w ? wr_lockset_ : rd_lockset_;
4629   }
4630 
lock_historyTSanThread4631   const LockHistory &lock_history() { return lock_history_; }
4632 
4633   // SIGNAL/WAIT events.
HandleWaitTSanThread4634   void HandleWait(uintptr_t cv) {
4635 
4636     SignallerMap::iterator it = signaller_map_->find(cv);
4637     if (it != signaller_map_->end()) {
4638       const VTS *signaller_vts = it->second.vts;
4639       NewSegmentForWait(signaller_vts);
4640     }
4641 
4642     if (debug_happens_before) {
4643       Printf("T%d: Wait: %p:\n    %s %s\n", tid_.raw(),
4644              cv,
4645              vts()->ToString().c_str(),
4646              Segment::ToString(sid()).c_str());
4647       if (G_flags->debug_level >= 1) {
4648         ReportStackTrace();
4649       }
4650     }
4651   }
4652 
HandleSignalTSanThread4653   void HandleSignal(uintptr_t cv) {
4654     Signaller *signaller = &(*signaller_map_)[cv];
4655     if (!signaller->vts) {
4656       signaller->vts = vts()->Clone();
4657     } else {
4658       VTS *new_vts = VTS::Join(signaller->vts, vts());
4659       VTS::Unref(signaller->vts);
4660       signaller->vts = new_vts;
4661     }
4662     NewSegmentForSignal();
4663     if (debug_happens_before) {
4664       Printf("T%d: Signal: %p:\n    %s %s\n    %s\n", tid_.raw(), cv,
4665              vts()->ToString().c_str(), Segment::ToString(sid()).c_str(),
4666              (signaller->vts)->ToString().c_str());
4667       if (G_flags->debug_level >= 1) {
4668         ReportStackTrace();
4669       }
4670     }
4671   }
4672 
NewSegmentWithoutUnrefingOldTSanThread4673   void INLINE NewSegmentWithoutUnrefingOld(const char *call_site,
4674                                            VTS *new_vts) {
4675     DCHECK(new_vts);
4676     SID new_sid = Segment::AddNewSegment(tid(), new_vts,
4677                                          rd_lockset_, wr_lockset_);
4678     SID old_sid = sid();
4679     if (old_sid.raw() != 0 && new_vts != vts()) {
4680       // Flush the cache if VTS changed - the VTS won't repeat.
4681       recent_segments_cache_.Clear();
4682     }
4683     sid_ = new_sid;
4684     Segment::Ref(new_sid, "TSanThread::NewSegmentWithoutUnrefingOld");
4685 
4686     if (kSizeOfHistoryStackTrace > 0) {
4687       FillEmbeddedStackTrace(Segment::embedded_stack_trace(sid()));
4688     }
4689     if (0)
4690     Printf("2: %s T%d/S%d old_sid=%d NewSegment: %s\n", call_site,
4691            tid().raw(), sid().raw(), old_sid.raw(),
4692          vts()->ToString().c_str());
4693   }
4694 
NewSegmentTSanThread4695   void INLINE NewSegment(const char *call_site, VTS *new_vts) {
4696     SID old_sid = sid();
4697     NewSegmentWithoutUnrefingOld(call_site, new_vts);
4698     Segment::Unref(old_sid, "TSanThread::NewSegment");
4699   }
4700 
NewSegmentForLockingEventTSanThread4701   void NewSegmentForLockingEvent() {
4702     // Flush the cache since we can't reuse segments with different lockset.
4703     recent_segments_cache_.Clear();
4704     NewSegment(__FUNCTION__, vts()->Clone());
4705   }
4706 
NewSegmentForMallocEventTSanThread4707   void NewSegmentForMallocEvent() {
4708     // Flush the cache since we can't reuse segments with different lockset.
4709     recent_segments_cache_.Clear();
4710     NewSegment(__FUNCTION__, vts()->Clone());
4711   }
4712 
4713 
SetTopPcTSanThread4714   void SetTopPc(uintptr_t pc) {
4715     if (pc) {
4716       DCHECK(!call_stack_->empty());
4717       call_stack_->back() = pc;
4718     }
4719   }
4720 
HandleSblockEnterSlowLockedTSanThread4721   void NOINLINE HandleSblockEnterSlowLocked() {
4722     AssertTILHeld();
4723     FlushStateIfOutOfSegments(this);
4724     this->stats.history_creates_new_segment++;
4725     VTS *new_vts = vts()->Clone();
4726     NewSegment("HandleSblockEnter", new_vts);
4727     recent_segments_cache_.Push(sid());
4728     GetSomeFreshSids();  // fill the thread-local SID cache.
4729   }
4730 
HandleSblockEnterTSanThread4731   INLINE bool HandleSblockEnter(uintptr_t pc, bool allow_slow_path) {
4732     DCHECK(G_flags->keep_history);
4733     if (!pc) return true;
4734 
4735     this->stats.events[SBLOCK_ENTER]++;
4736 
4737     SetTopPc(pc);
4738 
4739     bool refill_stack = false;
4740     SID match = recent_segments_cache_.Search(call_stack_, sid(),
4741                                               /*OUT*/&refill_stack);
4742     DCHECK(kSizeOfHistoryStackTrace > 0);
4743 
4744     if (match.valid()) {
4745       // This part is 100% thread-local, no need for locking.
4746       if (sid_ != match) {
4747         Segment::Ref(match, "TSanThread::HandleSblockEnter");
4748         this->AddDeadSid(sid_, "TSanThread::HandleSblockEnter");
4749         sid_ = match;
4750       }
4751       if (refill_stack) {
4752         this->stats.history_reuses_segment++;
4753         FillEmbeddedStackTrace(Segment::embedded_stack_trace(sid()));
4754       } else {
4755         this->stats.history_uses_same_segment++;
4756       }
4757     } else if (fresh_sids_.size() > 0) {
4758       // We have a fresh ready-to-use segment in thread local cache.
4759       SID fresh_sid = fresh_sids_.back();
4760       fresh_sids_.pop_back();
4761       Segment::SetupFreshSid(fresh_sid, tid(), vts()->Clone(),
4762                              rd_lockset_, wr_lockset_);
4763       this->AddDeadSid(sid_, "TSanThread::HandleSblockEnter-1");
4764       Segment::Ref(fresh_sid, "TSanThread::HandleSblockEnter-1");
4765       sid_ = fresh_sid;
4766       recent_segments_cache_.Push(sid());
4767       FillEmbeddedStackTrace(Segment::embedded_stack_trace(sid()));
4768       this->stats.history_uses_preallocated_segment++;
4769     } else {
4770       if (!allow_slow_path) return false;
4771       AssertTILHeld();
4772       // No fresh SIDs available, have to grab a lock and get few.
4773       HandleSblockEnterSlowLocked();
4774     }
4775     return true;
4776   }
4777 
NewSegmentForWaitTSanThread4778   void NewSegmentForWait(const VTS *signaller_vts) {
4779     const VTS *current_vts   = vts();
4780     if (0)
4781     Printf("T%d NewSegmentForWait: \n  %s\n  %s\n", tid().raw(),
4782            current_vts->ToString().c_str(),
4783            signaller_vts->ToString().c_str());
4784     // We don't want to create a happens-before arc if it will be redundant.
4785     if (!VTS::HappensBeforeCached(signaller_vts, current_vts)) {
4786       VTS *new_vts = VTS::Join(current_vts, signaller_vts);
4787       NewSegment("NewSegmentForWait", new_vts);
4788     }
4789     DCHECK(VTS::HappensBeforeCached(signaller_vts, vts()));
4790   }
4791 
NewSegmentForSignalTSanThread4792   void NewSegmentForSignal() {
4793     VTS *cur_vts = vts();
4794     VTS *new_vts = VTS::CopyAndTick(cur_vts, tid());
4795     NewSegment("NewSegmentForSignal", new_vts);
4796   }
4797 
4798   // When creating a child thread, we need to know
4799   // 1. where the thread was created (ctx)
4800   // 2. What was the vector clock of the parent thread (vts).
4801 
4802   struct ThreadCreateInfo {
4803     StackTrace *ctx;
4804     VTS        *vts;
4805   };
4806 
StopIgnoringAccessesInT0BecauseNewThreadStartedTSanThread4807   static void StopIgnoringAccessesInT0BecauseNewThreadStarted() {
4808     AssertTILHeld();
4809     if (g_so_far_only_one_thread) {
4810       g_so_far_only_one_thread = false;
4811       Get(TID(0))->set_ignore_all_accesses(false);
4812     }
4813   }
4814 
4815   // This event comes before the child is created (e.g. just
4816   // as we entered pthread_create).
HandleThreadCreateBeforeTSanThread4817   void HandleThreadCreateBefore(TID parent_tid, uintptr_t pc) {
4818     CHECK(parent_tid == tid());
4819     StopIgnoringAccessesInT0BecauseNewThreadStarted();
4820     // Store ctx and vts under TID(0).
4821     ThreadCreateInfo info;
4822     info.ctx = CreateStackTrace(pc);
4823     info.vts = vts()->Clone();
4824     CHECK(info.ctx && info.vts);
4825     child_tid_to_create_info_[TID(0)] = info;
4826     // Tick vts.
4827     this->NewSegmentForSignal();
4828 
4829     if (debug_thread) {
4830       Printf("T%d: THR_CREATE_BEFORE\n", parent_tid.raw());
4831     }
4832   }
4833 
4834   // This event comes when we are exiting the thread creation routine.
4835   // It may appear before *or* after THR_START event, at least with PIN.
HandleThreadCreateAfterTSanThread4836   void HandleThreadCreateAfter(TID parent_tid, TID child_tid) {
4837     CHECK(parent_tid == tid());
4838     // Place the info under child_tid if we did not use it yet.
4839     if (child_tid_to_create_info_.count(TID(0))){
4840       child_tid_to_create_info_[child_tid] = child_tid_to_create_info_[TID(0)];
4841       child_tid_to_create_info_.erase(TID(0));
4842     }
4843 
4844     if (debug_thread) {
4845       Printf("T%d: THR_CREATE_AFTER %d\n", parent_tid.raw(), child_tid.raw());
4846     }
4847   }
4848 
HandleChildThreadStartTSanThread4849   void HandleChildThreadStart(TID child_tid, VTS **vts, StackTrace **ctx) {
4850     TSanThread *parent = this;
4851     ThreadCreateInfo info;
4852     if (child_tid_to_create_info_.count(child_tid)) {
4853       // We already seen THR_CREATE_AFTER, so the info is under child_tid.
4854       info = child_tid_to_create_info_[child_tid];
4855       child_tid_to_create_info_.erase(child_tid);
4856       CHECK(info.ctx && info.vts);
4857     } else if (child_tid_to_create_info_.count(TID(0))){
4858       // We have not seen THR_CREATE_AFTER, but already seen THR_CREATE_BEFORE.
4859       info = child_tid_to_create_info_[TID(0)];
4860       child_tid_to_create_info_.erase(TID(0));
4861       CHECK(info.ctx && info.vts);
4862     } else {
4863       // We have not seen THR_CREATE_BEFORE/THR_CREATE_AFTER.
4864       // If the tool is single-threaded (valgrind) these events are redundant.
4865       info.ctx = parent->CreateStackTrace();
4866       info.vts = parent->vts()->Clone();
4867       parent->NewSegmentForSignal();
4868     }
4869     *ctx = info.ctx;
4870     VTS *singleton = VTS::CreateSingleton(child_tid);
4871     *vts = VTS::Join(singleton, info.vts);
4872     VTS::Unref(singleton);
4873     VTS::Unref(info.vts);
4874 
4875 
4876     if (debug_thread) {
4877       Printf("T%d: THR_START parent: T%d : %s %s\n", child_tid.raw(),
4878              parent->tid().raw(),
4879              parent->vts()->ToString().c_str(),
4880              (*vts)->ToString().c_str());
4881       if (G_flags->announce_threads) {
4882         Printf("%s\n", (*ctx)->ToString().c_str());
4883       }
4884     }
4885 
4886     // Parent should have ticked its VTS so there should be no h-b.
4887     DCHECK(!VTS::HappensBefore(parent->vts(), *vts));
4888   }
4889 
4890   // Support for Cyclic Barrier, e.g. pthread_barrier_t.
4891   // We need to create (barrier_count-1)^2 h-b arcs between
4892   // threads blocking on a barrier. We should not create any h-b arcs
4893   // for two calls to barrier_wait if the barrier was reset between then.
4894   struct CyclicBarrierInfo {
4895     // The value given to barrier_init.
4896     uint32_t barrier_count;
4897     // How many times we may block on this barrier before resetting.
4898     int32_t calls_before_reset;
4899     // How many times we entered the 'wait-before' and 'wait-after' handlers.
4900     int32_t n_wait_before, n_wait_after;
4901   };
4902   // The following situation is possible:
4903   // - N threads blocked on a barrier.
4904   // - All N threads reached the barrier and we started getting 'wait-after'
4905   //   events, but did not yet get all of them.
4906   // - N threads blocked on the barrier again and we started getting
4907   //   'wait-before' events from the next barrier epoch.
4908   // - We continue getting 'wait-after' events from the previous epoch.
4909   //
4910   // We don't want to create h-b arcs between barrier events of different
4911   // epochs, so we use 'barrier + (epoch % 4)' as an object on which we
4912   // signal and wait (it is unlikely that more than 4 epochs are live at once.
4913   enum { kNumberOfPossibleBarrierEpochsLiveAtOnce = 4 };
4914   // Maps the barrier pointer to CyclicBarrierInfo.
4915   typedef unordered_map<uintptr_t, CyclicBarrierInfo> CyclicBarrierMap;
4916 
GetCyclicBarrierInfoTSanThread4917   CyclicBarrierInfo &GetCyclicBarrierInfo(uintptr_t barrier) {
4918     if (cyclic_barrier_map_ == NULL) {
4919       cyclic_barrier_map_ = new CyclicBarrierMap;
4920     }
4921     return (*cyclic_barrier_map_)[barrier];
4922   }
4923 
HandleBarrierInitTSanThread4924   void HandleBarrierInit(uintptr_t barrier, uint32_t n) {
4925     CyclicBarrierInfo &info = GetCyclicBarrierInfo(barrier);
4926     CHECK(n > 0);
4927     memset(&info, 0, sizeof(CyclicBarrierInfo));
4928     info.barrier_count = n;
4929   }
4930 
HandleBarrierWaitBeforeTSanThread4931   void HandleBarrierWaitBefore(uintptr_t barrier) {
4932     CyclicBarrierInfo &info = GetCyclicBarrierInfo(barrier);
4933 
4934     CHECK(info.calls_before_reset >= 0);
4935     int32_t epoch = info.n_wait_before / info.barrier_count;
4936     epoch %= kNumberOfPossibleBarrierEpochsLiveAtOnce;
4937     info.n_wait_before++;
4938     if (info.calls_before_reset == 0) {
4939       // We are blocking the first time after reset. Clear the VTS.
4940       info.calls_before_reset = info.barrier_count;
4941       Signaller &signaller = (*signaller_map_)[barrier + epoch];
4942       VTS::Unref(signaller.vts);
4943       signaller.vts = NULL;
4944       if (debug_happens_before) {
4945         Printf("T%d barrier %p (epoch %d) reset\n", tid().raw(),
4946                barrier, epoch);
4947       }
4948     }
4949     info.calls_before_reset--;
4950     // Signal to all threads that blocked on this barrier.
4951     if (debug_happens_before) {
4952       Printf("T%d barrier %p (epoch %d) wait before\n", tid().raw(),
4953              barrier, epoch);
4954     }
4955     HandleSignal(barrier + epoch);
4956   }
4957 
HandleBarrierWaitAfterTSanThread4958   void HandleBarrierWaitAfter(uintptr_t barrier) {
4959     CyclicBarrierInfo &info = GetCyclicBarrierInfo(barrier);
4960     int32_t epoch = info.n_wait_after / info.barrier_count;
4961     epoch %= kNumberOfPossibleBarrierEpochsLiveAtOnce;
4962     info.n_wait_after++;
4963     if (debug_happens_before) {
4964       Printf("T%d barrier %p (epoch %d) wait after\n", tid().raw(),
4965              barrier, epoch);
4966     }
4967     HandleWait(barrier + epoch);
4968   }
4969 
4970   // Call stack  -------------
PopCallStackTSanThread4971   void PopCallStack() {
4972     CHECK(!call_stack_->empty());
4973     call_stack_->pop_back();
4974   }
4975 
HandleRtnCallTSanThread4976   void HandleRtnCall(uintptr_t call_pc, uintptr_t target_pc,
4977                      IGNORE_BELOW_RTN ignore_below) {
4978     this->stats.events[RTN_CALL]++;
4979     if (!call_stack_->empty() && call_pc) {
4980       call_stack_->back() = call_pc;
4981     }
4982     call_stack_->push_back(target_pc);
4983 
4984     bool ignore = false;
4985     if (ignore_below == IGNORE_BELOW_RTN_UNKNOWN) {
4986       if (ignore_below_cache_.Lookup(target_pc, &ignore) == false) {
4987         ignore = ThreadSanitizerIgnoreAccessesBelowFunction(target_pc);
4988         ignore_below_cache_.Insert(target_pc, ignore);
4989         G_stats->ignore_below_cache_miss++;
4990       } else {
4991         // Just in case, check the result of caching.
4992         DCHECK(ignore ==
4993                ThreadSanitizerIgnoreAccessesBelowFunction(target_pc));
4994       }
4995     } else {
4996       DCHECK(ignore_below == IGNORE_BELOW_RTN_YES ||
4997              ignore_below == IGNORE_BELOW_RTN_NO);
4998       ignore = ignore_below == IGNORE_BELOW_RTN_YES;
4999     }
5000 
5001     if (fun_r_ignore_) {
5002       fun_r_ignore_++;
5003     } else if (ignore) {
5004       fun_r_ignore_ = 1;
5005       set_ignore_all_accesses(true);
5006     }
5007   }
5008 
HandleRtnExitTSanThread5009   void HandleRtnExit() {
5010     this->stats.events[RTN_EXIT]++;
5011     if (!call_stack_->empty()) {
5012       call_stack_->pop_back();
5013       if (fun_r_ignore_) {
5014         if (--fun_r_ignore_ == 0) {
5015           set_ignore_all_accesses(false);
5016         }
5017       }
5018     }
5019   }
5020 
GetCallstackEntryTSanThread5021   uintptr_t GetCallstackEntry(size_t offset_from_top) {
5022     if (offset_from_top >= call_stack_->size()) return 0;
5023     return (*call_stack_)[call_stack_->size() - offset_from_top - 1];
5024   }
5025 
CallStackRtnNameTSanThread5026   string CallStackRtnName(size_t offset_from_top = 0) {
5027     if (call_stack_->size() <= offset_from_top)
5028       return "";
5029     uintptr_t pc = (*call_stack_)[call_stack_->size() - offset_from_top - 1];
5030     return PcToRtnName(pc, false);
5031   }
5032 
CallStackToStringRtnOnlyTSanThread5033   string CallStackToStringRtnOnly(int len) {
5034     string res;
5035     for (int i = 0; i < len; i++) {
5036       if (i)
5037         res += " ";
5038       res += CallStackRtnName(i);
5039     }
5040     return res;
5041   }
5042 
CallStackTopPcTSanThread5043   uintptr_t CallStackTopPc() {
5044     if (call_stack_->empty())
5045       return 0;
5046     return call_stack_->back();
5047   }
5048 
FillEmbeddedStackTraceTSanThread5049   INLINE void FillEmbeddedStackTrace(uintptr_t *emb_trace) {
5050     size_t size = min(call_stack_->size(), (size_t)kSizeOfHistoryStackTrace);
5051     size_t idx = call_stack_->size() - 1;
5052     uintptr_t *pcs = call_stack_->pcs();
5053     for (size_t i = 0; i < size; i++, idx--) {
5054       emb_trace[i] = pcs[idx];
5055     }
5056     if (size < (size_t) kSizeOfHistoryStackTrace) {
5057       emb_trace[size] = 0;
5058     }
5059   }
5060 
FillStackTraceTSanThread5061   INLINE void FillStackTrace(StackTrace *trace, size_t size) {
5062     size_t idx = call_stack_->size() - 1;
5063     uintptr_t *pcs = call_stack_->pcs();
5064     for (size_t i = 0; i < size; i++, idx--) {
5065       trace->Set(i, pcs[idx]);
5066     }
5067   }
5068 
CreateStackTraceTSanThread5069   INLINE StackTrace *CreateStackTrace(uintptr_t pc = 0,
5070                                       int max_len = -1,
5071                                       int capacity = 0) {
5072     if (!call_stack_->empty() && pc) {
5073       call_stack_->back() = pc;
5074     }
5075     if (max_len <= 0) {
5076       max_len = G_flags->num_callers;
5077     }
5078     int size = call_stack_->size();
5079     if (size > max_len)
5080       size = max_len;
5081     StackTrace *res = StackTrace::CreateNewEmptyStackTrace(size, capacity);
5082     FillStackTrace(res, size);
5083     return res;
5084   }
5085 
ReportStackTraceTSanThread5086   void ReportStackTrace(uintptr_t pc = 0, int max_len = -1) {
5087     StackTrace *trace = CreateStackTrace(pc, max_len);
5088     Report("%s", trace->ToString().c_str());
5089     StackTrace::Delete(trace);
5090   }
5091 
ForgetAllStateTSanThread5092   static void ForgetAllState() {
5093     // G_flags->debug_level = 2;
5094     for (int i = 0; i < TSanThread::NumberOfThreads(); i++) {
5095       TSanThread *thr = Get(TID(i));
5096       thr->recent_segments_cache_.ForgetAllState();
5097       thr->sid_ = SID();  // Reset the old SID so we don't try to read its VTS.
5098       VTS *singleton_vts = VTS::CreateSingleton(TID(i), 2);
5099       if (thr->is_running()) {
5100         thr->NewSegmentWithoutUnrefingOld("ForgetAllState", singleton_vts);
5101       }
5102       for (map<TID, ThreadCreateInfo>::iterator j =
5103                thr->child_tid_to_create_info_.begin();
5104            j != thr->child_tid_to_create_info_.end(); ++j) {
5105         ThreadCreateInfo &info = j->second;
5106         VTS::Unref(info.vts);
5107         // The parent's VTS should neither happen-before nor equal the child's.
5108         info.vts = VTS::CreateSingleton(TID(i), 1);
5109       }
5110       if (thr->vts_at_exit_) {
5111         VTS::Unref(thr->vts_at_exit_);
5112         thr->vts_at_exit_ = singleton_vts->Clone();
5113       }
5114       thr->dead_sids_.clear();
5115       thr->fresh_sids_.clear();
5116     }
5117     signaller_map_->ClearAndDeleteElements();
5118   }
5119 
InitClassMembersTSanThread5120   static void InitClassMembers() {
5121     ScopedMallocCostCenter malloc_cc("InitClassMembers");
5122     all_threads_        = new TSanThread*[G_flags->max_n_threads];
5123     memset(all_threads_, 0, sizeof(TSanThread*) * G_flags->max_n_threads);
5124     n_threads_          = 0;
5125     signaller_map_      = new SignallerMap;
5126   }
5127 
lock_era_access_setTSanThread5128   BitSet *lock_era_access_set(int is_w) {
5129     return &lock_era_access_set_[is_w];
5130   }
5131 
5132   // --------- dead SIDs, fresh SIDs
5133   // When running fast path w/o a lock we need to recycle SIDs to a thread-local
5134   // pool. HasRoomForDeadSids and AddDeadSid may be called w/o a lock.
5135   // FlushDeadSids should be called under a lock.
5136   // When creating a new segment on SBLOCK_ENTER, we need to get a fresh SID
5137   // from somewhere. We keep a pile of fresh ready-to-use SIDs in
5138   // a thread-local array.
5139   enum { kMaxNumDeadSids = 64,
5140          kMaxNumFreshSids = 256, };
AddDeadSidTSanThread5141   INLINE void AddDeadSid(SID sid, const char *where) {
5142     if (TS_SERIALIZED) {
5143       Segment::Unref(sid, where);
5144     } else {
5145       if (Segment::UnrefNoRecycle(sid, where) == 0) {
5146         dead_sids_.push_back(sid);
5147       }
5148     }
5149   }
5150 
FlushDeadSidsTSanThread5151   INLINE void FlushDeadSids() {
5152     if (TS_SERIALIZED) return;
5153     size_t n = dead_sids_.size();
5154     for (size_t i = 0; i < n; i++) {
5155       SID sid = dead_sids_[i];
5156       Segment::AssertLive(sid, __LINE__);
5157       DCHECK(Segment::Get(sid)->ref_count() == 0);
5158       Segment::RecycleOneSid(sid);
5159     }
5160     dead_sids_.clear();
5161   }
5162 
HasRoomForDeadSidsTSanThread5163   INLINE bool HasRoomForDeadSids() const {
5164     return TS_SERIALIZED ? false :
5165         dead_sids_.size() < kMaxNumDeadSids - 2;
5166   }
5167 
GetSomeFreshSidsTSanThread5168   void GetSomeFreshSids() {
5169     size_t cur_size = fresh_sids_.size();
5170     DCHECK(cur_size <= kMaxNumFreshSids);
5171     if (cur_size > kMaxNumFreshSids / 2) {
5172       // We already have quite a few fresh SIDs, do nothing.
5173       return;
5174     }
5175     DCHECK(fresh_sids_.capacity() >= kMaxNumFreshSids);
5176     size_t n_requested_sids = kMaxNumFreshSids - cur_size;
5177     fresh_sids_.resize(kMaxNumFreshSids);
5178     Segment::AllocateFreshSegments(n_requested_sids, &fresh_sids_[cur_size]);
5179   }
5180 
ReleaseFreshSidsTSanThread5181   void ReleaseFreshSids() {
5182     for (size_t i = 0; i < fresh_sids_.size(); i++) {
5183       Segment::RecycleOneFreshSid(fresh_sids_[i]);
5184     }
5185     fresh_sids_.clear();
5186   }
5187 
5188  private:
5189   bool is_running_;
5190   string thread_name_;
5191 
5192   TID    tid_;         // This thread's tid.
5193   SID    sid_;         // Current segment ID.
5194   TID    parent_tid_;  // Parent's tid.
5195   bool   thread_local_copy_of_g_has_expensive_flags_;
5196   uintptr_t  max_sp_;
5197   uintptr_t  min_sp_;
5198   uintptr_t  stack_size_for_ignore_;
5199   uintptr_t  fun_r_ignore_;  // > 0 if we are inside a fun_r-ed function.
5200   uintptr_t  min_sp_for_ignore_;
5201   uintptr_t  n_mops_since_start_;
5202   StackTrace *creation_context_;
5203   bool      announced_;
5204 
5205   LSID   rd_lockset_;
5206   LSID   wr_lockset_;
5207 
5208   // These bits should be read in the hottest loop, so we combine them all
5209   // together.
5210   // bit 1 -- ignore reads.
5211   // bit 2 -- ignore writes.
5212   // bit 3 -- have expensive flags
5213   int expensive_bits_;
5214   int ignore_depth_[2];
5215   StackTrace *ignore_context_[2];
5216 
5217   VTS *vts_at_exit_;
5218 
5219   CallStack *call_stack_;
5220 
5221   vector<SID> dead_sids_;
5222   vector<SID> fresh_sids_;
5223 
5224   PtrToBoolCache<251> ignore_below_cache_;
5225 
5226   LockHistory lock_history_;
5227   BitSet lock_era_access_set_[2];
5228   RecentSegmentsCache recent_segments_cache_;
5229 
5230   map<TID, ThreadCreateInfo> child_tid_to_create_info_;
5231 
5232   // This var is used to suppress race reports
5233   // when handling atomic memory accesses.
5234   // That is, an atomic memory access can't race with other accesses,
5235   // however plain memory accesses can race with atomic memory accesses.
5236   int inside_atomic_op_;
5237 
5238   prng_t rand_state_;
5239 
5240   struct Signaller {
5241     VTS *vts;
5242   };
5243 
5244   class SignallerMap: public unordered_map<uintptr_t, Signaller> {
5245     public:
ClearAndDeleteElements()5246      void ClearAndDeleteElements() {
5247        for (iterator it = begin(); it != end(); ++it) {
5248          VTS::Unref(it->second.vts);
5249        }
5250        clear();
5251      }
5252   };
5253 
5254   // All threads. The main thread has tid 0.
5255   static TSanThread **all_threads_;
5256   static int      n_threads_;
5257 
5258   // signaller address -> VTS
5259   static SignallerMap *signaller_map_;
5260   static CyclicBarrierMap *cyclic_barrier_map_;
5261 };
5262 
raw_tid(TSanThread * t)5263 INLINE static int32_t raw_tid(TSanThread *t) {
5264   return t->tid().raw();
5265 }
5266 
5267 // TSanThread:: static members
5268 TSanThread                    **TSanThread::all_threads_;
5269 int                         TSanThread::n_threads_;
5270 TSanThread::SignallerMap       *TSanThread::signaller_map_;
5271 TSanThread::CyclicBarrierMap   *TSanThread::cyclic_barrier_map_;
5272 
5273 
5274 // -------- TsanAtomicCore ------------------ {{{1
5275 
5276 // Responsible for handling of atomic memory accesses.
5277 class TsanAtomicCore {
5278  public:
5279   TsanAtomicCore();
5280 
5281   void HandleWrite(TSanThread* thr,
5282                    uintptr_t a,
5283                    uint64_t v,
5284                    uint64_t prev,
5285                    bool is_acquire,
5286                    bool is_release,
5287                    bool is_rmw);
5288 
5289   uint64_t HandleRead(TSanThread* thr,
5290                       uintptr_t a,
5291                       uint64_t v,
5292                       bool is_acquire);
5293 
5294   void ClearMemoryState(uintptr_t a, uintptr_t b);
5295 
5296  private:
5297   // Represents one value in modification history
5298   // of an atomic variable.
5299   struct AtomicHistoryEntry {
5300     // Actual value.
5301     // (atomics of size more than uint64_t are not supported as of now)
5302     uint64_t val;
5303     // ID of a thread that did the modification.
5304     TID tid;
5305     // The thread's clock during the modification.
5306     int32_t clk;
5307     // Vector clock that is acquired by a thread
5308     // that loads the value.
5309     // Similar to Signaller::vts.
5310     VTS* vts;
5311   };
5312 
5313   // Descriptor of an atomic variable.
5314   struct Atomic {
5315     // Number of stored entries in the modification order of the variable.
5316     // This represents space-modelling preciseness trade-off.
5317     // 4 values should be generally enough.
5318     static int32_t const kHistSize = 4;
5319     // Current position in the modification order.
5320     int32_t hist_pos;
5321     // Modification history organized as a circular buffer.
5322     // That is, old values are discarded.
5323     AtomicHistoryEntry hist [kHistSize];
5324     // It's basically a tid->hist_pos map that tracks what threads
5325     // had seen what values. It's required to meet the following requirement:
5326     // even relaxed loads must not be reordered in a single thread.
5327     VectorClock last_seen;
5328 
5329     Atomic();
5330     void reset(bool init = false);
5331   };
5332 
5333   typedef map<uintptr_t, Atomic> AtomicMap;
5334   AtomicMap atomic_map_;
5335 
5336   void AtomicFixHist(Atomic* atomic,
5337                      uint64_t prev);
5338 
5339   TsanAtomicCore(TsanAtomicCore const&);
5340   void operator=(TsanAtomicCore const&);
5341 };
5342 
5343 
5344 static TsanAtomicCore* g_atomicCore;
5345 
5346 
5347 // -------- Clear Memory State ------------------ {{{1
UnrefSegmentsInMemoryRange(uintptr_t a,uintptr_t b,Mask mask,CacheLine * line)5348 static void INLINE UnrefSegmentsInMemoryRange(uintptr_t a, uintptr_t b,
5349                                                 Mask mask, CacheLine *line) {
5350   while (!mask.Empty()) {
5351     uintptr_t x = mask.GetSomeSetBit();
5352     DCHECK(mask.Get(x));
5353     mask.Clear(x);
5354     line->GetValuePointer(x)->Unref("Detector::UnrefSegmentsInMemoryRange");
5355   }
5356 }
5357 
ClearMemoryStateInOneLine(TSanThread * thr,uintptr_t addr,uintptr_t beg,uintptr_t end)5358 void INLINE ClearMemoryStateInOneLine(TSanThread *thr, uintptr_t addr,
5359                                       uintptr_t beg, uintptr_t end) {
5360   AssertTILHeld();
5361   CacheLine *line = G_cache->GetLineIfExists(thr, addr, __LINE__);
5362   // CacheLine *line = G_cache->GetLineOrCreateNew(addr, __LINE__);
5363   if (line) {
5364     DCHECK(beg < CacheLine::kLineSize);
5365     DCHECK(end <= CacheLine::kLineSize);
5366     DCHECK(beg < end);
5367     Mask published = line->published();
5368     if (UNLIKELY(!published.Empty())) {
5369       Mask mask(published.GetRange(beg, end));
5370       ClearPublishedAttribute(line, mask);
5371     }
5372     Mask old_used = line->ClearRangeAndReturnOldUsed(beg, end);
5373     UnrefSegmentsInMemoryRange(beg, end, old_used, line);
5374     G_cache->ReleaseLine(thr, addr, line, __LINE__);
5375   }
5376 }
5377 
5378 // clear memory state for [a,b)
ClearMemoryState(TSanThread * thr,uintptr_t a,uintptr_t b)5379 void NOINLINE ClearMemoryState(TSanThread *thr, uintptr_t a, uintptr_t b) {
5380   if (a == b) return;
5381   CHECK(a < b);
5382   uintptr_t line1_tag = 0, line2_tag = 0;
5383   uintptr_t single_line_tag = GetCacheLinesForRange(a, b,
5384                                                     &line1_tag, &line2_tag);
5385   if (single_line_tag) {
5386     ClearMemoryStateInOneLine(thr, a, a - single_line_tag,
5387                               b - single_line_tag);
5388     return;
5389   }
5390 
5391   uintptr_t a_tag = CacheLine::ComputeTag(a);
5392   ClearMemoryStateInOneLine(thr, a, a - a_tag, CacheLine::kLineSize);
5393 
5394   for (uintptr_t tag_i = line1_tag; tag_i < line2_tag;
5395        tag_i += CacheLine::kLineSize) {
5396     ClearMemoryStateInOneLine(thr, tag_i, 0, CacheLine::kLineSize);
5397   }
5398 
5399   if (b > line2_tag) {
5400     ClearMemoryStateInOneLine(thr, line2_tag, 0, b - line2_tag);
5401   }
5402 
5403   if (DEBUG_MODE && G_flags->debug_level >= 2) {
5404     // Check that we've cleared it. Slow!
5405     for (uintptr_t x = a; x < b; x++) {
5406       uintptr_t off = CacheLine::ComputeOffset(x);
5407       (void)off;
5408       CacheLine *line = G_cache->GetLineOrCreateNew(thr, x, __LINE__);
5409       CHECK(!line->has_shadow_value().Get(off));
5410       G_cache->ReleaseLine(thr, x, line, __LINE__);
5411     }
5412   }
5413 
5414   g_atomicCore->ClearMemoryState(a, b);
5415 }
5416 
5417 // -------- PCQ --------------------- {{{1
5418 struct PCQ {
5419   uintptr_t pcq_addr;
5420   deque<VTS*> putters;
5421 };
5422 
5423 typedef map<uintptr_t, PCQ> PCQMap;
5424 static PCQMap *g_pcq_map;
5425 
5426 // -------- Heap info ---------------------- {{{1
5427 #include "ts_heap_info.h"
5428 // Information about heap memory.
5429 
5430 struct HeapInfo {
5431   uintptr_t   ptr;
5432   uintptr_t   size;
5433   SID         sid;
HeapInfoHeapInfo5434   HeapInfo() : ptr(0), size(0), sid(0) { }
5435 
segHeapInfo5436   Segment *seg() { return Segment::Get(sid); }
tidHeapInfo5437   TID tid() { return seg()->tid(); }
StackTraceStringHeapInfo5438   string StackTraceString() { return Segment::StackTraceString(sid); }
5439 };
5440 
5441 static HeapMap<HeapInfo> *G_heap_map;
5442 
5443 struct ThreadStackInfo {
5444   uintptr_t   ptr;
5445   uintptr_t   size;
ThreadStackInfoThreadStackInfo5446   ThreadStackInfo() : ptr(0), size(0) { }
5447 };
5448 
5449 static HeapMap<ThreadStackInfo> *G_thread_stack_map;
5450 
5451 // -------- Forget all state -------- {{{1
5452 // We need to forget all state and start over because we've
5453 // run out of some resources (most likely, segment IDs).
ForgetAllStateAndStartOver(TSanThread * thr,const char * reason)5454 static void ForgetAllStateAndStartOver(TSanThread *thr, const char *reason) {
5455   // This is done under the main lock.
5456   AssertTILHeld();
5457   size_t start_time = g_last_flush_time = TimeInMilliSeconds();
5458   Report("T%d INFO: %s. Flushing state.\n", raw_tid(thr), reason);
5459 
5460   if (TS_SERIALIZED == 0) {
5461     // We own the lock, but we also must acquire all cache lines
5462     // so that the fast-path (unlocked) code does not execute while
5463     // we are flushing.
5464     G_cache->AcquireAllLines(thr);
5465   }
5466 
5467 
5468   if (0) {
5469     Report("INFO: Thread Sanitizer will now forget all history.\n");
5470     Report("INFO: This is experimental, and may fail!\n");
5471     if (G_flags->keep_history > 0) {
5472       Report("INFO: Consider re-running with --keep_history=0\n");
5473     }
5474     if (G_flags->show_stats) {
5475         G_stats->PrintStats();
5476     }
5477   }
5478 
5479   G_stats->n_forgets++;
5480 
5481   Segment::ForgetAllState();
5482   SegmentSet::ForgetAllState();
5483   TSanThread::ForgetAllState();
5484   VTS::FlushHBCache();
5485 
5486   G_heap_map->Clear();
5487 
5488   g_publish_info_map->clear();
5489 
5490   for (PCQMap::iterator it = g_pcq_map->begin(); it != g_pcq_map->end(); ++it) {
5491     PCQ &pcq = it->second;
5492     for (deque<VTS*>::iterator it2 = pcq.putters.begin();
5493          it2 != pcq.putters.end(); ++it2) {
5494       VTS::Unref(*it2);
5495       *it2 = VTS::CreateSingleton(TID(0), 1);
5496     }
5497   }
5498 
5499   // Must be the last one to flush as it effectively releases the
5500   // cach lines and enables fast path code to run in other threads.
5501   G_cache->ForgetAllState(thr);
5502 
5503   size_t stop_time = TimeInMilliSeconds();
5504   if (DEBUG_MODE || (stop_time - start_time > 0)) {
5505     Report("T%d INFO: Flush took %ld ms\n", raw_tid(thr),
5506            stop_time - start_time);
5507   }
5508 }
5509 
FlushStateIfOutOfSegments(TSanThread * thr)5510 static INLINE void FlushStateIfOutOfSegments(TSanThread *thr) {
5511   if (Segment::NumberOfSegments() > kMaxSIDBeforeFlush) {
5512     // too few sids left -- flush state.
5513     if (DEBUG_MODE) {
5514       G_cache->PrintStorageStats();
5515       Segment::ShowSegmentStats();
5516     }
5517     ForgetAllStateAndStartOver(thr, "run out of segment IDs");
5518   }
5519 }
5520 
5521 // -------- Expected Race ---------------------- {{{1
5522 typedef  HeapMap<ExpectedRace> ExpectedRacesMap;
5523 static ExpectedRacesMap *G_expected_races_map;
5524 static bool g_expecting_races;
5525 static int g_found_races_since_EXPECT_RACE_BEGIN;
5526 
ThreadSanitizerFindExpectedRace(uintptr_t addr)5527 ExpectedRace* ThreadSanitizerFindExpectedRace(uintptr_t addr) {
5528   return G_expected_races_map->GetInfo(addr);
5529 }
5530 
5531 // -------- Suppressions ----------------------- {{{1
5532 static const char default_suppressions[] =
5533 // TODO(kcc): as it gets bigger, move it into a separate object file.
5534 "# We need to have some default suppressions, but we don't want to    \n"
5535 "# keep them in a separate text file, so we keep the in the code.     \n"
5536 
5537 #ifdef VGO_darwin
5538 "{                                                                    \n"
5539 "   dyld tries to unlock an invalid mutex when adding/removing image. \n"
5540 "   ThreadSanitizer:InvalidLock                                       \n"
5541 "   fun:pthread_mutex_unlock                                          \n"
5542 "   fun:_dyld_register_func_for_*_image                               \n"
5543 "}                                                                    \n"
5544 
5545 "{                                                                      \n"
5546 "  Benign reports in __NSOperationInternal when using workqueue threads \n"
5547 "  ThreadSanitizer:Race                                                 \n"
5548 "  fun:__+[__NSOperationInternal _observeValueForKeyPath:ofObject:changeKind:oldValue:newValue:indexes:context:]_block_invoke_*\n"
5549 "  fun:_dispatch_call_block_and_release                                 \n"
5550 "}                                                                      \n"
5551 
5552 "{                                                                    \n"
5553 "  Benign race in GCD when using workqueue threads.                   \n"
5554 "  ThreadSanitizer:Race                                               \n"
5555 "  fun:____startOperations_block_invoke_*                             \n"
5556 "  ...                                                                \n"
5557 "  fun:_dispatch_call_block_and_release                               \n"
5558 "}                                                                    \n"
5559 
5560 "{                                                                    \n"
5561 "  Benign race in NSOQSchedule when using workqueue threads.          \n"
5562 "  ThreadSanitizer:Race                                               \n"
5563 "  fun:__doStart*                                                     \n"
5564 "  ...                                                                \n"
5565 "  fun:_dispatch_call_block_and_release                               \n"
5566 "}                                                                    \n"
5567 
5568 
5569 #endif
5570 
5571 #ifndef _MSC_VER
5572 "{                                                                   \n"
5573 "  False reports on std::string internals. See TSan issue #40.       \n"
5574 "  ThreadSanitizer:Race                                              \n"
5575 "  ...                                                               \n"
5576 "  fun:*~basic_string*                                               \n"
5577 "}                                                                   \n"
5578 
5579 "{                                                                   \n"
5580 "  False reports on std::string internals. See TSan issue #40.       \n"
5581 "  ThreadSanitizer:Race                                              \n"
5582 "  ...                                                               \n"
5583 "  fun:*basic_string*_M_destroy                                      \n"
5584 "}                                                                   \n"
5585 
5586 #else
5587 "{                                                                   \n"
5588 "  False lock report inside ntdll.dll                                \n"
5589 "  ThreadSanitizer:InvalidLock                                       \n"
5590 "  fun:*                                                             \n"
5591 "  obj:*ntdll.dll                                                    \n"
5592 "}                                                                   \n"
5593 
5594 "{                                                                   \n"
5595 "  False report due to lack of debug symbols in ntdll.dll  (a)       \n"
5596 "  ThreadSanitizer:InvalidLock                                       \n"
5597 "  fun:*SRWLock*                                                     \n"
5598 "}                                                                   \n"
5599 
5600 "{                                                                   \n"
5601 "  False report due to lack of debug symbols in ntdll.dll  (b)       \n"
5602 "  ThreadSanitizer:UnlockForeign                                     \n"
5603 "  fun:*SRWLock*                                                     \n"
5604 "}                                                                   \n"
5605 
5606 "{                                                                   \n"
5607 "  False report due to lack of debug symbols in ntdll.dll  (c)       \n"
5608 "  ThreadSanitizer:UnlockNonLocked                                   \n"
5609 "  fun:*SRWLock*                                                     \n"
5610 "}                                                                   \n"
5611 
5612 "{                                                                   \n"
5613 "  False reports on std::string internals (2). See TSan issue #40.   \n"
5614 "  ThreadSanitizer:Race                                              \n"
5615 "  ...                                                               \n"
5616 "  fun:*basic_string*scalar deleting destructor*                     \n"
5617 "}                                                                   \n"
5618 #endif
5619 
5620 #ifdef TS_PIN
5621 "{                                                                   \n"
5622 "  Suppression for issue 54 (PIN lacks support for IFUNC)            \n"
5623 "  ThreadSanitizer:Race                                              \n"
5624 "  ...                                                               \n"
5625 "  fun:*NegativeTests_Strlen::Worker*                                \n"
5626 "}                                                                   \n"
5627 #endif
5628 
5629 ;
5630 
5631 // -------- Report Storage --------------------- {{{1
5632 class ReportStorage {
5633  public:
5634 
ReportStorage()5635   ReportStorage()
5636    : n_reports(0),
5637      n_race_reports(0),
5638      program_finished_(0),
5639      unwind_cb_(0) {
5640     if (G_flags->generate_suppressions) {
5641       Report("INFO: generate_suppressions = true\n");
5642     }
5643     // Read default suppressions
5644     int n = suppressions_.ReadFromString(default_suppressions);
5645     if (n == -1) {
5646       Report("Error reading default suppressions at line %d: %s\n",
5647           suppressions_.GetErrorLineNo(),
5648           suppressions_.GetErrorString().c_str());
5649       exit(1);
5650     }
5651 
5652     // Read user-supplied suppressions.
5653     for (size_t i = 0; i < G_flags->suppressions.size(); i++) {
5654       const string &supp_path = G_flags->suppressions[i];
5655       Report("INFO: reading suppressions file %s\n", supp_path.c_str());
5656       int n = suppressions_.ReadFromString(ReadFileToString(supp_path, true));
5657       if (n == -1) {
5658         Report("Error at line %d: %s\n",
5659             suppressions_.GetErrorLineNo(),
5660             suppressions_.GetErrorString().c_str());
5661         exit(1);
5662       }
5663       Report("INFO: %6d suppression(s) read from file %s\n",
5664              n, supp_path.c_str());
5665     }
5666   }
5667 
AddReport(TSanThread * thr,uintptr_t pc,bool is_w,uintptr_t addr,int size,ShadowValue old_sval,ShadowValue new_sval,bool is_published)5668   bool NOINLINE AddReport(TSanThread *thr, uintptr_t pc, bool is_w, uintptr_t addr,
5669                           int size,
5670                           ShadowValue old_sval, ShadowValue new_sval,
5671                           bool is_published) {
5672     {
5673       // Check this isn't a "_ZNSs4_Rep20_S_empty_rep_storageE" report.
5674       uintptr_t offset;
5675       string symbol_descr;
5676       if (GetNameAndOffsetOfGlobalObject(addr, &symbol_descr, &offset)) {
5677         if (StringMatch("*empty_rep_storage*", symbol_descr))
5678           return false;
5679         if (StringMatch("_IO_stdfile_*_lock", symbol_descr))
5680           return false;
5681         if (StringMatch("_IO_*_stdout_", symbol_descr))
5682           return false;
5683         if (StringMatch("_IO_*_stderr_", symbol_descr))
5684           return false;
5685       }
5686     }
5687 
5688     bool is_expected = false;
5689     ExpectedRace *expected_race = G_expected_races_map->GetInfo(addr);
5690     if (debug_expected_races) {
5691       Printf("Checking expected race for %lx; exp_race=%p\n",
5692              addr, expected_race);
5693       if (expected_race) {
5694         Printf("  FOUND\n");
5695       }
5696     }
5697 
5698     if (expected_race) {
5699       if (G_flags->nacl_untrusted != expected_race->is_nacl_untrusted) {
5700         Report("WARNING: this race is only expected in NaCl %strusted mode\n",
5701             expected_race->is_nacl_untrusted ? "un" : "");
5702       } else {
5703         is_expected = true;
5704         expected_race->count++;
5705       }
5706     }
5707 
5708     if (g_expecting_races) {
5709       is_expected = true;
5710       g_found_races_since_EXPECT_RACE_BEGIN++;
5711     }
5712 
5713     if (is_expected && !G_flags->show_expected_races) return false;
5714 
5715     StackTrace *stack_trace = thr->CreateStackTrace(pc);
5716     if (unwind_cb_) {
5717       int const maxcnt = 256;
5718       uintptr_t cur_stack [maxcnt];
5719       int cnt = unwind_cb_(cur_stack, maxcnt, pc);
5720       if (cnt > 0 && cnt <= maxcnt) {
5721         cnt = min<int>(cnt, stack_trace->capacity());
5722         stack_trace->set_size(cnt);
5723         for (int i = 0; i < cnt; i++)
5724           stack_trace->Set(i, cur_stack[i]);
5725       }
5726     }
5727     int n_reports_for_this_context = reported_stacks_[stack_trace]++;
5728 
5729     if (n_reports_for_this_context > 0) {
5730       // we already reported a race here.
5731       StackTrace::Delete(stack_trace);
5732       return false;
5733     }
5734 
5735 
5736     ThreadSanitizerDataRaceReport *race_report =
5737         new ThreadSanitizerDataRaceReport;
5738 
5739     race_report->type = ThreadSanitizerReport::DATA_RACE;
5740     race_report->new_sval = new_sval;
5741     race_report->old_sval = old_sval;
5742     race_report->is_expected = is_expected;
5743     race_report->last_access_is_w = is_w;
5744     race_report->racey_addr = addr;
5745     race_report->racey_addr_description = DescribeMemory(addr);
5746     race_report->last_access_tid = thr->tid();
5747     race_report->last_access_sid = thr->sid();
5748     race_report->last_access_size = size;
5749     race_report->stack_trace = stack_trace;
5750     race_report->racey_addr_was_published = is_published;
5751     race_report->last_acces_lsid[false] = thr->lsid(false);
5752     race_report->last_acces_lsid[true] = thr->lsid(true);
5753 
5754     Segment *seg = Segment::Get(thr->sid());
5755     (void)seg;
5756     CHECK(thr->lsid(false) == seg->lsid(false));
5757     CHECK(thr->lsid(true) == seg->lsid(true));
5758 
5759     return ThreadSanitizerPrintReport(race_report);
5760   }
5761 
AnnounceThreadsInSegmentSet(SSID ssid)5762   void AnnounceThreadsInSegmentSet(SSID ssid) {
5763     if (ssid.IsEmpty()) return;
5764     for (int s = 0; s < SegmentSet::Size(ssid); s++) {
5765       Segment *seg = SegmentSet::GetSegmentForNonSingleton(ssid, s, __LINE__);
5766       TSanThread::Get(seg->tid())->Announce();
5767     }
5768   }
5769 
5770 
5771 
PrintConcurrentSegmentSet(SSID ssid,TID tid,SID sid,LSID lsid,bool is_w,const char * descr,set<LID> * locks,set<SID> * concurrent_sids)5772   void PrintConcurrentSegmentSet(SSID ssid, TID tid, SID sid,
5773                                  LSID lsid, bool is_w,
5774                                  const char *descr, set<LID> *locks,
5775                                  set<SID>* concurrent_sids) {
5776     if (ssid.IsEmpty()) return;
5777     bool printed_header = false;
5778     TSanThread *thr1 = TSanThread::Get(tid);
5779     for (int s = 0; s < SegmentSet::Size(ssid); s++) {
5780       SID concurrent_sid = SegmentSet::GetSID(ssid, s, __LINE__);
5781       Segment *seg = Segment::Get(concurrent_sid);
5782       if (Segment::HappensBeforeOrSameThread(concurrent_sid, sid)) continue;
5783       if (!LockSet::IntersectionIsEmpty(lsid, seg->lsid(is_w))) continue;
5784       if (concurrent_sids) {
5785         concurrent_sids->insert(concurrent_sid);
5786       }
5787       TSanThread *thr2 = TSanThread::Get(seg->tid());
5788       if (!printed_header) {
5789         Report("  %sConcurrent %s happened at (OR AFTER) these points:%s\n",
5790                c_magenta, descr, c_default);
5791         printed_header = true;
5792       }
5793 
5794       Report("   %s (%s):\n",
5795              thr2->ThreadName().c_str(),
5796              TwoLockSetsToString(seg->lsid(false),
5797                                  seg->lsid(true)).c_str());
5798       if (G_flags->show_states) {
5799         Report("   S%d\n", concurrent_sid.raw());
5800       }
5801       LockSet::AddLocksToSet(seg->lsid(false), locks);
5802       LockSet::AddLocksToSet(seg->lsid(true), locks);
5803       Report("%s", Segment::StackTraceString(concurrent_sid).c_str());
5804       if (!G_flags->pure_happens_before &&
5805           G_flags->suggest_happens_before_arcs) {
5806         set<LID> message_locks;
5807         // Report("Locks in T%d\n", thr1->tid().raw());
5808         // thr1->lock_history().PrintLocks();
5809         // Report("Unlocks in T%d\n", thr2->tid().raw());
5810         // thr2->lock_history().PrintUnlocks();
5811         if (LockHistory::Intersect(thr1->lock_history(), thr2->lock_history(),
5812                                    seg->lock_era(), &message_locks)) {
5813           Report("   Note: these locks were recently released by T%d"
5814                  " and later acquired by T%d: {%s}\n"
5815                  "   See http://code.google.com/p/data-race-test/wiki/"
5816                  "PureHappensBeforeVsHybrid\n",
5817                  thr2->tid().raw(),
5818                  thr1->tid().raw(),
5819                  SetOfLocksToString(message_locks).c_str());
5820           locks->insert(message_locks.begin(), message_locks.end());
5821         }
5822       }
5823     }
5824   }
5825 
SetProgramFinished()5826   void SetProgramFinished() {
5827     CHECK(!program_finished_);
5828     program_finished_ = true;
5829   }
5830 
RaceInfoString(uintptr_t pc,set<SID> & concurrent_sids)5831   string RaceInfoString(uintptr_t pc, set<SID>& concurrent_sids) {
5832     string s;
5833     char buf[100];
5834     snprintf(buf, 100, "Race verifier data: %p", (void*)pc);
5835     s += buf;
5836     for (set<SID>::iterator it = concurrent_sids.begin();
5837          it != concurrent_sids.end(); ++it) {
5838       // Take the first pc of the concurrent stack trace.
5839       uintptr_t concurrent_pc = *Segment::embedded_stack_trace(*it);
5840       snprintf(buf, 100, ",%p", (void*)concurrent_pc);
5841       s += buf;
5842     }
5843     s += "\n";
5844     return s;
5845   }
5846 
PrintRaceReport(ThreadSanitizerDataRaceReport * race)5847   void PrintRaceReport(ThreadSanitizerDataRaceReport *race) {
5848     bool short_report = program_finished_;
5849     if (!short_report) {
5850       AnnounceThreadsInSegmentSet(race->new_sval.rd_ssid());
5851       AnnounceThreadsInSegmentSet(race->new_sval.wr_ssid());
5852     }
5853     bool is_w = race->last_access_is_w;
5854     TID     tid = race->last_access_tid;
5855     TSanThread *thr = TSanThread::Get(tid);
5856     SID     sid = race->last_access_sid;
5857     LSID    lsid = race->last_acces_lsid[is_w];
5858     set<LID> all_locks;
5859 
5860     n_race_reports++;
5861     if (G_flags->html) {
5862       Report("<b id=race%d>Race report #%d; </b>"
5863              "<a href=\"#race%d\">Next;</a>  "
5864              "<a href=\"#race%d\">Prev;</a>\n",
5865              n_race_reports, n_race_reports,
5866              n_race_reports+1, n_race_reports-1);
5867     }
5868 
5869 
5870     // Note the {{{ and }}}. These are for vim folds.
5871     Report("%sWARNING: %s data race during %s of size %d at %p: {{{%s\n",
5872            c_red,
5873            race->is_expected ? "Expected" : "Possible",
5874            is_w ? "write" : "read",
5875            race->last_access_size,
5876            race->racey_addr,
5877            c_default);
5878     if (!short_report) {
5879       LockSet::AddLocksToSet(race->last_acces_lsid[false], &all_locks);
5880       LockSet::AddLocksToSet(race->last_acces_lsid[true], &all_locks);
5881       Report("   %s (%s):\n",
5882              thr->ThreadName().c_str(),
5883              TwoLockSetsToString(race->last_acces_lsid[false],
5884                                  race->last_acces_lsid[true]).c_str());
5885     }
5886 
5887     CHECK(race->stack_trace);
5888     Report("%s", race->stack_trace->ToString().c_str());
5889     if (short_report) {
5890       Report(" See the full version of this report above.\n");
5891       Report("}%s\n", "}}");
5892       return;
5893     }
5894     // Report(" sid=%d; vts=%s\n", thr->sid().raw(),
5895     //       thr->vts()->ToString().c_str());
5896     if (G_flags->show_states) {
5897       Report(" old state: %s\n", race->old_sval.ToString().c_str());
5898       Report(" new state: %s\n", race->new_sval.ToString().c_str());
5899     }
5900     set<SID> concurrent_sids;
5901     if (G_flags->keep_history) {
5902       PrintConcurrentSegmentSet(race->new_sval.wr_ssid(),
5903                                 tid, sid, lsid, true, "write(s)", &all_locks,
5904                                 &concurrent_sids);
5905       if (is_w) {
5906         PrintConcurrentSegmentSet(race->new_sval.rd_ssid(),
5907                                   tid, sid, lsid, false, "read(s)", &all_locks,
5908                                   &concurrent_sids);
5909       }
5910     } else {
5911       Report("  %sAccess history is disabled. "
5912              "Consider running with --keep-history=1 for better reports.%s\n",
5913              c_cyan, c_default);
5914     }
5915 
5916     if (race->racey_addr_was_published) {
5917       Report(" This memory was published\n");
5918     }
5919     if (race->racey_addr_description.size() > 0) {
5920       Report("%s", race->racey_addr_description.c_str());
5921     }
5922     if (race->is_expected) {
5923       ExpectedRace *expected_race =
5924           G_expected_races_map->GetInfo(race->racey_addr);
5925       if (expected_race) {
5926         CHECK(expected_race->description);
5927         Report(" Description: \"%s\"\n", expected_race->description);
5928       }
5929     }
5930     set<LID>  locks_reported;
5931 
5932     if (!all_locks.empty()) {
5933       Report("  %sLocks involved in this report "
5934              "(reporting last lock sites):%s {%s}\n",
5935              c_green, c_default,
5936              SetOfLocksToString(all_locks).c_str());
5937 
5938       for (set<LID>::iterator it = all_locks.begin();
5939            it != all_locks.end(); ++it) {
5940         LID lid = *it;
5941         Lock::ReportLockWithOrWithoutContext(lid, true);
5942       }
5943     }
5944 
5945     string raceInfoString = RaceInfoString(race->stack_trace->Get(0),
5946         concurrent_sids);
5947     Report("   %s", raceInfoString.c_str());
5948     Report("}}}\n");
5949   }
5950 
PrintReport(ThreadSanitizerReport * report)5951   bool PrintReport(ThreadSanitizerReport *report) {
5952     CHECK(report);
5953     // Check if we have a suppression.
5954     vector<string> funcs_mangled;
5955     vector<string> funcs_demangled;
5956     vector<string> objects;
5957 
5958     CHECK(!g_race_verifier_active);
5959     CHECK(report->stack_trace);
5960     CHECK(report->stack_trace->size());
5961     for (size_t i = 0; i < report->stack_trace->size(); i++) {
5962       uintptr_t pc = report->stack_trace->Get(i);
5963       string img, rtn, file;
5964       int line;
5965       PcToStrings(pc, false, &img, &rtn, &file, &line);
5966       if (rtn == "(below main)" || rtn == "ThreadSanitizerStartThread")
5967         break;
5968 
5969       funcs_mangled.push_back(rtn);
5970       funcs_demangled.push_back(NormalizeFunctionName(PcToRtnName(pc, true)));
5971       objects.push_back(img);
5972 
5973       if (rtn == "main")
5974         break;
5975     }
5976     string suppression_name;
5977     if (suppressions_.StackTraceSuppressed("ThreadSanitizer",
5978                                            report->ReportName(),
5979                                            funcs_mangled,
5980                                            funcs_demangled,
5981                                            objects,
5982                                            &suppression_name)) {
5983       used_suppressions_[suppression_name]++;
5984       return false;
5985     }
5986 
5987     // Actually print it.
5988     if (report->type == ThreadSanitizerReport::UNLOCK_FOREIGN) {
5989       ThreadSanitizerBadUnlockReport *bad_unlock =
5990           reinterpret_cast<ThreadSanitizerBadUnlockReport*>(report);
5991       Report("WARNING: Lock %s was released by thread T%d"
5992              " which did not acquire this lock: {{{\n%s}}}\n",
5993              Lock::ToString(bad_unlock->lid).c_str(),
5994              bad_unlock->tid.raw(),
5995              bad_unlock->stack_trace->ToString().c_str());
5996     } else if (report->type == ThreadSanitizerReport::UNLOCK_NONLOCKED) {
5997       ThreadSanitizerBadUnlockReport *bad_unlock =
5998           reinterpret_cast<ThreadSanitizerBadUnlockReport*>(report);
5999       Report("WARNING: Unlocking a non-locked lock %s in thread T%d: "
6000              "{{{\n%s}}}\n",
6001              Lock::ToString(bad_unlock->lid).c_str(),
6002              bad_unlock->tid.raw(),
6003              bad_unlock->stack_trace->ToString().c_str());
6004     } else if (report->type == ThreadSanitizerReport::INVALID_LOCK) {
6005       ThreadSanitizerInvalidLockReport *invalid_lock =
6006           reinterpret_cast<ThreadSanitizerInvalidLockReport*>(report);
6007       Report("WARNING: accessing an invalid lock %p in thread T%d: "
6008              "{{{\n%s}}}\n",
6009              invalid_lock->lock_addr,
6010              invalid_lock->tid.raw(),
6011              invalid_lock->stack_trace->ToString().c_str());
6012     } else if (report->type == ThreadSanitizerReport::ATOMICITY_VIOLATION) {
6013       ThreadSanitizerAtomicityViolationReport *av =
6014           reinterpret_cast<ThreadSanitizerAtomicityViolationReport*>(report);
6015       Report("WARNING: Suspected atomicity violation {{{\n");
6016       av->r1->Print();
6017       av->r2->Print();
6018       av->r3->Print();
6019       Report("}}}\n");
6020 
6021     } else {
6022       CHECK(report->type == ThreadSanitizerReport::DATA_RACE);
6023       ThreadSanitizerDataRaceReport *race =
6024           reinterpret_cast<ThreadSanitizerDataRaceReport*>(report);
6025       PrintRaceReport(race);
6026     }
6027 
6028     n_reports++;
6029     SetNumberOfFoundErrors(n_reports);
6030     if (!G_flags->summary_file.empty()) {
6031       char buff[100];
6032       snprintf(buff, sizeof(buff),
6033                "ThreadSanitizer: %d warning(s) reported\n", n_reports);
6034       // We overwrite the contents of this file with the new summary.
6035       // We don't do that at the end because even if we crash later
6036       // we will already have the summary.
6037       OpenFileWriteStringAndClose(G_flags->summary_file, buff);
6038     }
6039 
6040     // Generate a suppression.
6041     if (G_flags->generate_suppressions) {
6042       string supp = "{\n";
6043       supp += "  <Put your suppression name here>\n";
6044       supp += string("  ThreadSanitizer:") + report->ReportName() + "\n";
6045       for (size_t i = 0; i < funcs_mangled.size(); i++) {
6046         const string &func = funcs_demangled[i];
6047         if (func.size() == 0 || func == "(no symbols") {
6048           supp += "  obj:" + objects[i] + "\n";
6049         } else {
6050           supp += "  fun:" + funcs_demangled[i] + "\n";
6051         }
6052         if (StackTrace::CutStackBelowFunc(funcs_demangled[i])) {
6053           break;
6054         }
6055       }
6056       supp += "}";
6057       Printf("------- suppression -------\n%s\n------- end suppression -------\n",
6058              supp.c_str());
6059     }
6060 
6061     return true;
6062   }
6063 
PrintUsedSuppression()6064   void PrintUsedSuppression() {
6065     for (map<string, int>::iterator it = used_suppressions_.begin();
6066          it != used_suppressions_.end(); ++it) {
6067       Report("used_suppression: %d %s\n", it->second, it->first.c_str());
6068     }
6069   }
6070 
PrintSummary()6071   void PrintSummary() {
6072     Report("ThreadSanitizer summary: reported %d warning(s) (%d race(s))\n",
6073            n_reports, n_race_reports);
6074   }
6075 
6076 
DescribeMemory(uintptr_t a)6077   string DescribeMemory(uintptr_t a) {
6078     const int kBufLen = 1023;
6079     char buff[kBufLen+1];
6080 
6081     // Is this stack?
6082     for (int i = 0; i < TSanThread::NumberOfThreads(); i++) {
6083       TSanThread *t = TSanThread::Get(TID(i));
6084       if (!t || !t->is_running()) continue;
6085       if (t->MemoryIsInStack(a)) {
6086         snprintf(buff, sizeof(buff),
6087                  "  %sLocation %p is %ld bytes inside T%d's stack [%p,%p]%s\n",
6088                  c_blue,
6089                  reinterpret_cast<void*>(a),
6090                  static_cast<long>(t->max_sp() - a),
6091                  i,
6092                  reinterpret_cast<void*>(t->min_sp()),
6093                  reinterpret_cast<void*>(t->max_sp()),
6094                  c_default
6095                 );
6096         return buff;
6097       }
6098     }
6099 
6100     HeapInfo *heap_info = G_heap_map->GetInfo(a);
6101     if (heap_info) {
6102       snprintf(buff, sizeof(buff),
6103              "  %sLocation %p is %ld bytes inside a block starting at %p"
6104              " of size %ld allocated by T%d from heap:%s\n",
6105              c_blue,
6106              reinterpret_cast<void*>(a),
6107              static_cast<long>(a - heap_info->ptr),
6108              reinterpret_cast<void*>(heap_info->ptr),
6109              static_cast<long>(heap_info->size),
6110              heap_info->tid().raw(), c_default);
6111       return string(buff) + heap_info->StackTraceString().c_str();
6112     }
6113 
6114 
6115     // Is it a global object?
6116     uintptr_t offset;
6117     string symbol_descr;
6118     if (GetNameAndOffsetOfGlobalObject(a, &symbol_descr, &offset)) {
6119       snprintf(buff, sizeof(buff),
6120               "  %sAddress %p is %d bytes inside data symbol \"",
6121               c_blue, reinterpret_cast<void*>(a), static_cast<int>(offset));
6122       return buff + symbol_descr + "\"" + c_default + "\n";
6123     }
6124 
6125     if (G_flags->debug_level >= 2) {
6126       string res;
6127       // Is this near stack?
6128       for (int i = 0; i < TSanThread::NumberOfThreads(); i++) {
6129         TSanThread *t = TSanThread::Get(TID(i));
6130         const uintptr_t kMaxStackDiff = 1024 * 16;
6131         uintptr_t diff1 = a - t->max_sp();
6132         uintptr_t diff2 = t->min_sp() - a;
6133         if (diff1 < kMaxStackDiff ||
6134             diff2 < kMaxStackDiff ||
6135             t->MemoryIsInStack(a)) {
6136           uintptr_t diff = t->MemoryIsInStack(a) ? 0 :
6137               (diff1 < kMaxStackDiff ? diff1 : diff2);
6138           snprintf(buff, sizeof(buff),
6139                    "  %sLocation %p is within %d bytes outside T%d's stack [%p,%p]%s\n",
6140                    c_blue,
6141                    reinterpret_cast<void*>(a),
6142                    static_cast<int>(diff),
6143                    i,
6144                    reinterpret_cast<void*>(t->min_sp()),
6145                    reinterpret_cast<void*>(t->max_sp()),
6146                    c_default
6147                   );
6148           res += buff;
6149         }
6150       }
6151       if (res.size() > 0) {
6152         return res +
6153             "  This report _may_ indicate that valgrind incorrectly "
6154             "computed the stack boundaries\n";
6155       }
6156     }
6157 
6158     return "";
6159   }
6160 
SetUnwindCallback(ThreadSanitizerUnwindCallback cb)6161   void SetUnwindCallback(ThreadSanitizerUnwindCallback cb) {
6162     unwind_cb_ = cb;
6163   }
6164 
6165  private:
6166   map<StackTrace *, int, StackTrace::Less> reported_stacks_;
6167   int n_reports;
6168   int n_race_reports;
6169   bool program_finished_;
6170   Suppressions suppressions_;
6171   map<string, int> used_suppressions_;
6172   ThreadSanitizerUnwindCallback unwind_cb_;
6173 };
6174 
6175 // -------- Event Sampling ---------------- {{{1
6176 // This class samples (profiles) events.
6177 // Instances of this class should all be static.
6178 class EventSampler {
6179  public:
6180 
6181   // Sample one event
Sample(TSanThread * thr,const char * event_name,bool need_locking)6182   void Sample(TSanThread *thr, const char *event_name, bool need_locking) {
6183     CHECK_NE(G_flags->sample_events, 0);
6184     (counter_)++;
6185     if ((counter_ & ((1 << G_flags->sample_events) - 1)) != 0)
6186       return;
6187 
6188     TIL til(ts_lock, 8, need_locking);
6189     string pos = thr->CallStackToStringRtnOnly(G_flags->sample_events_depth);
6190     (*samples_)[event_name][pos]++;
6191     total_samples_++;
6192     if (total_samples_ >= print_after_this_number_of_samples_) {
6193       print_after_this_number_of_samples_ +=
6194           print_after_this_number_of_samples_ / 2;
6195       ShowSamples();
6196     }
6197   }
6198 
6199   // Show existing samples
ShowSamples()6200   static void ShowSamples() {
6201     if (G_flags->sample_events == 0) return;
6202     Printf("ShowSamples: (all samples: %lld)\n", total_samples_);
6203     for (SampleMapMap::iterator it1 = samples_->begin();
6204          it1 != samples_->end(); ++it1) {
6205       string name = it1->first;
6206       SampleMap &m = it1->second;
6207       int total = 0;
6208       for (SampleMap::iterator it2 = m.begin(); it2 != m.end(); it2++) {
6209         total += it2->second;
6210       }
6211 
6212       map<int, string> reverted_map;
6213       for (SampleMap::iterator it2 = m.begin(); it2 != m.end(); it2++) {
6214         int n_samples = it2->second;
6215         if (n_samples * 1000 < total) continue;
6216         reverted_map[n_samples] = it2->first;
6217       }
6218       Printf("%s: total samples %'d (~%'lld events)\n", name.c_str(),
6219              total,
6220              (int64_t)total << G_flags->sample_events);
6221       for (map<int, string>::iterator it = reverted_map.begin();
6222            it != reverted_map.end(); ++it) {
6223         Printf("%s: %d samples (~%d%%) %s\n", name.c_str(), it->first,
6224                (it->first * 100) / total, it->second.c_str());
6225       }
6226       Printf("\n");
6227     }
6228   }
6229 
InitClassMembers()6230   static void InitClassMembers() {
6231     samples_ = new SampleMapMap;
6232     total_samples_ = 0;
6233     print_after_this_number_of_samples_ = 1000;
6234   }
6235 
6236  private:
6237   int counter_;
6238 
6239   typedef map<string, int> SampleMap;
6240   typedef map<string, SampleMap> SampleMapMap;
6241   static SampleMapMap *samples_;
6242   static int64_t total_samples_;
6243   static int64_t print_after_this_number_of_samples_;
6244 };
6245 
6246 EventSampler::SampleMapMap *EventSampler::samples_;
6247 int64_t EventSampler::total_samples_;
6248 int64_t EventSampler::print_after_this_number_of_samples_;
6249 
6250 // -------- Detector ---------------------- {{{1
6251 // Collection of event handlers.
6252 class Detector {
6253  public:
HandleTraceLoop(TSanThread * thr,uintptr_t pc,MopInfo * mops,uintptr_t * tleb,size_t n,int expensive_bits,bool need_locking)6254   void INLINE HandleTraceLoop(TSanThread *thr, uintptr_t pc,
6255                               MopInfo *mops,
6256                               uintptr_t *tleb, size_t n,
6257                               int expensive_bits, bool need_locking) {
6258     bool has_expensive_flags = (expensive_bits & 4) != 0;
6259     size_t i = 0;
6260     uintptr_t sblock_pc = pc;
6261     size_t n_locks = 0;
6262     do {
6263       uintptr_t addr = tleb[i];
6264       if (addr == 0) continue;  // This mop was not executed.
6265       MopInfo *mop = &mops[i];
6266       tleb[i] = 0;  // we've consumed this mop, clear it.
6267       DCHECK(mop->size() != 0);
6268       DCHECK(mop->pc() != 0);
6269       if ((expensive_bits & 1) && mop->is_write() == false) continue;
6270       if ((expensive_bits & 2) && mop->is_write() == true) continue;
6271       n_locks += HandleMemoryAccessInternal(thr, &sblock_pc, addr, mop,
6272                                  has_expensive_flags,
6273                                  need_locking);
6274     } while (++i < n);
6275     if (has_expensive_flags) {
6276       const size_t mop_stat_size = TS_ARRAY_SIZE(thr->stats.mops_per_trace);
6277       thr->stats.mops_per_trace[min(n, mop_stat_size - 1)]++;
6278       const size_t stat_size = TS_ARRAY_SIZE(thr->stats.locks_per_trace);
6279       thr->stats.locks_per_trace[min(n_locks, stat_size - 1)]++;
6280     }
6281   }
6282 
6283 #ifdef _MSC_VER
6284   NOINLINE
6285   // With MSVC, INLINE would cause the compilation to be insanely slow.
6286 #else
6287   INLINE
6288 #endif
HandleTrace(TSanThread * thr,MopInfo * mops,size_t n,uintptr_t pc,uintptr_t * tleb,bool need_locking)6289   void HandleTrace(TSanThread *thr, MopInfo *mops, size_t n, uintptr_t pc,
6290                    uintptr_t *tleb, bool need_locking) {
6291     DCHECK(n);
6292     // 0 bit - ignore reads, 1 bit -- ignore writes,
6293     // 2 bit - has_expensive_flags.
6294     int expensive_bits = thr->expensive_bits();
6295 
6296     if (expensive_bits == 0) {
6297       HandleTraceLoop(thr, pc, mops, tleb, n, 0, need_locking);
6298     } else {
6299       if ((expensive_bits & 3) == 3) {
6300         // everything is ignored, just clear the tleb.
6301         for (size_t i = 0; i < n; i++) tleb[i] = 0;
6302       } else {
6303         HandleTraceLoop(thr, pc, mops, tleb, n, expensive_bits, need_locking);
6304       }
6305     }
6306     // At the end, the tleb must be cleared.
6307     for (size_t i = 0; i < n; i++) DCHECK(tleb[i] == 0);
6308   }
6309 
6310   // Special case of a trace with just one mop and no sblock.
HandleMemoryAccess(TSanThread * thr,uintptr_t pc,uintptr_t addr,uintptr_t size,bool is_w,bool need_locking)6311   void INLINE HandleMemoryAccess(TSanThread *thr, uintptr_t pc,
6312                                  uintptr_t addr, uintptr_t size,
6313                                  bool is_w, bool need_locking) {
6314     CHECK(size);
6315     MopInfo mop(pc, size, is_w, false);
6316     HandleTrace(thr, &mop, 1, 0/*no sblock*/, &addr, need_locking);
6317   }
6318 
ShowUnfreedHeap()6319   void ShowUnfreedHeap() {
6320     // check if there is not deleted memory
6321     // (for debugging free() interceptors, not for leak detection)
6322     if (DEBUG_MODE && G_flags->debug_level >= 1) {
6323       for (HeapMap<HeapInfo>::iterator it = G_heap_map->begin();
6324            it != G_heap_map->end(); ++it) {
6325         HeapInfo &info = it->second;
6326         Printf("Not free()-ed memory: %p [%p, %p)\n%s\n",
6327                info.size, info.ptr, info.ptr + info.size,
6328                info.StackTraceString().c_str());
6329       }
6330     }
6331   }
6332 
FlushExpectedRaces(bool print_summary)6333   void FlushExpectedRaces(bool print_summary) {
6334     // Report("ThreadSanitizerValgrind: done\n");
6335     // check if we found all expected races (for unit tests only).
6336     static int total_missing = 0;
6337     int this_flush_missing = 0;
6338     for (ExpectedRacesMap::iterator it = G_expected_races_map->begin();
6339          it != G_expected_races_map->end(); ++it) {
6340       ExpectedRace race = it->second;
6341       if (debug_expected_races) {
6342         Printf("Checking if expected race fired: %p\n", race.ptr);
6343       }
6344       if (race.count == 0 &&
6345           !(g_race_verifier_active && !race.is_verifiable) &&
6346           (G_flags->nacl_untrusted == race.is_nacl_untrusted)) {
6347         ++this_flush_missing;
6348         Printf("Missing an expected race on %p: %s (annotated at %s)\n",
6349                it->first,
6350                race.description,
6351                PcToRtnNameAndFilePos(race.pc).c_str());
6352       }
6353     }
6354 
6355     if (this_flush_missing) {
6356       int n_errs = GetNumberOfFoundErrors();
6357       SetNumberOfFoundErrors(n_errs + this_flush_missing);
6358       total_missing += this_flush_missing;
6359     }
6360     G_expected_races_map->Clear();
6361 
6362     if (print_summary && total_missing > 0)
6363       Report("WARNING: %d expected race(s) NOT detected!\n", total_missing);
6364   }
6365 
HandleProgramEnd()6366   void HandleProgramEnd() {
6367     FlushExpectedRaces(true);
6368     // ShowUnfreedHeap();
6369     EventSampler::ShowSamples();
6370     ShowStats();
6371     TraceInfo::PrintTraceProfile();
6372     ShowProcSelfStatus();
6373     reports_.PrintUsedSuppression();
6374     reports_.PrintSummary();
6375     // Report("ThreadSanitizerValgrind: exiting\n");
6376   }
6377 
FlushIfOutOfMem(TSanThread * thr)6378   void FlushIfOutOfMem(TSanThread *thr) {
6379     static int max_vm_size;
6380     static int soft_limit;
6381     const int hard_limit = G_flags->max_mem_in_mb;
6382     const int minimal_soft_limit = (hard_limit * 13) / 16;
6383     const int print_info_limit   = (hard_limit * 12) / 16;
6384 
6385     CHECK(hard_limit > 0);
6386 
6387     int vm_size_in_mb = GetVmSizeInMb();
6388     if (max_vm_size < vm_size_in_mb) {
6389       max_vm_size = vm_size_in_mb;
6390       if (max_vm_size > print_info_limit) {
6391         Report("INFO: ThreadSanitizer's VmSize: %dM\n", (int)max_vm_size);
6392       }
6393     }
6394 
6395     if (soft_limit == 0) {
6396       soft_limit = minimal_soft_limit;
6397     }
6398 
6399     if (vm_size_in_mb > soft_limit) {
6400       ForgetAllStateAndStartOver(thr,
6401           "ThreadSanitizer is running close to its memory limit");
6402       soft_limit = vm_size_in_mb + 1;
6403     }
6404   }
6405 
6406   // Force state flushing.
FlushState(TID tid)6407   void FlushState(TID tid) {
6408     ForgetAllStateAndStartOver(TSanThread::Get(tid),
6409                                "State flushing requested by client");
6410   }
6411 
FlushIfNeeded(TSanThread * thr)6412   void FlushIfNeeded(TSanThread *thr) {
6413     // Are we out of segment IDs?
6414 #ifdef TS_VALGRIND  // GetVmSizeInMb() works only with valgrind any way.
6415     static int counter;
6416     counter++;  // ATTENTION: don't do this in multi-threaded code -- too slow.
6417     CHECK(TS_SERIALIZED == 1);
6418 
6419     // Are we out of memory?
6420     if (G_flags->max_mem_in_mb > 0) {
6421       const int kFreq = 1014 * 32;
6422       if ((counter % kFreq) == 0) {  // Don't do it too often.
6423         // TODO(kcc): find a way to check memory limit more frequently.
6424         TIL til(ts_lock, 7);
6425         AssertTILHeld();
6426         FlushIfOutOfMem(thr);
6427       }
6428     }
6429 #if 0
6430     if ((counter % (1024 * 1024 * 64)) == 0 ||
6431         counter == (1024 * 1024)) {
6432       // ShowStats();
6433       EventSampler::ShowSamples();
6434       TraceInfo::PrintTraceProfile();
6435     }
6436 #endif
6437 #endif
6438 
6439 #if 0  // do we still need it? Hope not..
6440     size_t flush_period = G_flags->flush_period * 1000;  // milliseconds.
6441     if (flush_period && (counter % (1024 * 4)) == 0) {
6442       size_t cur_time = TimeInMilliSeconds();
6443       if (cur_time - g_last_flush_time  > flush_period) {
6444         TIL til(ts_lock, 7);
6445         ForgetAllStateAndStartOver(
6446           "Doing periodic flush (period is set by --flush_period=n_seconds)");
6447       }
6448     }
6449 #endif
6450   }
6451 
HandleRtnCall(TID tid,uintptr_t call_pc,uintptr_t target_pc,IGNORE_BELOW_RTN ignore_below)6452   void HandleRtnCall(TID tid, uintptr_t call_pc, uintptr_t target_pc,
6453                      IGNORE_BELOW_RTN ignore_below) {
6454     TSanThread *thr = TSanThread::Get(tid);
6455     thr->HandleRtnCall(call_pc, target_pc, ignore_below);
6456     FlushIfNeeded(thr);
6457   }
6458 
HandleOneEvent(Event * e)6459   void INLINE HandleOneEvent(Event *e) {
6460     ScopedMallocCostCenter malloc_cc("HandleOneEvent");
6461 
6462     DCHECK(e);
6463     EventType type = e->type();
6464     DCHECK(type != NOOP);
6465     TSanThread *thr = NULL;
6466     if (type != THR_START) {
6467       thr = TSanThread::Get(TID(e->tid()));
6468       DCHECK(thr);
6469       thr->SetTopPc(e->pc());
6470       thr->stats.events[type]++;
6471     }
6472 
6473     switch (type) {
6474       case READ:
6475         HandleMemoryAccess(thr, e->pc(), e->a(), e->info(), false, true);
6476         return;
6477       case WRITE:
6478         HandleMemoryAccess(thr, e->pc(), e->a(), e->info(), true, true);
6479         return;
6480       case RTN_CALL:
6481         HandleRtnCall(TID(e->tid()), e->pc(), e->a(),
6482                       IGNORE_BELOW_RTN_UNKNOWN);
6483         return;
6484       case RTN_EXIT:
6485         thr->HandleRtnExit();
6486         return;
6487       default: break;
6488     }
6489 
6490     // Everything else is under a lock.
6491     TIL til(ts_lock, 0);
6492     AssertTILHeld();
6493 
6494 
6495     if (UNLIKELY(type == THR_START)) {
6496         HandleThreadStart(TID(e->tid()), TID(e->info()), (CallStack*)e->pc());
6497         TSanThread::Get(TID(e->tid()))->stats.events[type]++;
6498         return;
6499     }
6500 
6501     FlushStateIfOutOfSegments(thr);
6502 
6503     // Since we have the lock, get some fresh SIDs.
6504     thr->GetSomeFreshSids();
6505 
6506     switch (type) {
6507       case THR_START   : CHECK(0); break;
6508         break;
6509       case SBLOCK_ENTER:
6510         if (thr->ignore_reads() && thr->ignore_writes()) break;
6511         thr->HandleSblockEnter(e->pc(), /*allow_slow_path=*/true);
6512         break;
6513       case THR_CREATE_BEFORE:
6514         thr->HandleThreadCreateBefore(TID(e->tid()), e->pc());
6515         break;
6516       case THR_CREATE_AFTER:
6517         thr->HandleThreadCreateAfter(TID(e->tid()), TID(e->info()));
6518         break;
6519       case THR_FIRST_INSN:
6520         HandleThreadFirstInsn(TID(e->tid()));
6521         break;
6522       case THR_JOIN_AFTER     : HandleThreadJoinAfter(e);   break;
6523       case THR_STACK_TOP      : HandleThreadStackTop(e); break;
6524 
6525       case THR_END     : HandleThreadEnd(TID(e->tid()));     break;
6526       case MALLOC      : HandleMalloc(e, false);     break;
6527       case FREE        : HandleFree(e);         break;
6528       case MMAP        : HandleMalloc(e, true);      break;  // same as MALLOC
6529       case MUNMAP      : HandleMunmap(e);     break;
6530 
6531 
6532       case WRITER_LOCK : thr->HandleLock(e->a(), true);     break;
6533       case READER_LOCK : thr->HandleLock(e->a(), false);    break;
6534       case UNLOCK      : thr->HandleUnlock(e->a());       break;
6535       case UNLOCK_OR_INIT : HandleUnlockOrInit(e); break;
6536 
6537       case LOCK_CREATE:
6538       case LOCK_DESTROY: HandleLockCreateOrDestroy(e); break;
6539 
6540       case SIGNAL      : thr->HandleSignal(e->a());  break;
6541       case WAIT        : thr->HandleWait(e->a());   break;
6542 
6543       case CYCLIC_BARRIER_INIT:
6544         thr->HandleBarrierInit(e->a(), e->info());
6545         break;
6546       case CYCLIC_BARRIER_WAIT_BEFORE  :
6547         thr->HandleBarrierWaitBefore(e->a());
6548         break;
6549       case CYCLIC_BARRIER_WAIT_AFTER  :
6550         thr->HandleBarrierWaitAfter(e->a());
6551         break;
6552 
6553       case PCQ_CREATE   : HandlePcqCreate(e);   break;
6554       case PCQ_DESTROY  : HandlePcqDestroy(e);  break;
6555       case PCQ_PUT      : HandlePcqPut(e);      break;
6556       case PCQ_GET      : HandlePcqGet(e);      break;
6557 
6558 
6559       case EXPECT_RACE :
6560         HandleExpectRace(e->a(), (const char*)e->pc(), TID(e->tid()));
6561         break;
6562       case BENIGN_RACE :
6563         HandleBenignRace(e->a(), e->info(),
6564                          (const char*)e->pc(), TID(e->tid()));
6565         break;
6566       case FLUSH_EXPECTED_RACES:
6567         FlushExpectedRaces(false);
6568         break;
6569       case EXPECT_RACE_BEGIN:
6570         CHECK(g_expecting_races == false);
6571         g_expecting_races = true;
6572         g_found_races_since_EXPECT_RACE_BEGIN = 0;
6573         break;
6574       case EXPECT_RACE_END:
6575         CHECK(g_expecting_races == true);
6576         g_expecting_races = false;
6577         if (g_found_races_since_EXPECT_RACE_BEGIN == 0) {
6578           int n_errs = GetNumberOfFoundErrors();
6579           SetNumberOfFoundErrors(n_errs + 1);
6580           Printf("WARNING: expected race not found.\n");
6581         }
6582         break;
6583 
6584       case HB_LOCK     : HandleHBLock(e);       break;
6585       case NON_HB_LOCK : HandleNonHBLock(e);    break;
6586 
6587       case IGNORE_READS_BEG:  HandleIgnore(e, false, true);  break;
6588       case IGNORE_READS_END:  HandleIgnore(e, false, false); break;
6589       case IGNORE_WRITES_BEG: HandleIgnore(e, true, true);   break;
6590       case IGNORE_WRITES_END: HandleIgnore(e, true, false);  break;
6591 
6592       case SET_THREAD_NAME:
6593         thr->set_thread_name((const char*)e->a());
6594         break;
6595       case SET_LOCK_NAME: {
6596           uintptr_t lock_addr = e->a();
6597           const char *name = reinterpret_cast<const char *>(e->info());
6598           Lock *lock = Lock::LookupOrCreate(lock_addr);
6599           lock->set_name(name);
6600         }
6601         break;
6602 
6603       case PUBLISH_RANGE : HandlePublishRange(e); break;
6604       case UNPUBLISH_RANGE :
6605         Report("WARNING: ANNOTATE_UNPUBLISH_MEMORY_RANGE is deprecated\n");
6606         break;
6607 
6608       case TRACE_MEM   : HandleTraceMem(e);   break;
6609       case STACK_TRACE : HandleStackTrace(e); break;
6610       case NOOP        : CHECK(0);           break;  // can't happen.
6611       case VERBOSITY   : e->Print(); G_flags->verbosity = e->info(); break;
6612       case FLUSH_STATE : FlushState(TID(e->tid()));       break;
6613       default                 : CHECK(0);    break;
6614     }
6615   }
6616 
6617  private:
ShowProcSelfStatus()6618   void ShowProcSelfStatus() {
6619     if (G_flags->show_proc_self_status) {
6620       string str = ReadFileToString("/proc/self/status", false);
6621       if (!str.empty()) {
6622         Printf("%s", str.c_str());
6623       }
6624     }
6625   }
6626 
ShowStats()6627   void ShowStats() {
6628     if (G_flags->show_stats) {
6629       G_stats->PrintStats();
6630       G_cache->PrintStorageStats();
6631     }
6632   }
6633 
6634   // PCQ_CREATE, PCQ_DESTROY, PCQ_PUT, PCQ_GET
HandlePcqCreate(Event * e)6635   void HandlePcqCreate(Event *e) {
6636     if (G_flags->verbosity >= 2) {
6637       e->Print();
6638     }
6639     PCQ pcq;
6640     pcq.pcq_addr = e->a();
6641     CHECK(!g_pcq_map->count(e->a()));
6642     (*g_pcq_map)[e->a()] = pcq;
6643   }
HandlePcqDestroy(Event * e)6644   void HandlePcqDestroy(Event *e) {
6645     if (G_flags->verbosity >= 2) {
6646       e->Print();
6647     }
6648     CHECK(g_pcq_map->count(e->a()));
6649     g_pcq_map->erase(e->a());
6650   }
HandlePcqPut(Event * e)6651   void HandlePcqPut(Event *e) {
6652     if (G_flags->verbosity >= 2) {
6653       e->Print();
6654     }
6655     PCQ &pcq = (*g_pcq_map)[e->a()];
6656     CHECK(pcq.pcq_addr == e->a());
6657     TSanThread *thread = TSanThread::Get(TID(e->tid()));
6658     VTS *vts = thread->segment()->vts()->Clone();
6659     pcq.putters.push_back(vts);
6660     thread->NewSegmentForSignal();
6661   }
HandlePcqGet(Event * e)6662   void HandlePcqGet(Event *e) {
6663     if (G_flags->verbosity >= 2) {
6664       e->Print();
6665     }
6666     PCQ &pcq = (*g_pcq_map)[e->a()];
6667     CHECK(pcq.pcq_addr == e->a());
6668     CHECK(!pcq.putters.empty());
6669     VTS *putter = pcq.putters.front();
6670     pcq.putters.pop_front();
6671     CHECK(putter);
6672     TSanThread *thread = TSanThread::Get(TID(e->tid()));
6673     thread->NewSegmentForWait(putter);
6674     VTS::Unref(putter);
6675   }
6676 
6677   // PUBLISH_RANGE
HandlePublishRange(Event * e)6678   void HandlePublishRange(Event *e) {
6679     if (G_flags->verbosity >= 2) {
6680       e->Print();
6681     }
6682     static int reported_deprecation;
6683     reported_deprecation++;
6684     if (reported_deprecation < 20) {
6685       Report("WARNING: ANNOTATE_PUBLISH_MEMORY_RANGE is deprecated and will not"
6686              " be supported in future versions of ThreadSanitizer.\n");
6687     }
6688 
6689     uintptr_t mem = e->a();
6690     uintptr_t size = e->info();
6691 
6692     TID tid(e->tid());
6693     TSanThread *thread = TSanThread::Get(tid);
6694     VTS *vts = thread->segment()->vts();
6695     PublishRange(thread, mem, mem + size, vts);
6696 
6697     thread->NewSegmentForSignal();
6698     // Printf("Publish: [%p, %p)\n", mem, mem+size);
6699   }
6700 
HandleIgnore(Event * e,bool is_w,bool on)6701   void HandleIgnore(Event *e, bool is_w, bool on) {
6702     if (G_flags->verbosity >= 2) {
6703       e->Print();
6704     }
6705     TSanThread *thread = TSanThread::Get(TID(e->tid()));
6706     thread->set_ignore_accesses(is_w, on);
6707   }
6708 
6709   // BENIGN_RACE
HandleBenignRace(uintptr_t ptr,uintptr_t size,const char * descr,TID tid)6710   void HandleBenignRace(uintptr_t ptr, uintptr_t size,
6711                         const char *descr, TID tid) {
6712     TSanThread *thr = TSanThread::Get(tid);
6713     if (debug_benign_races) {
6714       Printf("T%d: BENIGN_RACE: ptr=%p size=%ld descr='%s'\n",
6715              tid.raw(), ptr, size, descr);
6716     }
6717     // Simply set all 'racey' bits in the shadow state of [ptr, ptr+size).
6718     for (uintptr_t p = ptr; p < ptr + size; p++) {
6719       CacheLine *line = G_cache->GetLineOrCreateNew(thr, p, __LINE__);
6720       CHECK(line);
6721       line->racey().Set(CacheLine::ComputeOffset(p));
6722       G_cache->ReleaseLine(thr, p, line, __LINE__);
6723     }
6724   }
6725 
6726   // EXPECT_RACE
HandleExpectRace(uintptr_t ptr,const char * descr,TID tid)6727   void HandleExpectRace(uintptr_t ptr, const char *descr, TID tid) {
6728     ExpectedRace expected_race;
6729     expected_race.ptr = ptr;
6730     expected_race.size = 1;
6731     expected_race.count = 0;
6732     expected_race.is_verifiable = !descr ||
6733         (string(descr).find("UNVERIFIABLE") == string::npos);
6734     expected_race.is_nacl_untrusted = !descr ||
6735         (string(descr).find("NACL_UNTRUSTED") != string::npos);
6736     // copy descr (may not have strdup)
6737     CHECK(descr);
6738     size_t descr_len = strlen(descr);
6739     char *d = new char [descr_len + 1];
6740     memcpy(d, descr, descr_len);
6741     d[descr_len] = 0;
6742     expected_race.description = d;
6743 
6744     TSanThread *thread = TSanThread::Get(tid);
6745     expected_race.pc = thread->GetCallstackEntry(1);
6746     G_expected_races_map->InsertInfo(ptr, expected_race);
6747 
6748     // Flush 'racey' flag for the address
6749     CacheLine *cache_line = G_cache->GetLineIfExists(thread, ptr, __LINE__);
6750     if (cache_line != NULL) {
6751       uintptr_t offset = CacheLine::ComputeOffset(ptr);
6752       cache_line->racey().ClearRange(offset, offset + 1);
6753       G_cache->ReleaseLine(thread, ptr, cache_line, __LINE__);
6754     }
6755 
6756     if (debug_expected_races) {
6757       Printf("T%d: EXPECT_RACE: ptr=%p descr='%s'\n", tid.raw(), ptr, descr);
6758       thread->ReportStackTrace(ptr);
6759       int i = 0;
6760       for (ExpectedRacesMap::iterator it = G_expected_races_map->begin();
6761            it != G_expected_races_map->end(); ++it) {
6762         ExpectedRace &x = it->second;
6763         Printf("  [%d] %p [0x%lx]\n", i, &x, x.ptr);
6764         i++;
6765       }
6766     }
6767   }
6768 
HandleStackTrace(Event * e)6769   void HandleStackTrace(Event *e) {
6770     TSanThread *thread = TSanThread::Get(TID(e->tid()));
6771     e->Print();
6772     thread->ReportStackTrace();
6773   }
6774 
6775   // HB_LOCK
HandleHBLock(Event * e)6776   void HandleHBLock(Event *e) {
6777     if (G_flags->verbosity >= 2) {
6778       e->Print();
6779     }
6780     Lock *lock = Lock::LookupOrCreate(e->a());
6781     CHECK(lock);
6782     lock->set_is_pure_happens_before(true);
6783   }
6784 
6785   // NON_HB_LOCK
HandleNonHBLock(Event * e)6786   void HandleNonHBLock(Event *e) {
6787     if (G_flags->verbosity >= 2) {
6788       e->Print();
6789     }
6790     Lock *lock = Lock::LookupOrCreate(e->a());
6791     CHECK(lock);
6792     lock->set_is_pure_happens_before(false);
6793   }
6794 
6795   // UNLOCK_OR_INIT
6796   // This is a hack to handle posix pthread_spin_unlock which is sometimes
6797   // the same symbol as pthread_spin_init. We need to handle unlock as init
6798   // if the lock was not seen before or if it is currently unlocked.
6799   // TODO(kcc): is there a way to distinguish pthread_spin_init
6800   // and pthread_spin_unlock?
HandleUnlockOrInit(Event * e)6801   void HandleUnlockOrInit(Event *e) {
6802     TSanThread *thread = TSanThread::Get(TID(e->tid()));
6803     if (G_flags->verbosity >= 2) {
6804       e->Print();
6805       thread->ReportStackTrace();
6806     }
6807     uintptr_t lock_addr = e->a();
6808     Lock *lock = Lock::Lookup(lock_addr);
6809     if (lock && lock->wr_held()) {
6810       // We know this lock and it is locked. Just unlock it.
6811       thread->HandleUnlock(lock_addr);
6812     } else {
6813       // Never seen this lock or it is currently unlocked. Init it.
6814       Lock::Create(lock_addr);
6815     }
6816   }
6817 
HandleLockCreateOrDestroy(Event * e)6818   void HandleLockCreateOrDestroy(Event *e) {
6819     TSanThread *thread = TSanThread::Get(TID(e->tid()));
6820     uintptr_t lock_addr = e->a();
6821     if (debug_lock) {
6822       e->Print();
6823     }
6824     if (e->type() == LOCK_CREATE) {
6825       Lock::Create(lock_addr);
6826     } else {
6827       CHECK(e->type() == LOCK_DESTROY);
6828       // A locked pthread_mutex_t can not be destroyed but other lock types can.
6829       // When destroying a lock, we must unlock it.
6830       // If there is a bug in a program when someone attempts to unlock
6831       // a destoyed lock, we are likely to fail in an assert.
6832       //
6833       // We do not unlock-on-destroy after main() has exited.
6834       // This is because global Mutex objects may be desctructed while threads
6835       // holding them are still running. Urgh...
6836       Lock *lock = Lock::Lookup(lock_addr);
6837       // If the lock is not found, report an error.
6838       if (lock == NULL) {
6839         ThreadSanitizerInvalidLockReport *report =
6840             new ThreadSanitizerInvalidLockReport;
6841         report->type = ThreadSanitizerReport::INVALID_LOCK;
6842         report->tid = TID(e->tid());
6843         report->lock_addr = lock_addr;
6844         report->stack_trace = thread->CreateStackTrace();
6845         ThreadSanitizerPrintReport(report);
6846         return;
6847       }
6848       if (lock->wr_held() || lock->rd_held()) {
6849         if (G_flags->unlock_on_mutex_destroy && !g_has_exited_main) {
6850           thread->HandleUnlock(lock_addr);
6851         }
6852       }
6853       thread->HandleForgetSignaller(lock_addr);
6854       Lock::Destroy(lock_addr);
6855     }
6856   }
6857 
HandleTraceMem(Event * e)6858   void HandleTraceMem(Event *e) {
6859     if (G_flags->trace_level == 0) return;
6860     TID tid(e->tid());
6861     TSanThread *thr = TSanThread::Get(TID(e->tid()));
6862     uintptr_t a = e->a();
6863     CacheLine *line = G_cache->GetLineOrCreateNew(thr, a, __LINE__);
6864     uintptr_t offset = CacheLine::ComputeOffset(a);
6865     line->traced().Set(offset);
6866     G_cache->ReleaseLine(thr, a, line, __LINE__);
6867     if (G_flags->verbosity >= 2) e->Print();
6868   }
6869 
RefAndUnrefTwoSegSetPairsIfDifferent(SSID new_ssid1,SSID old_ssid1,SSID new_ssid2,SSID old_ssid2)6870   INLINE void RefAndUnrefTwoSegSetPairsIfDifferent(SSID new_ssid1,
6871                                                    SSID old_ssid1,
6872                                                    SSID new_ssid2,
6873                                                    SSID old_ssid2) {
6874     bool recycle_1 = new_ssid1 != old_ssid1,
6875          recycle_2 = new_ssid2 != old_ssid2;
6876     if (recycle_1 && !new_ssid1.IsEmpty()) {
6877       SegmentSet::Ref(new_ssid1, "RefAndUnrefTwoSegSetPairsIfDifferent");
6878     }
6879 
6880     if (recycle_2 && !new_ssid2.IsEmpty()) {
6881       SegmentSet::Ref(new_ssid2, "RefAndUnrefTwoSegSetPairsIfDifferent");
6882     }
6883 
6884     if (recycle_1 && !old_ssid1.IsEmpty()) {
6885       SegmentSet::Unref(old_ssid1, "RefAndUnrefTwoSegSetPairsIfDifferent");
6886     }
6887 
6888     if (recycle_2 && !old_ssid2.IsEmpty()) {
6889       SegmentSet::Unref(old_ssid2, "RefAndUnrefTwoSegSetPairsIfDifferent");
6890     }
6891   }
6892 
6893 
6894   // return true if the current pair of read/write segment sets
6895   // describes a race.
CheckIfRace(SSID rd_ssid,SSID wr_ssid)6896   bool NOINLINE CheckIfRace(SSID rd_ssid, SSID wr_ssid) {
6897     int wr_ss_size = SegmentSet::Size(wr_ssid);
6898     int rd_ss_size = SegmentSet::Size(rd_ssid);
6899 
6900     DCHECK(wr_ss_size >= 2 || (wr_ss_size >= 1 && rd_ss_size >= 1));
6901 
6902     // check all write-write pairs
6903     for (int w1 = 0; w1 < wr_ss_size; w1++) {
6904       SID w1_sid = SegmentSet::GetSID(wr_ssid, w1, __LINE__);
6905       Segment *w1_seg = Segment::Get(w1_sid);
6906       LSID w1_ls = w1_seg->lsid(true);
6907       for (int w2 = w1 + 1; w2 < wr_ss_size; w2++) {
6908         DCHECK(wr_ssid.IsTuple());
6909         SegmentSet *ss = SegmentSet::Get(wr_ssid);
6910         LSID w2_ls = Segment::Get(ss->GetSID(w2))->lsid(true);
6911         if (LockSet::IntersectionIsEmpty(w1_ls, w2_ls)) {
6912           return true;
6913         } else {
6914           // May happen only if the locks in the intersection are hybrid locks.
6915           DCHECK(LockSet::HasNonPhbLocks(w1_ls) &&
6916                  LockSet::HasNonPhbLocks(w2_ls));
6917         }
6918       }
6919       // check all write-read pairs
6920       for (int r = 0; r < rd_ss_size; r++) {
6921         SID r_sid = SegmentSet::GetSID(rd_ssid, r, __LINE__);
6922         Segment *r_seg = Segment::Get(r_sid);
6923         LSID r_ls = r_seg->lsid(false);
6924         if (Segment::HappensBeforeOrSameThread(w1_sid, r_sid))
6925           continue;
6926         if (LockSet::IntersectionIsEmpty(w1_ls, r_ls)) {
6927           return true;
6928         } else {
6929           // May happen only if the locks in the intersection are hybrid locks.
6930           DCHECK(LockSet::HasNonPhbLocks(w1_ls) &&
6931                  LockSet::HasNonPhbLocks(r_ls));
6932         }
6933       }
6934     }
6935     return false;
6936   }
6937 
6938   // New experimental state machine.
6939   // Set *res to the new state.
6940   // Return true if the new state is race.
MemoryStateMachine(ShadowValue old_sval,TSanThread * thr,bool is_w,ShadowValue * res)6941   bool INLINE MemoryStateMachine(ShadowValue old_sval, TSanThread *thr,
6942                                  bool is_w, ShadowValue *res) {
6943     ShadowValue new_sval;
6944     SID cur_sid = thr->sid();
6945     DCHECK(cur_sid.valid());
6946 
6947     if (UNLIKELY(old_sval.IsNew())) {
6948       // We see this memory for the first time.
6949       DCHECK(cur_sid.valid());
6950       if (is_w) {
6951         new_sval.set(SSID(0), SSID(cur_sid));
6952       } else {
6953         new_sval.set(SSID(cur_sid), SSID(0));
6954       }
6955       *res = new_sval;
6956       return false;
6957     }
6958 
6959     SSID old_rd_ssid = old_sval.rd_ssid();
6960     SSID old_wr_ssid = old_sval.wr_ssid();
6961     SSID new_rd_ssid(0);
6962     SSID new_wr_ssid(0);
6963     if (is_w) {
6964       new_rd_ssid = SegmentSet::RemoveSegmentFromSS(old_rd_ssid, cur_sid);
6965       new_wr_ssid = SegmentSet::AddSegmentToSS(old_wr_ssid, cur_sid);
6966     } else {
6967       if (SegmentSet::Contains(old_wr_ssid, cur_sid)) {
6968         // cur_sid is already in old_wr_ssid, no change to SSrd is required.
6969         new_rd_ssid = old_rd_ssid;
6970       } else {
6971         new_rd_ssid = SegmentSet::AddSegmentToSS(old_rd_ssid, cur_sid);
6972       }
6973       new_wr_ssid = old_wr_ssid;
6974     }
6975 
6976     if (UNLIKELY(G_flags->sample_events > 0)) {
6977       if (new_rd_ssid.IsTuple() || new_wr_ssid.IsTuple()) {
6978         static EventSampler sampler;
6979         sampler.Sample(thr, "HasTupleSS", false);
6980       }
6981     }
6982 
6983 
6984     new_sval.set(new_rd_ssid, new_wr_ssid);
6985     *res = new_sval;
6986     if (new_sval == old_sval)
6987       return false;
6988 
6989     if (new_wr_ssid.IsTuple() ||
6990         (!new_wr_ssid.IsEmpty() && !new_rd_ssid.IsEmpty())) {
6991       return CheckIfRace(new_rd_ssid, new_wr_ssid);
6992     }
6993     return false;
6994   }
6995 
6996 
6997   // Fast path implementation for the case when we stay in the same thread.
6998   // In this case we don't need to call HappensBefore(), deal with
6999   // Tuple segment sets and check for race.
7000   // If this function returns true, the ShadowValue *new_sval is updated
7001   // in the same way as MemoryStateMachine() would have done it. Just faster.
MemoryStateMachineSameThread(bool is_w,ShadowValue old_sval,TSanThread * thr,ShadowValue * new_sval)7002   INLINE bool MemoryStateMachineSameThread(bool is_w, ShadowValue old_sval,
7003                                            TSanThread *thr,
7004                                            ShadowValue *new_sval) {
7005 #define MSM_STAT(i) do { if (DEBUG_MODE) \
7006   thr->stats.msm_branch_count[i]++; } while ((void)0, 0)
7007     SSID rd_ssid = old_sval.rd_ssid();
7008     SSID wr_ssid = old_sval.wr_ssid();
7009     SID cur_sid = thr->sid();
7010     TID tid = thr->tid();
7011     if (rd_ssid.IsEmpty()) {
7012       if (wr_ssid.IsSingleton()) {
7013         // *** CASE 01 ***: rd_ssid == 0, wr_ssid == singleton
7014         SID wr_sid = wr_ssid.GetSingleton();
7015         if (wr_sid == cur_sid) {  // --- w/r: {0, cur} => {0, cur}
7016           MSM_STAT(1);
7017           // no op
7018           return true;
7019         }
7020         if (tid == Segment::Get(wr_sid)->tid()) {
7021           // same thread, but the segments are different.
7022           DCHECK(cur_sid != wr_sid);
7023           if (is_w) {    // -------------- w: {0, wr} => {0, cur}
7024             MSM_STAT(2);
7025             new_sval->set(SSID(0), SSID(cur_sid));
7026             thr->AddDeadSid(wr_sid, "FastPath01");
7027           } else {       // -------------- r: {0, wr} => {cur, wr}
7028             MSM_STAT(3);
7029             new_sval->set(SSID(cur_sid), wr_ssid);
7030           }
7031           Segment::Ref(cur_sid, "FastPath01");
7032           return true;
7033         }
7034       } else if (wr_ssid.IsEmpty()) {
7035         // *** CASE 00 ***: rd_ssid == 0, wr_ssid == 0
7036         if (is_w) {      // -------------- w: {0, 0} => {0, cur}
7037           MSM_STAT(4);
7038           new_sval->set(SSID(0), SSID(cur_sid));
7039         } else {         // -------------- r: {0, 0} => {cur, 0}
7040           MSM_STAT(5);
7041           new_sval->set(SSID(cur_sid), SSID(0));
7042         }
7043         Segment::Ref(cur_sid, "FastPath00");
7044         return true;
7045       }
7046     } else if (rd_ssid.IsSingleton()) {
7047       SID rd_sid = rd_ssid.GetSingleton();
7048       if (wr_ssid.IsEmpty()) {
7049         // *** CASE 10 ***: rd_ssid == singleton, wr_ssid == 0
7050         if (rd_sid == cur_sid) {
7051           // same segment.
7052           if (is_w) {    // -------------- w: {cur, 0} => {0, cur}
7053             MSM_STAT(6);
7054             new_sval->set(SSID(0), SSID(cur_sid));
7055           } else {       // -------------- r: {cur, 0} => {cur, 0}
7056             MSM_STAT(7);
7057             // no op
7058           }
7059           return true;
7060         }
7061         if (tid == Segment::Get(rd_sid)->tid()) {
7062           // same thread, but the segments are different.
7063           DCHECK(cur_sid != rd_sid);
7064           if (is_w) {  // -------------- w: {rd, 0} => {0, cur}
7065             MSM_STAT(8);
7066             new_sval->set(SSID(0), SSID(cur_sid));
7067           } else {     // -------------- r: {rd, 0} => {cur, 0}
7068             MSM_STAT(9);
7069             new_sval->set(SSID(cur_sid), SSID(0));
7070           }
7071           Segment::Ref(cur_sid, "FastPath10");
7072           thr->AddDeadSid(rd_sid, "FastPath10");
7073           return true;
7074         }
7075       } else if (wr_ssid.IsSingleton()){
7076         // *** CASE 11 ***: rd_ssid == singleton, wr_ssid == singleton
7077         DCHECK(rd_ssid.IsSingleton());
7078         SID wr_sid = wr_ssid.GetSingleton();
7079         DCHECK(wr_sid != rd_sid);  // By definition of ShadowValue.
7080         if (cur_sid == rd_sid) {
7081           if (tid == Segment::Get(wr_sid)->tid()) {
7082             if (is_w) {  // -------------- w: {cur, wr} => {0, cur}
7083               MSM_STAT(10);
7084               new_sval->set(SSID(0), SSID(cur_sid));
7085               thr->AddDeadSid(wr_sid, "FastPath11");
7086             } else {     // -------------- r: {cur, wr} => {cur, wr}
7087               MSM_STAT(11);
7088               // no op
7089             }
7090             return true;
7091           }
7092         } else if (cur_sid == wr_sid){
7093           if (tid == Segment::Get(rd_sid)->tid()) {
7094             if (is_w) {  // -------------- w: {rd, cur} => {rd, cur}
7095               MSM_STAT(12);
7096               // no op
7097             } else {     // -------------- r: {rd, cur} => {0, cur}
7098               MSM_STAT(13);
7099               new_sval->set(SSID(0), SSID(cur_sid));
7100               thr->AddDeadSid(rd_sid, "FastPath11");
7101             }
7102             return true;
7103           }
7104         } else if (tid == Segment::Get(rd_sid)->tid() &&
7105                    tid == Segment::Get(wr_sid)->tid()) {
7106           if (is_w) {    // -------------- w: {rd, wr} => {0, cur}
7107             MSM_STAT(14);
7108             new_sval->set(SSID(0), SSID(cur_sid));
7109             thr->AddDeadSid(wr_sid, "FastPath11");
7110           } else {       // -------------- r: {rd, wr} => {cur, wr}
7111             MSM_STAT(15);
7112             new_sval->set(SSID(cur_sid), wr_ssid);
7113           }
7114           thr->AddDeadSid(rd_sid, "FastPath11");
7115           Segment::Ref(cur_sid, "FastPath11");
7116           return true;
7117         }
7118       }
7119     }
7120     MSM_STAT(0);
7121     return false;
7122 #undef MSM_STAT
7123   }
7124 
7125   // return false if we were not able to complete the task (fast_path_only).
HandleMemoryAccessHelper(bool is_w,CacheLine * cache_line,uintptr_t addr,uintptr_t size,uintptr_t pc,TSanThread * thr,bool fast_path_only)7126   INLINE bool HandleMemoryAccessHelper(bool is_w,
7127                                        CacheLine *cache_line,
7128                                        uintptr_t addr,
7129                                        uintptr_t size,
7130                                        uintptr_t pc,
7131                                        TSanThread *thr,
7132                                        bool fast_path_only) {
7133     DCHECK((addr & (size - 1)) == 0);  // size-aligned.
7134     uintptr_t offset = CacheLine::ComputeOffset(addr);
7135 
7136     ShadowValue old_sval;
7137     ShadowValue *sval_p = NULL;
7138 
7139     if (UNLIKELY(!cache_line->has_shadow_value().Get(offset))) {
7140       sval_p = cache_line->AddNewSvalAtOffset(offset);
7141       DCHECK(sval_p->IsNew());
7142     } else {
7143       sval_p = cache_line->GetValuePointer(offset);
7144     }
7145     old_sval = *sval_p;
7146 
7147     bool res = false;
7148     bool fast_path_ok = MemoryStateMachineSameThread(
7149         is_w, old_sval, thr, sval_p);
7150     if (fast_path_ok) {
7151       res = true;
7152     } else if (fast_path_only) {
7153       res = false;
7154     } else {
7155       bool is_published = cache_line->published().Get(offset);
7156       // We check only the first bit for publishing, oh well.
7157       if (UNLIKELY(is_published)) {
7158         const VTS *signaller_vts = GetPublisherVTS(addr);
7159         CHECK(signaller_vts);
7160         thr->NewSegmentForWait(signaller_vts);
7161       }
7162 
7163       bool is_race = MemoryStateMachine(old_sval, thr, is_w, sval_p);
7164 
7165       // Check for race.
7166       if (UNLIKELY(is_race)) {
7167         if (thr->ShouldReportRaces()) {
7168           if (G_flags->report_races && !cache_line->racey().Get(offset)) {
7169             reports_.AddReport(thr, pc, is_w, addr, size,
7170                                old_sval, *sval_p, is_published);
7171           }
7172           cache_line->racey().SetRange(offset, offset + size);
7173         }
7174       }
7175 
7176       // Ref/Unref segments
7177       RefAndUnrefTwoSegSetPairsIfDifferent(sval_p->rd_ssid(),
7178                                            old_sval.rd_ssid(),
7179                                            sval_p->wr_ssid(),
7180                                            old_sval.wr_ssid());
7181       res = true;
7182     }
7183 
7184 
7185     if (DEBUG_MODE && !fast_path_only) {
7186       // check that the SSIDs/SIDs in the new sval have sane ref counters.
7187       CHECK(!sval_p->wr_ssid().IsEmpty() || !sval_p->rd_ssid().IsEmpty());
7188       for (int i = 0; i < 2; i++) {
7189         SSID ssid = i ? sval_p->rd_ssid() : sval_p->wr_ssid();
7190         if (ssid.IsEmpty()) continue;
7191         if (ssid.IsSingleton()) {
7192           // singleton segment should have ref count > 0.
7193           SID sid = ssid.GetSingleton();
7194           Segment *seg = Segment::Get(sid);
7195           (void)seg;
7196           CHECK(seg->ref_count() > 0);
7197           if (sid == thr->sid()) {
7198             // if this is the current seg, ref count should be > 1.
7199             CHECK(seg->ref_count() > 1);
7200           }
7201         } else {
7202           SegmentSet *sset = SegmentSet::Get(ssid);
7203           (void)sset;
7204           CHECK(sset->ref_count() > 0);
7205         }
7206       }
7207     }
7208     return res;
7209   }
7210 
7211 
7212   // return false if we were not able to complete the task (fast_path_only).
HandleAccessGranularityAndExecuteHelper(CacheLine * cache_line,TSanThread * thr,uintptr_t addr,MopInfo * mop,bool has_expensive_flags,bool fast_path_only)7213   INLINE bool HandleAccessGranularityAndExecuteHelper(
7214       CacheLine *cache_line,
7215       TSanThread *thr, uintptr_t addr, MopInfo *mop,
7216       bool has_expensive_flags, bool fast_path_only) {
7217     size_t size = mop->size();
7218     uintptr_t pc = mop->pc();
7219     bool is_w = mop->is_write();
7220     uintptr_t a = addr;
7221     uintptr_t b = 0;
7222     uintptr_t off = CacheLine::ComputeOffset(a);
7223 
7224     uint16_t *granularity_mask = cache_line->granularity_mask(off);
7225     uint16_t gr = *granularity_mask;
7226 
7227     // Can't do split/join on the fast path, bacause it involves segment set
7228     // reference count manipulation that is not thread-safe.
7229 
7230     if        (size == 8 && (off & 7) == 0) {
7231       if (!gr) {
7232         *granularity_mask = gr = 1;  // 0000000000000001
7233       }
7234       if (GranularityIs8(off, gr)) {
7235         if (has_expensive_flags) thr->stats.n_fast_access8++;
7236         cache_line->DebugTrace(off, __FUNCTION__, __LINE__);
7237         goto one_call;
7238       } else {
7239         if (fast_path_only) return false;
7240         if (has_expensive_flags) thr->stats.n_slow_access8++;
7241         cache_line->Join_1_to_2(off);
7242         cache_line->Join_1_to_2(off + 2);
7243         cache_line->Join_1_to_2(off + 4);
7244         cache_line->Join_1_to_2(off + 6);
7245         cache_line->Join_2_to_4(off);
7246         cache_line->Join_2_to_4(off + 4);
7247         cache_line->Join_4_to_8(off);
7248         goto slow_path;
7249       }
7250     } else if (size == 4 && (off & 3) == 0) {
7251       if (!gr) {
7252         *granularity_mask = gr = 3 << 1;  // 0000000000000110
7253       }
7254       if (GranularityIs4(off, gr)) {
7255         if (has_expensive_flags) thr->stats.n_fast_access4++;
7256         cache_line->DebugTrace(off, __FUNCTION__, __LINE__);
7257         goto one_call;
7258       } else {
7259         if (fast_path_only) return false;
7260         if (has_expensive_flags) thr->stats.n_slow_access4++;
7261         cache_line->Split_8_to_4(off);
7262         cache_line->Join_1_to_2(off);
7263         cache_line->Join_1_to_2(off + 2);
7264         cache_line->Join_2_to_4(off);
7265         goto slow_path;
7266       }
7267     } else if (size == 2 && (off & 1) == 0) {
7268       if (!gr) {
7269         *granularity_mask = gr = 15 << 3;  // 0000000001111000
7270       }
7271       if (GranularityIs2(off, gr)) {
7272         if (has_expensive_flags) thr->stats.n_fast_access2++;
7273         cache_line->DebugTrace(off, __FUNCTION__, __LINE__);
7274         goto one_call;
7275       } else {
7276         if (fast_path_only) return false;
7277         if (has_expensive_flags) thr->stats.n_slow_access2++;
7278         cache_line->Split_8_to_4(off);
7279         cache_line->Split_4_to_2(off);
7280         cache_line->Join_1_to_2(off);
7281         goto slow_path;
7282       }
7283     } else if (size == 1) {
7284       if (!gr) {
7285         *granularity_mask = gr = 255 << 7;  // 0111111110000000
7286       }
7287       if (GranularityIs1(off, gr)) {
7288         if (has_expensive_flags) thr->stats.n_fast_access1++;
7289         cache_line->DebugTrace(off, __FUNCTION__, __LINE__);
7290         goto one_call;
7291       } else {
7292         if (fast_path_only) return false;
7293         if (has_expensive_flags) thr->stats.n_slow_access1++;
7294         cache_line->Split_8_to_4(off);
7295         cache_line->Split_4_to_2(off);
7296         cache_line->Split_2_to_1(off);
7297         goto slow_path;
7298       }
7299     } else {
7300       if (fast_path_only) return false;
7301       if (has_expensive_flags) thr->stats.n_very_slow_access++;
7302       // Very slow: size is not 1,2,4,8 or address is unaligned.
7303       // Handle this access as a series of 1-byte accesses, but only
7304       // inside the current cache line.
7305       // TODO(kcc): do we want to handle the next cache line as well?
7306       b = a + mop->size();
7307       uintptr_t max_x = min(b, CacheLine::ComputeNextTag(a));
7308       for (uintptr_t x = a; x < max_x; x++) {
7309         off = CacheLine::ComputeOffset(x);
7310         DCHECK(CacheLine::ComputeTag(x) == cache_line->tag());
7311         uint16_t *granularity_mask = cache_line->granularity_mask(off);
7312         if (!*granularity_mask) {
7313           *granularity_mask = 1;
7314         }
7315         cache_line->DebugTrace(off, __FUNCTION__, __LINE__);
7316         cache_line->Split_8_to_4(off);
7317         cache_line->Split_4_to_2(off);
7318         cache_line->Split_2_to_1(off);
7319         if (!HandleMemoryAccessHelper(is_w, cache_line, x, 1, pc, thr, false))
7320           return false;
7321       }
7322       return true;
7323     }
7324 
7325 slow_path:
7326     if (fast_path_only) return false;
7327     DCHECK(cache_line);
7328     DCHECK(size == 1 || size == 2 || size == 4 || size == 8);
7329     DCHECK((addr & (size - 1)) == 0);  // size-aligned.
7330     gr = *granularity_mask;
7331     CHECK(gr);
7332     // size is one of 1, 2, 4, 8; address is size-aligned, but the granularity
7333     // is different.
7334     b = a + mop->size();
7335     for (uintptr_t x = a; x < b;) {
7336       if (has_expensive_flags) thr->stats.n_access_slow_iter++;
7337       off = CacheLine::ComputeOffset(x);
7338       cache_line->DebugTrace(off, __FUNCTION__, __LINE__);
7339       size_t s = 0;
7340       // How many bytes are we going to access?
7341       if     (GranularityIs8(off, gr)) s = 8;
7342       else if(GranularityIs4(off, gr)) s = 4;
7343       else if(GranularityIs2(off, gr)) s = 2;
7344       else                             s = 1;
7345       if (!HandleMemoryAccessHelper(is_w, cache_line, x, s, pc, thr, false))
7346         return false;
7347       x += s;
7348     }
7349     return true;
7350 one_call:
7351     return HandleMemoryAccessHelper(is_w, cache_line, addr, size, pc,
7352                                     thr, fast_path_only);
7353   }
7354 
IsTraced(CacheLine * cache_line,uintptr_t addr,bool has_expensive_flags)7355   INLINE bool IsTraced(CacheLine *cache_line, uintptr_t addr,
7356                        bool has_expensive_flags) {
7357     if (!has_expensive_flags) return false;
7358     if (G_flags->trace_level == 0) return false;
7359     DCHECK(cache_line);
7360     uintptr_t off = CacheLine::ComputeOffset(addr);
7361     if (cache_line->traced().Get(off)) {
7362       return true;
7363     } else if (addr == G_flags->trace_addr) {
7364       return true;
7365     }
7366     return false;
7367   }
7368 
DoTrace(TSanThread * thr,uintptr_t addr,MopInfo * mop,bool need_locking)7369   void DoTrace(TSanThread *thr, uintptr_t addr, MopInfo *mop, bool need_locking) {
7370     size_t size = mop->size();
7371     uintptr_t pc = mop->pc();
7372     TIL til(ts_lock, 1, need_locking);
7373     for (uintptr_t x = addr; x < addr + size; x++) {
7374       uintptr_t off = CacheLine::ComputeOffset(x);
7375       CacheLine *cache_line = G_cache->GetLineOrCreateNew(thr,
7376                                                           x, __LINE__);
7377       ShadowValue *sval_p = cache_line->GetValuePointer(off);
7378       if (cache_line->has_shadow_value().Get(off) != 0) {
7379         bool is_published = cache_line->published().Get(off);
7380         Printf("TRACE: T%d/S%d %s[%d] addr=%p sval: %s%s; line=%p P=%s\n",
7381                raw_tid(thr), thr->sid().raw(), mop->is_write() ? "wr" : "rd",
7382                size, addr, sval_p->ToString().c_str(),
7383                is_published ? " P" : "",
7384                cache_line,
7385                cache_line->published().Empty() ?
7386                "0" : cache_line->published().ToString().c_str());
7387         thr->ReportStackTrace(pc);
7388       }
7389       G_cache->ReleaseLine(thr, x, cache_line, __LINE__);
7390     }
7391   }
7392 
7393 
7394 #if TS_SERIALIZED == 1
7395   INLINE  // TODO(kcc): this can also be made NOINLINE later.
7396 #else
7397   NOINLINE
7398 #endif
HandleMemoryAccessSlowLocked(TSanThread * thr,uintptr_t addr,MopInfo * mop,bool has_expensive_flags,bool need_locking)7399   void HandleMemoryAccessSlowLocked(TSanThread *thr,
7400                                     uintptr_t addr,
7401                                     MopInfo *mop,
7402                                     bool has_expensive_flags,
7403                                     bool need_locking) {
7404     AssertTILHeld();
7405     DCHECK(thr->lsid(false) == thr->segment()->lsid(false));
7406     DCHECK(thr->lsid(true) == thr->segment()->lsid(true));
7407     thr->FlushDeadSids();
7408     if (TS_SERIALIZED == 0) {
7409       // In serialized version this is the hotspot, so grab fresh SIDs
7410       // only in non-serial variant.
7411       thr->GetSomeFreshSids();
7412     }
7413     CacheLine *cache_line = G_cache->GetLineOrCreateNew(thr, addr, __LINE__);
7414     HandleAccessGranularityAndExecuteHelper(cache_line, thr, addr,
7415                                             mop, has_expensive_flags,
7416                                             /*fast_path_only=*/false);
7417     bool tracing = IsTraced(cache_line, addr, has_expensive_flags);
7418     G_cache->ReleaseLine(thr, addr, cache_line, __LINE__);
7419     cache_line = NULL;  // just in case.
7420 
7421     if (has_expensive_flags) {
7422       if (tracing) {
7423         DoTrace(thr, addr, mop, /*need_locking=*/false);
7424       }
7425       if (G_flags->sample_events > 0) {
7426         const char *type = "SampleMemoryAccess";
7427         static EventSampler sampler;
7428         sampler.Sample(thr, type, false);
7429       }
7430     }
7431   }
7432 
HandleMemoryAccessInternal(TSanThread * thr,uintptr_t * sblock_pc,uintptr_t addr,MopInfo * mop,bool has_expensive_flags,bool need_locking)7433   INLINE bool HandleMemoryAccessInternal(TSanThread *thr,
7434                                          uintptr_t *sblock_pc,
7435                                          uintptr_t addr,
7436                                          MopInfo *mop,
7437                                          bool has_expensive_flags,
7438                                          bool need_locking) {
7439 #   define INC_STAT(stat) \
7440         do { if (has_expensive_flags) (stat)++; } while ((void)0, 0)
7441     if (TS_ATOMICITY && G_flags->atomicity) {
7442       HandleMemoryAccessForAtomicityViolationDetector(thr, addr, mop);
7443       return false;
7444     }
7445     DCHECK(mop->size() > 0);
7446     DCHECK(thr->is_running());
7447     DCHECK(!thr->ignore_reads() || !thr->ignore_writes());
7448 
7449     // We do not check and ignore stack now.
7450     // On unoptimized binaries this would give ~10% speedup if ignore_stack==true,
7451     // but if --ignore_stack==false this would cost few extra insns.
7452     // On optimized binaries ignoring stack gives nearly nothing.
7453     // if (thr->IgnoreMemoryIfInStack(addr)) return;
7454 
7455     CacheLine *cache_line = NULL;
7456     INC_STAT(thr->stats.memory_access_sizes[mop->size() <= 16 ? mop->size() : 17 ]);
7457     INC_STAT(thr->stats.events[mop->is_write() ? WRITE : READ]);
7458     if (has_expensive_flags) {
7459       thr->stats.access_to_first_1g += (addr >> 30) == 0;
7460       thr->stats.access_to_first_2g += (addr >> 31) == 0;
7461       thr->stats.access_to_first_4g += ((uint64_t)addr >> 32) == 0;
7462     }
7463 
7464     int locked_access_case = 0;
7465 
7466     if (need_locking) {
7467       // The fast (unlocked) path.
7468       if (thr->HasRoomForDeadSids()) {
7469         // Acquire a line w/o locks.
7470         cache_line = G_cache->TryAcquireLine(thr, addr, __LINE__);
7471         if (!Cache::LineIsNullOrLocked(cache_line)) {
7472           // The line is not empty or locked -- check the tag.
7473           if (cache_line->tag() == CacheLine::ComputeTag(addr)) {
7474             // The line is ours and non-empty -- fire the fast path.
7475             if (thr->HandleSblockEnter(*sblock_pc, /*allow_slow_path=*/false)) {
7476               *sblock_pc = 0;  // don't do SblockEnter any more.
7477               bool res = HandleAccessGranularityAndExecuteHelper(
7478                   cache_line, thr, addr,
7479                   mop, has_expensive_flags,
7480                   /*fast_path_only=*/true);
7481               bool traced = IsTraced(cache_line, addr, has_expensive_flags);
7482               // release the line.
7483               G_cache->ReleaseLine(thr, addr, cache_line, __LINE__);
7484               if (res && has_expensive_flags && traced) {
7485                 DoTrace(thr, addr, mop, /*need_locking=*/true);
7486               }
7487               if (res) {
7488                 INC_STAT(thr->stats.unlocked_access_ok);
7489                 // fast path succeded, we are done.
7490                 return false;
7491               } else {
7492                 locked_access_case = 1;
7493               }
7494             } else {
7495               // we were not able to handle SblockEnter.
7496               G_cache->ReleaseLine(thr, addr, cache_line, __LINE__);
7497               locked_access_case = 2;
7498             }
7499           } else {
7500             locked_access_case = 3;
7501             // The line has a wrong tag.
7502             G_cache->ReleaseLine(thr, addr, cache_line, __LINE__);
7503           }
7504         } else if (cache_line == NULL) {
7505           locked_access_case = 4;
7506           // We grabbed the cache slot but it is empty, release it.
7507           G_cache->ReleaseLine(thr, addr, cache_line, __LINE__);
7508         } else {
7509           locked_access_case = 5;
7510         }
7511       } else {
7512         locked_access_case = 6;
7513       }
7514     } else {
7515       locked_access_case = 7;
7516     }
7517 
7518     if (need_locking) {
7519       INC_STAT(thr->stats.locked_access[locked_access_case]);
7520     }
7521 
7522     // Everything below goes under a lock.
7523     TIL til(ts_lock, 2, need_locking);
7524     thr->HandleSblockEnter(*sblock_pc, /*allow_slow_path=*/true);
7525     *sblock_pc = 0;  // don't do SblockEnter any more.
7526     HandleMemoryAccessSlowLocked(thr, addr, mop,
7527                                  has_expensive_flags,
7528                                  need_locking);
7529     return true;
7530 #undef INC_STAT
7531   }
7532 
7533 
HandleMemoryAccessForAtomicityViolationDetector(TSanThread * thr,uintptr_t addr,MopInfo * mop)7534   void HandleMemoryAccessForAtomicityViolationDetector(TSanThread *thr,
7535                                                        uintptr_t addr,
7536                                                        MopInfo *mop) {
7537     CHECK(G_flags->atomicity);
7538     TID tid = thr->tid();
7539     if (thr->MemoryIsInStack(addr)) return;
7540 
7541     LSID wr_lsid = thr->lsid(0);
7542     LSID rd_lsid = thr->lsid(1);
7543     if (wr_lsid.raw() == 0 && rd_lsid.raw() == 0) {
7544       thr->increment_n_mops_since_start();
7545       return;
7546     }
7547     // uint64_t combined_lsid = wr_lsid.raw();
7548     // combined_lsid = (combined_lsid << 32) | rd_lsid.raw();
7549     // if (combined_lsid == 0) return;
7550 
7551 //    Printf("Era=%d T%d %s a=%p pc=%p in_stack=%d %s\n", g_lock_era,
7552 //           tid.raw(), is_w ? "W" : "R", addr, pc, thr->MemoryIsInStack(addr),
7553 //           PcToRtnNameAndFilePos(pc).c_str());
7554 
7555     BitSet *range_set = thr->lock_era_access_set(mop->is_write());
7556     // Printf("era %d T%d access under lock pc=%p addr=%p size=%p w=%d\n",
7557     //        g_lock_era, tid.raw(), pc, addr, size, is_w);
7558     range_set->Add(addr, addr + mop->size());
7559     // Printf("   %s\n", range_set->ToString().c_str());
7560   }
7561 
7562 
7563   // MALLOC
HandleMalloc(Event * e,bool is_mmap)7564   void HandleMalloc(Event *e, bool is_mmap) {
7565     ScopedMallocCostCenter cc("HandleMalloc");
7566     TID tid(e->tid());
7567     uintptr_t a = e->a();
7568     uintptr_t size = e->info();
7569 
7570 
7571     if (a == 0)
7572       return;
7573 
7574     #if defined(__GNUC__) && __WORDSIZE == 64
7575     // If we are allocating a huge piece of memory,
7576     // don't handle it because it is too slow.
7577     // TODO(kcc): this is a workaround for NaCl. May need to fix it cleaner.
7578     const uint64_t G84 = (1ULL << 32) * 21; // 84G.
7579     if (size >= G84) {
7580       return;
7581     }
7582     #endif
7583     TSanThread *thr = TSanThread::Get(tid);
7584     thr->NewSegmentForMallocEvent();
7585     uintptr_t b = a + size;
7586     CHECK(a <= b);
7587     ClearMemoryState(thr, a, b);
7588     // update heap_map
7589     HeapInfo info;
7590     info.ptr  = a;
7591     info.size = size;
7592     info.sid  = thr->sid();
7593     Segment::Ref(info.sid, __FUNCTION__);
7594     if (debug_malloc) {
7595       Printf("T%d MALLOC: %p [%p %p) %s %s\n%s\n",
7596              tid.raw(), size, a, a+size,
7597              Segment::ToString(thr->sid()).c_str(),
7598              thr->segment()->vts()->ToString().c_str(),
7599              info.StackTraceString().c_str());
7600     }
7601 
7602     // CHECK(!G_heap_map->count(a));  // we may have two calls
7603                                       //  to AnnotateNewMemory.
7604     G_heap_map->InsertInfo(a, info);
7605 
7606     if (is_mmap) {
7607       // Mmap may be used for thread stack, so we should keep the mmap info
7608       // when state is flushing.
7609       ThreadStackInfo ts_info;
7610       ts_info.ptr = a;
7611       ts_info.size = size;
7612       G_thread_stack_map->InsertInfo(a, ts_info);
7613     }
7614   }
7615 
ImitateWriteOnFree(TSanThread * thr,uintptr_t a,uintptr_t size,uintptr_t pc)7616   void ImitateWriteOnFree(TSanThread *thr, uintptr_t a, uintptr_t size, uintptr_t pc) {
7617     // Handle the memory deletion as a write, but don't touch all
7618     // the memory if there is too much of it, limit with the first 1K.
7619     if (size && G_flags->free_is_write && !global_ignore) {
7620       const uintptr_t kMaxWriteSizeOnFree = 2048;
7621       uintptr_t write_size = min(kMaxWriteSizeOnFree, size);
7622       uintptr_t step = sizeof(uintptr_t);
7623       // We simulate 4- or 8-byte accesses to make analysis faster.
7624       for (uintptr_t i = 0; i < write_size; i += step) {
7625         uintptr_t this_size = write_size - i >= step ? step : write_size - i;
7626         HandleMemoryAccess(thr, pc, a + i, this_size,
7627                            /*is_w=*/true, /*need_locking*/false);
7628       }
7629     }
7630   }
7631 
7632   // FREE
HandleFree(Event * e)7633   void HandleFree(Event *e) {
7634     TID tid(e->tid());
7635     TSanThread *thr = TSanThread::Get(tid);
7636     uintptr_t a = e->a();
7637     if (debug_free) {
7638       e->Print();
7639       thr->ReportStackTrace(e->pc());
7640     }
7641     if (a == 0)
7642       return;
7643     HeapInfo *info = G_heap_map->GetInfo(a);
7644     if (!info || info->ptr != a)
7645       return;
7646     uintptr_t size = info->size;
7647     uintptr_t pc = e->pc();
7648     ImitateWriteOnFree(thr, a, size, pc);
7649     // update G_heap_map
7650     CHECK(info->ptr == a);
7651     Segment::Unref(info->sid, __FUNCTION__);
7652 
7653     ClearMemoryState(thr, a, a + size);
7654     G_heap_map->EraseInfo(a);
7655 
7656     // We imitate a Write event again, in case there will be use-after-free.
7657     // We also need to create a new sblock so that the previous stack trace
7658     // has free() in it.
7659     if (G_flags->keep_history && G_flags->free_is_write) {
7660       thr->HandleSblockEnter(pc, /*allow_slow_path*/true);
7661     }
7662     ImitateWriteOnFree(thr, a, size, pc);
7663   }
7664 
HandleMunmap(Event * e)7665   void HandleMunmap(Event *e) {
7666     // TODO(glider): at the moment we handle only munmap()s of single mmap()ed
7667     // regions. The correct implementation should handle arbitrary munmap()s
7668     // that may carve the existing mappings or split them into two parts.
7669     // It should also be possible to munmap() several mappings at a time.
7670     uintptr_t a = e->a();
7671     if (a == 0)
7672       return;
7673     HeapInfo *h_info = G_heap_map->GetInfo(a);
7674     uintptr_t size = e->info();
7675     if (h_info && h_info->ptr == a && h_info->size == size) {
7676       // TODO(glider): we may want to handle memory deletion and call
7677       // Segment::Unref for all the unmapped memory.
7678       Segment::Unref(h_info->sid, __FUNCTION__);
7679       G_heap_map->EraseRange(a, a + size);
7680     }
7681 
7682     ThreadStackInfo *ts_info = G_thread_stack_map->GetInfo(a);
7683     if (ts_info && ts_info->ptr == a && ts_info->size == size)
7684       G_thread_stack_map->EraseRange(a, a + size);
7685   }
7686 
HandleThreadStart(TID child_tid,TID parent_tid,CallStack * call_stack)7687   void HandleThreadStart(TID child_tid, TID parent_tid, CallStack *call_stack) {
7688     // Printf("HandleThreadStart: tid=%d parent_tid=%d pc=%lx pid=%d\n",
7689     //         child_tid.raw(), parent_tid.raw(), pc, getpid());
7690     VTS *vts = NULL;
7691     StackTrace *creation_context = NULL;
7692     if (child_tid == TID(0)) {
7693       // main thread, we are done.
7694       vts = VTS::CreateSingleton(child_tid);
7695     } else if (!parent_tid.valid()) {
7696       TSanThread::StopIgnoringAccessesInT0BecauseNewThreadStarted();
7697       Report("INFO: creating thread T%d w/o a parent\n", child_tid.raw());
7698       vts = VTS::CreateSingleton(child_tid);
7699     } else {
7700       TSanThread::StopIgnoringAccessesInT0BecauseNewThreadStarted();
7701       TSanThread *parent = TSanThread::Get(parent_tid);
7702       CHECK(parent);
7703       parent->HandleChildThreadStart(child_tid, &vts, &creation_context);
7704     }
7705 
7706     if (!call_stack) {
7707       call_stack = new CallStack();
7708     }
7709     TSanThread *new_thread = new TSanThread(child_tid, parent_tid,
7710                                     vts, creation_context, call_stack);
7711     CHECK(new_thread == TSanThread::Get(child_tid));
7712     if (child_tid == TID(0)) {
7713       new_thread->set_ignore_all_accesses(true); // until a new thread comes.
7714     }
7715   }
7716 
7717   // Executes before the first instruction of the thread but after the thread
7718   // has been set up (e.g. the stack is in place).
HandleThreadFirstInsn(TID tid)7719   void HandleThreadFirstInsn(TID tid) {
7720     // TODO(kcc): get rid of this once we find out how to get the T0's stack.
7721     if (tid == TID(0)) {
7722       uintptr_t stack_min(0), stack_max(0);
7723       GetThreadStack(tid.raw(), &stack_min, &stack_max);
7724       TSanThread *thr = TSanThread::Get(tid);
7725       thr->SetStack(stack_min, stack_max);
7726       ClearMemoryState(thr, thr->min_sp(), thr->max_sp());
7727     }
7728   }
7729 
7730   // THR_STACK_TOP
HandleThreadStackTop(Event * e)7731   void HandleThreadStackTop(Event *e) {
7732     TID tid(e->tid());
7733     TSanThread *thr = TSanThread::Get(tid);
7734     // Stack grows from bottom up.
7735     uintptr_t sp = e->a();
7736     uintptr_t sp_min = 0, sp_max = 0;
7737     uintptr_t stack_size_if_known = e->info();
7738     ThreadStackInfo *stack_info;
7739     if (stack_size_if_known) {
7740       sp_min = sp - stack_size_if_known;
7741       sp_max = sp;
7742     } else if (NULL != (stack_info = G_thread_stack_map->GetInfo(sp))) {
7743       if (debug_thread) {
7744         Printf("T%d %s: %p\n%s\n", e->tid(), __FUNCTION__,  sp,
7745              reports_.DescribeMemory(sp).c_str());
7746       }
7747       sp_min = stack_info->ptr;
7748       sp_max = stack_info->ptr + stack_info->size;
7749     }
7750     if (debug_thread) {
7751       Printf("T%d SP: %p [%p %p), size=%ldK\n",
7752              e->tid(), sp, sp_min, sp_max, (sp_max - sp_min) >> 10);
7753     }
7754     if (sp_min < sp_max) {
7755       CHECK((sp_max - sp_min) >= 8 * 1024); // stay sane.
7756       CHECK((sp_max - sp_min) < 128 * 1024 * 1024); // stay sane.
7757       ClearMemoryState(thr, sp_min, sp_max);
7758       thr->SetStack(sp_min, sp_max);
7759     }
7760   }
7761 
7762   // THR_END
HandleThreadEnd(TID tid)7763   void HandleThreadEnd(TID tid) {
7764     TSanThread *thr = TSanThread::Get(tid);
7765     // Add the thread-local stats to global stats.
7766     G_stats->Add(thr->stats);
7767     thr->stats.Clear();
7768 
7769     // Printf("HandleThreadEnd: %d\n", tid.raw());
7770     if (tid != TID(0)) {
7771       TSanThread *child = TSanThread::Get(tid);
7772       child->HandleThreadEnd();
7773 
7774 
7775       if (debug_thread) {
7776         Printf("T%d:  THR_END     : %s %s\n", tid.raw(),
7777                Segment::ToString(child->sid()).c_str(),
7778                child->vts()->ToString().c_str());
7779       }
7780       ClearMemoryState(thr, child->min_sp(), child->max_sp());
7781     } else {
7782       reports_.SetProgramFinished();
7783     }
7784 
7785 
7786     if (g_so_far_only_one_thread == false
7787         && (thr->ignore_reads() || thr->ignore_writes())) {
7788       Report("WARNING: T%d ended while at least one 'ignore' bit is set: "
7789              "ignore_wr=%d ignore_rd=%d\n", tid.raw(),
7790              thr->ignore_reads(), thr->ignore_writes());
7791       for (int i = 0; i < 2; i++) {
7792         StackTrace *context = thr->GetLastIgnoreContext(i);
7793         if (context) {
7794           Report("Last ignore_%s call was here: \n%s\n", i ? "wr" : "rd",
7795                  context->ToString().c_str());
7796         }
7797       }
7798       if (G_flags->save_ignore_context == false) {
7799         Report("Rerun with --save_ignore_context to see where "
7800                "IGNORE_END is missing\n");
7801       }
7802     }
7803     ShowProcSelfStatus();
7804   }
7805 
7806   // THR_JOIN_AFTER
HandleThreadJoinAfter(Event * e)7807   void HandleThreadJoinAfter(Event *e) {
7808     TID tid(e->tid());
7809     TSanThread *parent_thr = TSanThread::Get(tid);
7810     VTS *vts_at_exit = NULL;
7811     TID child_tid = parent_thr->HandleThreadJoinAfter(&vts_at_exit, TID(e->a()));
7812     CHECK(vts_at_exit);
7813     CHECK(parent_thr->sid().valid());
7814     Segment::AssertLive(parent_thr->sid(),  __LINE__);
7815     parent_thr->NewSegmentForWait(vts_at_exit);
7816     if (debug_thread) {
7817       Printf("T%d:  THR_JOIN_AFTER T%d  : %s\n", tid.raw(),
7818              child_tid.raw(), parent_thr->vts()->ToString().c_str());
7819     }
7820   }
7821 
7822  public:
7823   // TODO(kcc): merge this into Detector class. (?)
7824   ReportStorage reports_;
7825 
SetUnwindCallback(ThreadSanitizerUnwindCallback cb)7826   void SetUnwindCallback(ThreadSanitizerUnwindCallback cb) {
7827     reports_.SetUnwindCallback(cb);
7828   }
7829 };
7830 
7831 static Detector        *G_detector;
7832 
7833 
HandleAtomicMop(uintptr_t a,uintptr_t pc,tsan_atomic_op op,tsan_memory_order mo,size_t size)7834 void TSanThread::HandleAtomicMop(uintptr_t a,
7835                              uintptr_t pc,
7836                              tsan_atomic_op op,
7837                              tsan_memory_order mo,
7838                              size_t size) {
7839   if (op == tsan_atomic_op_fence)
7840     return;
7841   bool const is_store = (op != tsan_atomic_op_load);
7842   CHECK(inside_atomic_op_ >= 0);
7843   if (mo != tsan_memory_order_natomic)
7844     inside_atomic_op_ += 1;
7845   MopInfo mop (pc, size, is_store, true);
7846   G_detector->HandleTrace(this, &mop, 1, pc, &a, false);
7847   if (mo != tsan_memory_order_natomic)
7848     inside_atomic_op_ -= 1;
7849   CHECK(inside_atomic_op_ >= 0);
7850 }
7851 
7852 
7853 // -------- Flags ------------------------- {{{1
7854 const char *usage_str =
7855 "Usage:\n"
7856 "  %s [options] program_to_test [program's options]\n"
7857 "See %s for details\n";
7858 
ThreadSanitizerPrintUsage()7859 void ThreadSanitizerPrintUsage() {
7860   Printf(usage_str, G_flags->tsan_program_name.c_str(),
7861          G_flags->tsan_url.c_str());
7862 }
7863 
ReportUnknownFlagAndExit(const string & str)7864 static void ReportUnknownFlagAndExit(const string &str) {
7865   Printf("Unknown flag or flag value: %s\n", str.c_str());
7866   ThreadSanitizerPrintUsage();
7867   exit(1);
7868 }
7869 
7870 // if arg and flag match, return true
7871 // and set 'val' to the substring of arg after '='.
FlagNameMatch(const string & arg,const string & flag,string * val)7872 static bool FlagNameMatch(const string &arg, const string &flag, string *val) {
7873   string f = string("--") + flag;
7874   if (arg.size() < f.size()) return false;
7875   for (size_t i = 0; i < f.size(); i++) {
7876     // '-' must match '-'
7877     // '_' may match '_' or '-'
7878     if (f[i] == '_') {
7879       if (arg[i] != '-' && arg[i] != '_') return false;
7880     } else {
7881       if (f[i] != arg[i]) return false;
7882     }
7883   }
7884   if (arg.size() == f.size()) {
7885     *val = "";
7886     return true;
7887   }
7888   if (arg[f.size()] != '=') return false;
7889   *val = arg.substr(f.size() + 1);
7890   return true;
7891 }
7892 
FindBoolFlag(const char * name,bool default_val,vector<string> * args,bool * retval)7893 static int FindBoolFlag(const char *name, bool default_val,
7894                   vector<string> *args, bool *retval) {
7895   int res = 0;
7896   *retval = default_val;
7897   bool cont = false;
7898   do {
7899     cont = false;
7900     vector<string>::iterator it = args->begin();
7901     for (; it != args->end(); ++it) {
7902       string &str = *it;
7903       string flag_value;
7904       if (!FlagNameMatch(str, name, &flag_value)) continue;
7905 
7906       if (flag_value == "")            *retval = true;
7907       else if (flag_value == "1")     *retval = true;
7908       else if (flag_value == "true")  *retval = true;
7909       else if (flag_value == "yes")   *retval = true;
7910       else if (flag_value == "0")     *retval = false;
7911       else if (flag_value == "false") *retval = false;
7912       else if (flag_value == "no")    *retval = false;
7913       else
7914         ReportUnknownFlagAndExit(str);
7915       res++;
7916       if (G_flags->verbosity >= 1) {
7917         Printf("%40s => %s\n", name, *retval ? "true" : "false");
7918       }
7919       break;
7920     }
7921     if (it != args->end()) {
7922       cont = true;
7923       args->erase(it);
7924     }
7925   } while (cont);
7926   return res;
7927 }
7928 
FindIntFlag(const char * name,intptr_t default_val,vector<string> * args,intptr_t * retval)7929 static void FindIntFlag(const char *name, intptr_t default_val,
7930                  vector<string> *args, intptr_t *retval) {
7931   *retval = default_val;
7932   bool cont = false;
7933   do {
7934     cont = false;
7935     vector<string>::iterator it = args->begin();
7936     for (; it != args->end(); ++it) {
7937       string &str = *it;
7938       string flag_value;
7939       if (!FlagNameMatch(str, name, &flag_value)) continue;
7940       char *end_ptr;
7941       const char *beg_ptr = flag_value.c_str();
7942       intptr_t int_val = my_strtol(beg_ptr, &end_ptr, 0);
7943       if (flag_value.empty() || beg_ptr + flag_value.size() != end_ptr)
7944         ReportUnknownFlagAndExit(str);
7945       *retval = int_val;
7946       if (G_flags->verbosity >= 1) {
7947         Printf("%40s => %ld\n", name, *retval);
7948       }
7949       break;
7950     }
7951     if (it != args->end()) {
7952       cont = true;
7953       args->erase(it);
7954     }
7955   } while (cont);
7956 }
7957 
FindUIntFlag(const char * name,intptr_t default_val,vector<string> * args,uintptr_t * retval)7958 static void FindUIntFlag(const char *name, intptr_t default_val,
7959                  vector<string> *args, uintptr_t *retval) {
7960   intptr_t signed_int;
7961   FindIntFlag(name, default_val, args, &signed_int);
7962   CHECK_GE(signed_int, 0);
7963   *retval = signed_int;
7964 }
7965 
FindStringFlag(const char * name,vector<string> * args,vector<string> * retval)7966 void FindStringFlag(const char *name, vector<string> *args,
7967                     vector<string> *retval) {
7968   bool cont = false;
7969   do {
7970     cont = false;
7971     vector<string>::iterator it = args->begin();
7972     for (; it != args->end(); ++it) {
7973       string &str = *it;
7974       string flag_value;
7975       if (!FlagNameMatch(str, name, &flag_value)) continue;
7976       retval->push_back(flag_value);
7977       if (G_flags->verbosity >= 1) {
7978         Printf("%40s => %s\n", name, flag_value.c_str());
7979       }
7980       break;
7981     }
7982     if (it != args->end()) {
7983       cont = true;
7984       args->erase(it);
7985     }
7986   } while (cont);
7987 }
7988 
FindStringFlag(const char * name,vector<string> * args,string * retval)7989 void FindStringFlag(const char *name, vector<string> *args,
7990                     string *retval) {
7991   vector<string> tmp;
7992   FindStringFlag(name, args, &tmp);
7993   if (tmp.size() > 0) {
7994     *retval = tmp.back();
7995   }
7996 }
7997 
GetMemoryLimitInMbFromProcSelfLimits()7998 static size_t GetMemoryLimitInMbFromProcSelfLimits() {
7999 #ifdef VGO_linux
8000   // Parse the memory limit section of /proc/self/limits.
8001   string proc_self_limits = ReadFileToString("/proc/self/limits", false);
8002   const char *max_addr_space = "Max address space";
8003   size_t pos = proc_self_limits.find(max_addr_space);
8004   if (pos == string::npos) return 0;
8005   pos += strlen(max_addr_space);
8006   while (proc_self_limits[pos] == ' ') pos++;
8007   if (proc_self_limits[pos] == 'u')
8008     return 0;  // 'unlimited'.
8009   char *end;
8010   size_t result = my_strtol(proc_self_limits.c_str() + pos, &end, 0);
8011   result >>= 20;
8012   return result;
8013 #else
8014   return 0;
8015 #endif
8016 }
8017 
GetMemoryLimitInMb()8018 static size_t GetMemoryLimitInMb() {
8019   size_t ret = -1;  // Maximum possible value.
8020 #if defined(VGO_linux) && __WORDSIZE == 32
8021   // Valgrind doesn't support more than 3G per process on 32-bit Linux.
8022   ret = 3 * 1024;
8023 #endif
8024 
8025   // Try /proc/self/limits.
8026   size_t from_proc_self = GetMemoryLimitInMbFromProcSelfLimits();
8027   if (from_proc_self && ret > from_proc_self) {
8028     ret = from_proc_self;
8029   }
8030   // Try env.
8031   const char *from_env_str =
8032     (const char*)getenv("VALGRIND_MEMORY_LIMIT_IN_MB");
8033   if (from_env_str) {
8034     char *end;
8035     size_t from_env_value = (size_t)my_strtol(from_env_str, &end, 0);
8036     if (ret > from_env_value)
8037       ret = from_env_value;
8038   }
8039   if (ret == (size_t)-1)
8040     return 0;
8041   return ret;
8042 }
8043 
PhaseDebugIsOn(const char * phase_name)8044 bool PhaseDebugIsOn(const char *phase_name) {
8045   CHECK(G_flags);
8046   for (size_t i = 0; i < G_flags->debug_phase.size(); i++) {
8047     if (G_flags->debug_phase[i] == phase_name)
8048       return true;
8049   }
8050   return false;
8051 }
8052 
ThreadSanitizerParseFlags(vector<string> * args)8053 void ThreadSanitizerParseFlags(vector<string> *args) {
8054 #ifdef TS_OFFLINE
8055   string input_type_tmp;
8056   FindStringFlag("input_type", args, &input_type_tmp);
8057   if (input_type_tmp.size() > 0) {
8058     G_flags->input_type = input_type_tmp;
8059   } else {
8060     G_flags->input_type = "str";
8061   }
8062 #endif
8063 
8064   // Check this first.
8065   FindIntFlag("v", 0, args, &G_flags->verbosity);
8066 
8067   FindBoolFlag("ignore_stack", false, args, &G_flags->ignore_stack);
8068   FindIntFlag("keep_history", 1, args, &G_flags->keep_history);
8069   FindUIntFlag("segment_set_recycle_queue_size", DEBUG_MODE ? 10 : 10000, args,
8070                &G_flags->segment_set_recycle_queue_size);
8071   FindUIntFlag("recent_segments_cache_size", 10, args,
8072                &G_flags->recent_segments_cache_size);
8073 
8074   bool fast_mode = false;
8075   FindBoolFlag("fast_mode", false, args, &fast_mode);
8076   if (fast_mode) {
8077     Printf("INFO: --fast-mode is deprecated\n");
8078   }
8079   bool ignore_in_dtor = false;
8080   FindBoolFlag("ignore_in_dtor", false, args, &ignore_in_dtor);
8081   if (ignore_in_dtor) {
8082     Printf("INFO: --ignore-in-dtor is deprecated\n");
8083   }
8084 
8085   int has_phb = FindBoolFlag("pure_happens_before", true, args,
8086                               &G_flags->pure_happens_before);
8087   bool hybrid = false;
8088   int has_hyb = FindBoolFlag("hybrid", false, args, &hybrid);
8089   if (has_hyb && has_phb) {
8090     Printf("INFO: --hybrid and --pure-happens-before"
8091            " is mutually exclusive; ignoring the --hybrid switch\n");
8092   } else if (has_hyb && !has_phb) {
8093     G_flags->pure_happens_before = !hybrid;
8094   }
8095 
8096   FindBoolFlag("show_expected_races", false, args,
8097                &G_flags->show_expected_races);
8098   FindBoolFlag("demangle", true, args, &G_flags->demangle);
8099 
8100   FindBoolFlag("announce_threads", false, args, &G_flags->announce_threads);
8101   FindBoolFlag("full_output", false, args, &G_flags->full_output);
8102   FindBoolFlag("show_states", false, args, &G_flags->show_states);
8103   FindBoolFlag("show_proc_self_status", false, args,
8104                &G_flags->show_proc_self_status);
8105   FindBoolFlag("show_valgrind_context", false, args,
8106                &G_flags->show_valgrind_context);
8107   FindBoolFlag("suggest_happens_before_arcs", true, args,
8108                &G_flags->suggest_happens_before_arcs);
8109   FindBoolFlag("show_pc", false, args, &G_flags->show_pc);
8110   FindBoolFlag("full_stack_frames", false, args, &G_flags->full_stack_frames);
8111   FindBoolFlag("free_is_write", true, args, &G_flags->free_is_write);
8112   FindBoolFlag("exit_after_main", false, args, &G_flags->exit_after_main);
8113 
8114   FindIntFlag("show_stats", 0, args, &G_flags->show_stats);
8115   FindBoolFlag("trace_profile", false, args, &G_flags->trace_profile);
8116   FindBoolFlag("color", false, args, &G_flags->color);
8117   FindBoolFlag("html", false, args, &G_flags->html);
8118 #ifdef TS_OFFLINE
8119   bool show_pid_default = false;
8120 #else
8121   bool show_pid_default = true;
8122 #endif
8123   FindBoolFlag("show_pid", show_pid_default, args, &G_flags->show_pid);
8124   FindBoolFlag("save_ignore_context", DEBUG_MODE ? true : false, args,
8125                &G_flags->save_ignore_context);
8126 
8127   FindIntFlag("dry_run", 0, args, &G_flags->dry_run);
8128   FindBoolFlag("report_races", true, args, &G_flags->report_races);
8129   FindIntFlag("locking_scheme", 1, args, &G_flags->locking_scheme);
8130   FindBoolFlag("unlock_on_mutex_destroy", true, args,
8131                &G_flags->unlock_on_mutex_destroy);
8132 
8133   FindIntFlag("sample_events", 0, args, &G_flags->sample_events);
8134   FindIntFlag("sample_events_depth", 2, args, &G_flags->sample_events_depth);
8135 
8136   FindIntFlag("debug_level", 1, args, &G_flags->debug_level);
8137   FindStringFlag("debug_phase", args, &G_flags->debug_phase);
8138   FindIntFlag("trace_level", 0, args, &G_flags->trace_level);
8139 
8140   FindIntFlag("literace_sampling", 0, args, &G_flags->literace_sampling);
8141   FindIntFlag("sampling", 0, args, &G_flags->literace_sampling);
8142   CHECK(G_flags->literace_sampling < 32);
8143   CHECK(G_flags->literace_sampling >= 0);
8144   FindBoolFlag("start_with_global_ignore_on", false, args,
8145                &G_flags->start_with_global_ignore_on);
8146 
8147   FindStringFlag("fullpath_after", args, &G_flags->file_prefix_to_cut);
8148   FindStringFlag("file_prefix_to_cut", args, &G_flags->file_prefix_to_cut);
8149   for (size_t i = 0; i < G_flags->file_prefix_to_cut.size(); i++) {
8150     G_flags->file_prefix_to_cut[i] =
8151         ConvertToPlatformIndependentPath(G_flags->file_prefix_to_cut[i]);
8152   }
8153 
8154   FindStringFlag("ignore", args, &G_flags->ignore);
8155   FindStringFlag("whitelist", args, &G_flags->whitelist);
8156   FindBoolFlag("ignore_unknown_pcs", false, args, &G_flags->ignore_unknown_pcs);
8157 
8158   FindBoolFlag("thread_coverage", false, args, &G_flags->thread_coverage);
8159 
8160   FindBoolFlag("atomicity", false, args, &G_flags->atomicity);
8161   if (G_flags->atomicity) {
8162     // When doing atomicity violation checking we should not
8163     // create h-b arcs between Unlocks and Locks.
8164     G_flags->pure_happens_before = false;
8165   }
8166 
8167   FindBoolFlag("call_coverage", false, args, &G_flags->call_coverage);
8168   FindStringFlag("dump_events", args, &G_flags->dump_events);
8169   FindBoolFlag("symbolize", true, args, &G_flags->symbolize);
8170 
8171   FindIntFlag("trace_addr", 0, args,
8172               reinterpret_cast<intptr_t*>(&G_flags->trace_addr));
8173 
8174   FindIntFlag("max_mem_in_mb", 0, args, &G_flags->max_mem_in_mb);
8175   FindBoolFlag("offline", false, args, &G_flags->offline);
8176   FindBoolFlag("attach_mode", false, args, &G_flags->attach_mode);
8177   if (G_flags->max_mem_in_mb == 0) {
8178     G_flags->max_mem_in_mb = GetMemoryLimitInMb();
8179   }
8180 
8181   vector<string> summary_file_tmp;
8182   FindStringFlag("summary_file", args, &summary_file_tmp);
8183   if (summary_file_tmp.size() > 0) {
8184     G_flags->summary_file = summary_file_tmp.back();
8185   }
8186 
8187   vector<string> log_file_tmp;
8188   FindStringFlag("log_file", args, &log_file_tmp);
8189   if (log_file_tmp.size() > 0) {
8190     G_flags->log_file = log_file_tmp.back();
8191   }
8192 
8193   G_flags->tsan_program_name = "valgrind --tool=tsan";
8194   FindStringFlag("tsan_program_name", args, &G_flags->tsan_program_name);
8195 
8196   G_flags->tsan_url = "http://code.google.com/p/data-race-test";
8197   FindStringFlag("tsan_url", args, &G_flags->tsan_url);
8198 
8199   FindStringFlag("suppressions", args, &G_flags->suppressions);
8200   FindBoolFlag("gen_suppressions", false, args,
8201                &G_flags->generate_suppressions);
8202 
8203   FindIntFlag("error_exitcode", 0, args, &G_flags->error_exitcode);
8204   FindIntFlag("flush_period", 0, args, &G_flags->flush_period);
8205   FindBoolFlag("trace_children", false, args, &G_flags->trace_children);
8206 
8207   FindIntFlag("max_sid", kMaxSID, args, &G_flags->max_sid);
8208   kMaxSID = G_flags->max_sid;
8209   if (kMaxSID <= 100000) {
8210     Printf("Error: max-sid should be at least 100000. Exiting\n");
8211     exit(1);
8212   }
8213   FindIntFlag("max_sid_before_flush", (kMaxSID * 15) / 16, args,
8214               &G_flags->max_sid_before_flush);
8215   kMaxSIDBeforeFlush = G_flags->max_sid_before_flush;
8216 
8217   FindIntFlag("num_callers_in_history", kSizeOfHistoryStackTrace, args,
8218               &G_flags->num_callers_in_history);
8219   kSizeOfHistoryStackTrace = G_flags->num_callers_in_history;
8220 
8221   // Cut stack under the following default functions.
8222   G_flags->cut_stack_below.push_back("TSanThread*ThreadBody*");
8223   G_flags->cut_stack_below.push_back("ThreadSanitizerStartThread");
8224   G_flags->cut_stack_below.push_back("start_thread");
8225   G_flags->cut_stack_below.push_back("BaseThreadInitThunk");
8226   FindStringFlag("cut_stack_below", args, &G_flags->cut_stack_below);
8227 
8228   FindIntFlag("num_callers", 16, args, &G_flags->num_callers);
8229 
8230   G_flags->max_n_threads        = 100000;
8231 
8232   if (G_flags->full_output) {
8233     G_flags->announce_threads = true;
8234     G_flags->show_pc = true;
8235     G_flags->full_stack_frames = true;
8236     G_flags->show_states = true;
8237     G_flags->file_prefix_to_cut.clear();
8238   }
8239 
8240   FindIntFlag("race_verifier_sleep_ms", 100, args,
8241       &G_flags->race_verifier_sleep_ms);
8242   FindStringFlag("race_verifier", args, &G_flags->race_verifier);
8243   FindStringFlag("race_verifier_extra", args, &G_flags->race_verifier_extra);
8244   g_race_verifier_active =
8245       !(G_flags->race_verifier.empty() && G_flags->race_verifier_extra.empty());
8246   if (g_race_verifier_active) {
8247     Printf("INFO: ThreadSanitizer running in Race Verifier mode.\n");
8248   }
8249 
8250   FindBoolFlag("nacl_untrusted", false, args, &G_flags->nacl_untrusted);
8251   FindBoolFlag("threaded_analysis", false, args, &G_flags->threaded_analysis);
8252 
8253   FindBoolFlag("sched_shake", false, args, &G_flags->sched_shake);
8254   FindBoolFlag("api_ambush", false, args, &G_flags->api_ambush);
8255 
8256   FindBoolFlag("enable_atomic", false, args, &G_flags->enable_atomic);
8257 
8258   if (!args->empty()) {
8259     ReportUnknownFlagAndExit(args->front());
8260   }
8261 
8262   debug_expected_races = PhaseDebugIsOn("expected_races");
8263   debug_benign_races = PhaseDebugIsOn("benign_races");
8264   debug_malloc = PhaseDebugIsOn("malloc");
8265   debug_free = PhaseDebugIsOn("free");
8266   debug_thread = PhaseDebugIsOn("thread");
8267   debug_ignore = PhaseDebugIsOn("ignore");
8268   debug_rtn = PhaseDebugIsOn("rtn");
8269   debug_lock = PhaseDebugIsOn("lock");
8270   debug_wrap = PhaseDebugIsOn("wrap");
8271   debug_ins = PhaseDebugIsOn("ins");
8272   debug_shadow_stack = PhaseDebugIsOn("shadow_stack");
8273   debug_happens_before = PhaseDebugIsOn("happens_before");
8274   debug_cache = PhaseDebugIsOn("cache");
8275   debug_race_verifier = PhaseDebugIsOn("race_verifier");
8276   debug_atomic = PhaseDebugIsOn("atomic");
8277 }
8278 
8279 // -------- ThreadSanitizer ------------------ {{{1
8280 
8281 // Setup the list of functions/images/files to ignore.
SetupIgnore()8282 static void SetupIgnore() {
8283   g_ignore_lists = new IgnoreLists;
8284   g_white_lists = new IgnoreLists;
8285 
8286   // Add some major ignore entries so that tsan remains sane
8287   // even w/o any ignore file. First - for all platforms.
8288   g_ignore_lists->ignores.push_back(IgnoreFun("ThreadSanitizerStartThread"));
8289   g_ignore_lists->ignores.push_back(IgnoreFun("exit"));
8290   g_ignore_lists->ignores.push_back(IgnoreFun("longjmp"));
8291 
8292   // Dangerous: recursively ignoring vfprintf hides races on printf arguments.
8293   // See PrintfTests in unittest/racecheck_unittest.cc
8294   // TODO(eugenis): Do something about this.
8295   // http://code.google.com/p/data-race-test/issues/detail?id=53
8296   g_ignore_lists->ignores_r.push_back(IgnoreFun("vfprintf"));
8297 
8298   // do not create segments in our Replace_* functions
8299   g_ignore_lists->ignores_hist.push_back(IgnoreFun("Replace_memcpy"));
8300   g_ignore_lists->ignores_hist.push_back(IgnoreFun("Replace_memchr"));
8301   g_ignore_lists->ignores_hist.push_back(IgnoreFun("Replace_strcpy"));
8302   g_ignore_lists->ignores_hist.push_back(IgnoreFun("Replace_strchr"));
8303   g_ignore_lists->ignores_hist.push_back(IgnoreFun("Replace_strchrnul"));
8304   g_ignore_lists->ignores_hist.push_back(IgnoreFun("Replace_strrchr"));
8305   g_ignore_lists->ignores_hist.push_back(IgnoreFun("Replace_strlen"));
8306   g_ignore_lists->ignores_hist.push_back(IgnoreFun("Replace_strcmp"));
8307 
8308   // Ignore everything in our own file.
8309   g_ignore_lists->ignores.push_back(IgnoreFile("*ts_valgrind_intercepts.c"));
8310 
8311 #ifndef _MSC_VER
8312   // POSIX ignores
8313   g_ignore_lists->ignores.push_back(IgnoreObj("*/libpthread*"));
8314   g_ignore_lists->ignores.push_back(IgnoreObj("*/ld-2*.so"));
8315   g_ignore_lists->ignores.push_back(IgnoreFun("pthread_create"));
8316   g_ignore_lists->ignores.push_back(IgnoreFun("pthread_create@*"));
8317   g_ignore_lists->ignores.push_back(IgnoreFun("pthread_create_WRK"));
8318   g_ignore_lists->ignores.push_back(IgnoreFun("__cxa_*"));
8319   g_ignore_lists->ignores.push_back(
8320       IgnoreFun("*__gnu_cxx*__exchange_and_add*"));
8321   g_ignore_lists->ignores.push_back(IgnoreFun("__lll_mutex_*"));
8322   g_ignore_lists->ignores.push_back(IgnoreFun("__lll_*lock_*"));
8323   g_ignore_lists->ignores.push_back(IgnoreFun("__fprintf_chk"));
8324   g_ignore_lists->ignores.push_back(IgnoreFun("_IO_file_xsputn*"));
8325   // fflush internals
8326   g_ignore_lists->ignores.push_back(IgnoreFun("_IO_adjust_column"));
8327   g_ignore_lists->ignores.push_back(IgnoreFun("_IO_flush_all_lockp"));
8328 
8329   g_ignore_lists->ignores.push_back(IgnoreFun("__sigsetjmp"));
8330   g_ignore_lists->ignores.push_back(IgnoreFun("__sigjmp_save"));
8331   g_ignore_lists->ignores.push_back(IgnoreFun("_setjmp"));
8332   g_ignore_lists->ignores.push_back(IgnoreFun("_longjmp_unwind"));
8333 
8334   g_ignore_lists->ignores.push_back(IgnoreFun("__mktime_internal"));
8335 
8336   // http://code.google.com/p/data-race-test/issues/detail?id=40
8337   g_ignore_lists->ignores_r.push_back(IgnoreFun("_ZNSsD1Ev"));
8338 
8339   g_ignore_lists->ignores_r.push_back(IgnoreFun("gaih_inet"));
8340   g_ignore_lists->ignores_r.push_back(IgnoreFun("getaddrinfo"));
8341   g_ignore_lists->ignores_r.push_back(IgnoreFun("gethostbyname2_r"));
8342 
8343   #ifdef VGO_darwin
8344     // Mac-only ignores
8345     g_ignore_lists->ignores.push_back(IgnoreObj("/usr/lib/dyld"));
8346     g_ignore_lists->ignores.push_back(IgnoreObj("/usr/lib/libobjc.A.dylib"));
8347     g_ignore_lists->ignores.push_back(IgnoreObj("*/libSystem.*.dylib"));
8348     g_ignore_lists->ignores_r.push_back(IgnoreFun("__CFDoExternRefOperation"));
8349     g_ignore_lists->ignores_r.push_back(IgnoreFun("_CFAutoreleasePoolPop"));
8350     g_ignore_lists->ignores_r.push_back(IgnoreFun("_CFAutoreleasePoolPush"));
8351     g_ignore_lists->ignores_r.push_back(IgnoreFun("OSAtomicAdd32"));
8352     g_ignore_lists->ignores_r.push_back(IgnoreTriple("_dispatch_Block_copy",
8353                                             "/usr/lib/libSystem.B.dylib", "*"));
8354 
8355     // pthread_lib_{enter,exit} shouldn't give us any reports since they
8356     // have IGNORE_ALL_ACCESSES_BEGIN/END but they do give the reports...
8357     g_ignore_lists->ignores_r.push_back(IgnoreFun("pthread_lib_enter"));
8358     g_ignore_lists->ignores_r.push_back(IgnoreFun("pthread_lib_exit"));
8359   #endif
8360 #else
8361   // Windows-only ignores
8362   g_ignore_lists->ignores.push_back(IgnoreObj("*ole32.dll"));
8363   g_ignore_lists->ignores.push_back(IgnoreObj("*OLEAUT32.dll"));
8364   g_ignore_lists->ignores.push_back(IgnoreObj("*MSCTF.dll"));
8365   g_ignore_lists->ignores.push_back(IgnoreObj("*ntdll.dll"));
8366   g_ignore_lists->ignores.push_back(IgnoreObj("*mswsock.dll"));
8367   g_ignore_lists->ignores.push_back(IgnoreObj("*WS2_32.dll"));
8368   g_ignore_lists->ignores.push_back(IgnoreObj("*msvcrt.dll"));
8369   g_ignore_lists->ignores.push_back(IgnoreObj("*kernel32.dll"));
8370   g_ignore_lists->ignores.push_back(IgnoreObj("*ADVAPI32.DLL"));
8371 
8372   g_ignore_lists->ignores.push_back(IgnoreFun("_EH_epilog3"));
8373   g_ignore_lists->ignores.push_back(IgnoreFun("_EH_prolog3_catch"));
8374   g_ignore_lists->ignores.push_back(IgnoreFun("unnamedImageEntryPoint"));
8375   g_ignore_lists->ignores.push_back(IgnoreFun("_Mtxunlock"));
8376   g_ignore_lists->ignores.push_back(IgnoreFun("IsNLSDefinedString"));
8377 
8378   g_ignore_lists->ignores_r.push_back(IgnoreFun("RtlDestroyQueryDebugBuffer"));
8379   g_ignore_lists->ignores_r.push_back(IgnoreFun("BCryptGenerateSymmetricKey"));
8380   g_ignore_lists->ignores_r.push_back(IgnoreFun("SHGetItemFromDataObject"));
8381 
8382   // http://code.google.com/p/data-race-test/issues/detail?id=53
8383   g_ignore_lists->ignores_r.push_back(IgnoreFun("_stbuf"));
8384   g_ignore_lists->ignores_r.push_back(IgnoreFun("_getptd"));
8385 
8386   // TODO(timurrrr): Add support for FLS (fiber-local-storage)
8387   // http://code.google.com/p/data-race-test/issues/detail?id=55
8388   g_ignore_lists->ignores_r.push_back(IgnoreFun("_freefls"));
8389 #endif
8390 
8391 #ifdef ANDROID
8392   // Android does not have a libpthread; pthread_* functions live in libc.
8393   // We have to ignore them one-by-one.
8394   g_ignore_lists->ignores.push_back(IgnoreFun("pthread_*"));
8395   g_ignore_lists->ignores.push_back(IgnoreFun("__init_tls"));
8396 #endif
8397 
8398   // Now read the ignore/whitelist files.
8399   for (size_t i = 0; i < G_flags->ignore.size(); i++) {
8400     string file_name = G_flags->ignore[i];
8401     Report("INFO: Reading ignore file: %s\n", file_name.c_str());
8402     string str = ReadFileToString(file_name, true);
8403     ReadIgnoresFromString(str, g_ignore_lists);
8404   }
8405   for (size_t i = 0; i < G_flags->whitelist.size(); i++) {
8406     string file_name = G_flags->whitelist[i];
8407     Report("INFO: Reading whitelist file: %s\n", file_name.c_str());
8408     string str = ReadFileToString(file_name, true);
8409     ReadIgnoresFromString(str, g_white_lists);
8410   }
8411 }
8412 
ThreadSanitizerSetUnwindCallback(ThreadSanitizerUnwindCallback cb)8413 void ThreadSanitizerSetUnwindCallback(ThreadSanitizerUnwindCallback cb) {
8414   G_detector->SetUnwindCallback(cb);
8415 }
8416 
ThreadSanitizerNaclUntrustedRegion(uintptr_t mem_start,uintptr_t mem_end)8417 void ThreadSanitizerNaclUntrustedRegion(uintptr_t mem_start, uintptr_t mem_end) {
8418   g_nacl_mem_start = mem_start;
8419   g_nacl_mem_end = mem_end;
8420 }
8421 
AddrIsInNaclUntrustedRegion(uintptr_t addr)8422 bool AddrIsInNaclUntrustedRegion(uintptr_t addr) {
8423   return addr >= g_nacl_mem_start && addr < g_nacl_mem_end;
8424 }
8425 
ThreadSanitizerIgnoreForNacl(uintptr_t addr)8426 bool ThreadSanitizerIgnoreForNacl(uintptr_t addr) {
8427   // Ignore trusted addresses if tracing untrusted code, and ignore untrusted
8428   // addresses otherwise.
8429   return G_flags->nacl_untrusted != AddrIsInNaclUntrustedRegion(addr);
8430 }
8431 
ThreadSanitizerWantToInstrumentSblock(uintptr_t pc)8432 bool ThreadSanitizerWantToInstrumentSblock(uintptr_t pc) {
8433   string img_name, rtn_name, file_name;
8434   int line_no;
8435   G_stats->pc_to_strings++;
8436   PcToStrings(pc, false, &img_name, &rtn_name, &file_name, &line_no);
8437 
8438   if (g_white_lists->ignores.size() > 0) {
8439     bool in_white_list = TripleVectorMatchKnown(g_white_lists->ignores,
8440                                                 rtn_name, img_name, file_name);
8441     if (in_white_list) {
8442       if (debug_ignore) {
8443         Report("INFO: Whitelisted rtn: %s\n", rtn_name.c_str());
8444       }
8445     } else {
8446       return false;
8447     }
8448   }
8449 
8450   if (G_flags->ignore_unknown_pcs && rtn_name == "(no symbols)") {
8451     if (debug_ignore) {
8452       Report("INFO: not instrumenting unknown function at %p\n", pc);
8453     }
8454     return false;
8455   }
8456 
8457   bool ignore = TripleVectorMatchKnown(g_ignore_lists->ignores,
8458                                        rtn_name, img_name, file_name) ||
8459                 TripleVectorMatchKnown(g_ignore_lists->ignores_r,
8460                                        rtn_name, img_name, file_name);
8461   if (debug_ignore) {
8462     Printf("%s: pc=%p file_name=%s img_name=%s rtn_name=%s ret=%d\n",
8463            __FUNCTION__, pc, file_name.c_str(), img_name.c_str(),
8464            rtn_name.c_str(), !ignore);
8465   }
8466   bool nacl_ignore = ThreadSanitizerIgnoreForNacl(pc);
8467   return !(ignore || nacl_ignore);
8468 }
8469 
ThreadSanitizerWantToCreateSegmentsOnSblockEntry(uintptr_t pc)8470 bool ThreadSanitizerWantToCreateSegmentsOnSblockEntry(uintptr_t pc) {
8471   string rtn_name;
8472   rtn_name = PcToRtnName(pc, false);
8473   if (G_flags->keep_history == 0)
8474     return false;
8475   return !(TripleVectorMatchKnown(g_ignore_lists->ignores_hist,
8476                                   rtn_name, "", ""));
8477 }
8478 
8479 // Returns true if function at "pc" is marked as "fun_r" in the ignore file.
ThreadSanitizerIgnoreAccessesBelowFunction(uintptr_t pc)8480 bool NOINLINE ThreadSanitizerIgnoreAccessesBelowFunction(uintptr_t pc) {
8481   ScopedMallocCostCenter cc(__FUNCTION__);
8482   typedef unordered_map<uintptr_t, bool> Cache;
8483   static Cache *cache = NULL;
8484   {
8485     TIL ignore_below_lock(ts_ignore_below_lock, 18);
8486     if (!cache)
8487       cache = new Cache;
8488 
8489     // Fast path - check if we already know the answer.
8490     Cache::iterator i = cache->find(pc);
8491     if (i != cache->end())
8492       return i->second;
8493   }
8494 
8495   string rtn_name = PcToRtnName(pc, false);
8496   bool ret =
8497       TripleVectorMatchKnown(g_ignore_lists->ignores_r, rtn_name, "", "");
8498 
8499   if (DEBUG_MODE) {
8500     // Heavy test for NormalizeFunctionName: test on all possible inputs in
8501     // debug mode. TODO(timurrrr): Remove when tested.
8502     NormalizeFunctionName(PcToRtnName(pc, true));
8503   }
8504 
8505   // Grab the lock again
8506   TIL ignore_below_lock(ts_ignore_below_lock, 19);
8507   if (ret && debug_ignore) {
8508     Report("INFO: ignoring all accesses below the function '%s' (%p)\n",
8509            PcToRtnNameAndFilePos(pc).c_str(), pc);
8510   }
8511   return ((*cache)[pc] = ret);
8512 }
8513 
8514 // We intercept a user function with this name
8515 // and answer the user query with a non-NULL string.
ThreadSanitizerQuery(const char * query)8516 extern "C" const char *ThreadSanitizerQuery(const char *query) {
8517   const char *ret = "0";
8518   string str(query);
8519   if (str == "pure_happens_before" && G_flags->pure_happens_before == true) {
8520     ret = "1";
8521   }
8522   if (str == "hybrid_full" &&
8523       G_flags->pure_happens_before == false) {
8524     ret = "1";
8525   }
8526   if (str == "race_verifier" && g_race_verifier_active == true) {
8527     ret = "1";
8528   }
8529   if (DEBUG_MODE && G_flags->debug_level >= 2) {
8530     Printf("ThreadSanitizerQuery(\"%s\") = \"%s\"\n", query, ret);
8531   }
8532   if (str == "trace-level=0") {
8533     Report("INFO: trace-level=0\n");
8534     G_flags->trace_level = 0;
8535     debug_happens_before = false;
8536   }
8537   if (str == "trace-level=1") {
8538     Report("INFO: trace-level=1\n");
8539     G_flags->trace_level = 1;
8540     debug_happens_before = true;
8541   }
8542   return ret;
8543 }
8544 
ThreadSanitizerInit()8545 extern void ThreadSanitizerInit() {
8546   ScopedMallocCostCenter cc("ThreadSanitizerInit");
8547   ts_lock = new TSLock;
8548   ts_ignore_below_lock = new TSLock;
8549   g_so_far_only_one_thread = true;
8550   ANNOTATE_BENIGN_RACE(&g_so_far_only_one_thread, "real benign race");
8551   CHECK_EQ(sizeof(ShadowValue), 8);
8552   CHECK(G_flags);
8553   G_stats        = new Stats;
8554   SetupIgnore();
8555 
8556   G_detector     = new Detector;
8557   G_cache        = new Cache;
8558   G_expected_races_map = new ExpectedRacesMap;
8559   G_heap_map           = new HeapMap<HeapInfo>;
8560   G_thread_stack_map   = new HeapMap<ThreadStackInfo>;
8561   {
8562     ScopedMallocCostCenter cc1("Segment::InitClassMembers");
8563     Segment::InitClassMembers();
8564   }
8565   SegmentSet::InitClassMembers();
8566   CacheLine::InitClassMembers();
8567   TSanThread::InitClassMembers();
8568   Lock::InitClassMembers();
8569   LockSet::InitClassMembers();
8570   EventSampler::InitClassMembers();
8571   VTS::InitClassMembers();
8572   // TODO(timurrrr): make sure *::InitClassMembers() are called only once for
8573   // each class
8574   g_publish_info_map = new PublishInfoMap;
8575   g_stack_trace_free_list = new StackTraceFreeList;
8576   g_pcq_map = new PCQMap;
8577   g_atomicCore = new TsanAtomicCore();
8578 
8579 
8580   if (G_flags->html) {
8581     c_bold    = "<font ><b>";
8582     c_red     = "<font color=red><b>";
8583     c_green   = "<font color=green><b>";
8584     c_magenta = "<font color=magenta><b>";
8585     c_cyan    = "<font color=cyan><b>";
8586     c_blue   = "<font color=blue><b>";
8587     c_yellow  = "<font color=yellow><b>";
8588     c_default = "</b></font>";
8589   } else if (G_flags->color) {
8590     // Enable ANSI colors.
8591     c_bold    = "\033[1m";
8592     c_red     = "\033[31m";
8593     c_green   = "\033[32m";
8594     c_yellow  = "\033[33m";
8595     c_blue    = "\033[34m";
8596     c_magenta = "\033[35m";
8597     c_cyan    = "\033[36m";
8598     c_default = "\033[0m";
8599   }
8600 
8601   if (G_flags->verbosity >= 1) {
8602     Report("INFO: Started pid %d\n",  getpid());
8603   }
8604   if (G_flags->start_with_global_ignore_on) {
8605     global_ignore = true;
8606     Report("INFO: STARTING WITH GLOBAL IGNORE ON\n");
8607   }
8608   ANNOTATE_BENIGN_RACE(&g_lock_era,
8609                        "g_lock_era may be incremented in a racey way");
8610 }
8611 
ThreadSanitizerFini()8612 extern void ThreadSanitizerFini() {
8613   G_detector->HandleProgramEnd();
8614 }
8615 
ThreadSanitizerDumpAllStacks()8616 extern void ThreadSanitizerDumpAllStacks() {
8617   // first, print running threads.
8618   for (int i = 0; i < TSanThread::NumberOfThreads(); i++) {
8619     TSanThread *t = TSanThread::Get(TID(i));
8620     if (!t || !t->is_running()) continue;
8621     Report("T%d\n", i);
8622     t->ReportStackTrace();
8623   }
8624   // now print all dead threds.
8625   for (int i = 0; i < TSanThread::NumberOfThreads(); i++) {
8626     TSanThread *t = TSanThread::Get(TID(i));
8627     if (!t || t->is_running()) continue;
8628     Report("T%d (not running)\n", i);
8629     t->ReportStackTrace();
8630   }
8631 }
8632 
8633 
ThreadSanitizerHandleOneEvent(Event * e)8634 extern void ThreadSanitizerHandleOneEvent(Event *e) {
8635   // Lock is inside on some paths.
8636   G_detector->HandleOneEvent(e);
8637 }
8638 
ThreadSanitizerGetThreadByTid(int32_t tid)8639 TSanThread *ThreadSanitizerGetThreadByTid(int32_t tid) {
8640   return TSanThread::Get(TID(tid));
8641 }
8642 
ThreadSanitizerHandleTrace(int32_t tid,TraceInfo * trace_info,uintptr_t * tleb)8643 extern NOINLINE void ThreadSanitizerHandleTrace(int32_t tid, TraceInfo *trace_info,
8644                                        uintptr_t *tleb) {
8645   ThreadSanitizerHandleTrace(TSanThread::Get(TID(tid)), trace_info, tleb);
8646 }
ThreadSanitizerHandleTrace(TSanThread * thr,TraceInfo * trace_info,uintptr_t * tleb)8647 extern NOINLINE void ThreadSanitizerHandleTrace(TSanThread *thr, TraceInfo *trace_info,
8648                                                 uintptr_t *tleb) {
8649   DCHECK(thr);
8650   // The lock is taken inside on the slow path.
8651   G_detector->HandleTrace(thr,
8652                           trace_info->mops(),
8653                           trace_info->n_mops(),
8654                           trace_info->pc(),
8655                           tleb, /*need_locking=*/true);
8656 }
8657 
ThreadSanitizerHandleOneMemoryAccess(TSanThread * thr,MopInfo mop,uintptr_t addr)8658 extern NOINLINE void ThreadSanitizerHandleOneMemoryAccess(TSanThread *thr,
8659                                                           MopInfo mop,
8660                                                           uintptr_t addr) {
8661   DCHECK(thr);
8662   G_detector->HandleTrace(thr,
8663                           &mop,
8664                           1,
8665                           mop.create_sblock() ? mop.pc() : 0,
8666                           &addr, /*need_locking=*/true);
8667 }
8668 
ThreadSanitizerHandleRtnCall(int32_t tid,uintptr_t call_pc,uintptr_t target_pc,IGNORE_BELOW_RTN ignore_below)8669 void NOINLINE ThreadSanitizerHandleRtnCall(int32_t tid, uintptr_t call_pc,
8670                                          uintptr_t target_pc,
8671                                          IGNORE_BELOW_RTN ignore_below) {
8672   // This does locking on a cold path. Hot path in thread-local.
8673   G_detector->HandleRtnCall(TID(tid), call_pc, target_pc, ignore_below);
8674 
8675   if (G_flags->sample_events) {
8676     static EventSampler sampler;
8677     TSanThread *thr = TSanThread::Get(TID(tid));
8678     sampler.Sample(thr, "RTN_CALL", true);
8679   }
8680 }
ThreadSanitizerHandleRtnExit(int32_t tid)8681 void NOINLINE ThreadSanitizerHandleRtnExit(int32_t tid) {
8682   // This is a thread-local operation, no need for locking.
8683   TSanThread::Get(TID(tid))->HandleRtnExit();
8684 }
8685 
ThreadSanitizerPrintReport(ThreadSanitizerReport * report)8686 static bool ThreadSanitizerPrintReport(ThreadSanitizerReport *report) {
8687   return G_detector->reports_.PrintReport(report);
8688 }
8689 
8690 
8691 // -------- TsanAtomicImplementation ------------------ {{{1
8692 
8693 // Atomic operation handler.
8694 // The idea of atomic handling is as simple as follows.
8695 // * First, we handle it as normal memory access,
8696 //     however with race reporting suppressed. That is, we won't produce any
8697 //     race reports during atomic access, but we can produce race reports
8698 //     later during normal memory accesses that race with the access.
8699 // * Then, we do the actual atomic memory access.
8700 //     It's executed in an atomic fashion, because there can be simultaneous
8701 //     atomic accesses from non-instrumented code (FUTEX_OP is a notable
8702 //     example).
8703 // * Finally, we update simulated memory model state according to
8704 //     the access type and associated memory order as follows.
8705 //     For writes and RMWs we create a new entry in the modification order
8706 //     of the variable. For reads we scan the modification order starting
8707 //     from the latest entry and going back in time, during the scan we decide
8708 //     what entry the read returns. A separate VTS (happens-before edges)
8709 //     is associated with each entry in the modification order, so that a load
8710 //     acquires memory visibility from the exact release-sequence associated
8711 //     with the loaded value.
8712 // For details of memory modelling refer to sections 1.10 and 29
8713 //     of C++0x standard:
8714 // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3242.pdf
ThreadSanitizerHandleAtomicOp(int32_t tid,uintptr_t pc,tsan_atomic_op op,tsan_memory_order mo,tsan_memory_order fail_mo,size_t size,void volatile * a,uint64_t v,uint64_t cmp)8715 uint64_t ThreadSanitizerHandleAtomicOp(int32_t tid,
8716                                        uintptr_t pc,
8717                                        tsan_atomic_op op,
8718                                        tsan_memory_order mo,
8719                                        tsan_memory_order fail_mo,
8720                                        size_t size,
8721                                        void volatile* a,
8722                                        uint64_t v,
8723                                        uint64_t cmp) {
8724   if (G_flags->enable_atomic == false) {
8725     uint64_t newv = 0;
8726     uint64_t prev = 0;
8727     return tsan_atomic_do_op(op, mo, fail_mo, size, a, v, cmp, &newv, &prev);
8728   } else {
8729     uint64_t rv = 0;
8730     TSanThread* thr = TSanThread::Get(TID(tid));
8731     // Just a verification of the parameters.
8732     tsan_atomic_verify(op, mo, fail_mo, size, a);
8733 
8734     {
8735       TIL til(ts_lock, 0);
8736       uint64_t newv = 0;
8737       uint64_t prev = 0;
8738       // Handle it as a plain mop. Race reports are temporally suppressed,though.
8739       thr->HandleAtomicMop((uintptr_t)a, pc, op, mo, size);
8740       // Do the actual atomic operation. It's executed in an atomic fashion,
8741       // because there can be simultaneous atomic accesses
8742       // from non-instrumented code.
8743       rv = tsan_atomic_do_op(op, mo, fail_mo, size, a, v, cmp, &newv, &prev);
8744 
8745       PrintfIf(debug_atomic, "rv=%llu, newv=%llu, prev=%llu\n",
8746                (unsigned long long)rv,
8747                (unsigned long long)newv,
8748                (unsigned long long)prev);
8749 
8750       if (op != tsan_atomic_op_fence) {
8751         if (op == tsan_atomic_op_load) {
8752           // For reads it replaces the return value with a random value
8753           // from visible sequence of side-effects in the modification order
8754           // of the variable.
8755           rv = g_atomicCore->HandleRead(thr, (uintptr_t)a, rv,
8756                                         tsan_atomic_is_acquire(mo));
8757         } else if ((op == tsan_atomic_op_compare_exchange_weak
8758             || op == tsan_atomic_op_compare_exchange_strong)
8759             && cmp != rv) {
8760           // Failed compare_exchange is handled as read, because, well,
8761           // it's indeed just a read (at least logically).
8762           g_atomicCore->HandleRead(thr, (uintptr_t)a, rv,
8763                                    tsan_atomic_is_acquire(fail_mo));
8764         } else {
8765           // For writes and RMW operations it updates modification order
8766           // of the atomic variable.
8767           g_atomicCore->HandleWrite(thr, (uintptr_t)a, newv, prev,
8768                                     tsan_atomic_is_acquire(mo),
8769                                     tsan_atomic_is_release(mo),
8770                                     tsan_atomic_is_rmw(op));
8771         }
8772       }
8773     }
8774 
8775     PrintfIf(debug_atomic, "ATOMIC: %s-%s %p (%llu,%llu)=%llu\n",
8776              tsan_atomic_to_str(op),
8777              tsan_atomic_to_str(mo),
8778              a, (unsigned long long)v, (unsigned long long)cmp,
8779              (unsigned long long)rv);
8780 
8781     return rv;
8782   }
8783 }
8784 
8785 
TsanAtomicCore()8786 TsanAtomicCore::TsanAtomicCore() {
8787 }
8788 
8789 
HandleWrite(TSanThread * thr,uintptr_t a,uint64_t v,uint64_t prev,bool const is_acquire,bool const is_release,bool const is_rmw)8790 void TsanAtomicCore::HandleWrite(TSanThread* thr,
8791                                  uintptr_t a,
8792                                  uint64_t v,
8793                                  uint64_t prev,
8794                                  bool const is_acquire,
8795                                  bool const is_release,
8796                                  bool const is_rmw) {
8797   PrintfIf(debug_atomic, "HIST(%p): store acquire=%u, release=%u, rmw=%u\n",
8798            (void*)a, is_acquire, is_release, is_rmw);
8799   Atomic* atomic = &atomic_map_[a];
8800   // Fix modification history if there were untracked accesses.
8801   AtomicFixHist(atomic, prev);
8802   AtomicHistoryEntry& hprv = atomic->hist
8803       [(atomic->hist_pos - 1) % Atomic::kHistSize];
8804   AtomicHistoryEntry& hist = atomic->hist
8805       [atomic->hist_pos % Atomic::kHistSize];
8806   // Fill in new entry in the modification history.
8807   hist.val = v;
8808   hist.tid = thr->tid();
8809   hist.clk = thr->vts()->clk(thr->tid());
8810   if (hist.vts != 0) {
8811     VTS::Unref(hist.vts);
8812     hist.vts = 0;
8813   }
8814   atomic->hist_pos += 1;
8815 
8816   // Update VTS according to memory access type and memory ordering.
8817   if (is_rmw) {
8818     if (is_release) {
8819       if (hprv.vts != 0) {
8820         hist.vts = VTS::Join(hprv.vts, thr->vts());
8821       } else {
8822         hist.vts = thr->vts()->Clone();
8823       }
8824     } else if (hprv.vts != 0) {
8825       hist.vts = hprv.vts->Clone();
8826     }
8827     if (is_acquire && hprv.vts != 0) {
8828       thr->NewSegmentForWait(hprv.vts);
8829     }
8830   } else {
8831     DCHECK(is_acquire == false);
8832     if (is_release) {
8833       hist.vts = thr->vts()->Clone();
8834     }
8835   }
8836 
8837   // Update the thread's VTS if it's relese memory access.
8838   if (is_release) {
8839     thr->NewSegmentForSignal();
8840     if (debug_happens_before) {
8841       Printf("T%d: Signal: %p:\n    %s %s\n    %s\n",
8842              thr->tid().raw(), a,
8843              thr->vts()->ToString().c_str(),
8844              Segment::ToString(thr->sid()).c_str(),
8845              hist.vts->ToString().c_str());
8846       if (G_flags->debug_level >= 1) {
8847         thr->ReportStackTrace();
8848       }
8849     }
8850   }
8851 }
8852 
8853 
HandleRead(TSanThread * thr,uintptr_t a,uint64_t v,bool is_acquire)8854 uint64_t TsanAtomicCore::HandleRead(TSanThread* thr,
8855                                     uintptr_t a,
8856                                     uint64_t v,
8857                                     bool is_acquire) {
8858   PrintfIf(debug_atomic, "HIST(%p): {\n", (void*)a);
8859 
8860   Atomic* atomic = &atomic_map_[a];
8861   // Fix modification history if there were untracked accesses.
8862   AtomicFixHist(atomic, v);
8863   AtomicHistoryEntry* hist0 = 0;
8864   int32_t seen_seq = 0;
8865   int32_t const seen_seq0 = atomic->last_seen.clock(thr->tid());
8866   // Scan modification order of the variable from the latest entry
8867   // back in time. For each side-effect (write) we determine as to
8868   // whether we have to yield the value or we can go back in time further.
8869   for (int32_t i = 0; i != Atomic::kHistSize; i += 1) {
8870     int32_t const idx = (atomic->hist_pos - i - 1);
8871     CHECK(idx >= 0);
8872     AtomicHistoryEntry& hist = atomic->hist[idx % Atomic::kHistSize];
8873     PrintfIf(debug_atomic, "HIST(%p):   #%u (tid=%u, clk=%u,"
8874            " val=%llu) vts=%u\n",
8875            (void*)a, (unsigned)i, (unsigned)hist.tid.raw(),
8876            (unsigned)hist.clk, (unsigned long long)hist.val,
8877            (unsigned)thr->vts()->clk(hist.tid));
8878     if (hist.tid.raw() == TID::kInvalidTID) {
8879       // We hit an uninialized entry, that is, it's an access to an unitialized
8880       // variable (potentially due to "race").
8881       // Unfortunately, it should not happen as of now.
8882       // TODO(dvyukov): how can we detect and report unitialized atomic reads?.
8883       // .
8884       hist0 = 0;
8885       break;
8886     } else if (i == Atomic::kHistSize - 1) {
8887       // It's the last entry so we have to return it
8888       // because we have to return something.
8889       PrintfIf(debug_atomic, "HIST(%p):   replaced: last\n", (void*)a);
8890       hist0 = &hist;
8891       break;
8892     } else if (seen_seq0 >= idx) {
8893       // The thread had already seen the entry so we have to return
8894       // at least it.
8895       PrintfIf(debug_atomic, "HIST(%p):   replaced: stability\n", (void*)a);
8896       hist0 = &hist;
8897       break;
8898     } else if (thr->vts()->clk(hist.tid) >= hist.clk) {
8899       // The write happened-before the read, so we have to return it.
8900       PrintfIf(debug_atomic, "HIST(%p):   replaced: ordering\n", (void*)a);
8901       hist0 = &hist;
8902       break;
8903     } else if (thr->random() % 2) {
8904       // We are not obliged to return the entry but we can (and decided to do).
8905       PrintfIf(debug_atomic, "HIST(%p):   replaced: coherence\n", (void*)a);
8906       seen_seq = idx;
8907       hist0 = &hist;
8908       break;
8909     } else {
8910       // Move on to the next (older) entry.
8911       PrintfIf(debug_atomic, "HIST(%p):   can be replaced but not\n", (void*)a);
8912     }
8913   }
8914 
8915   if (hist0 != 0) {
8916     v = hist0->val;
8917     // Acquire mamory visibility is needed.
8918     if (is_acquire) {
8919       if (hist0->vts != 0) {
8920         thr->NewSegmentForWait(hist0->vts);
8921       }
8922 
8923       if (debug_happens_before) {
8924         Printf("T%d: Wait: %p:\n    %s %s\n",
8925                thr->tid().raw(), a,
8926                thr->vts()->ToString().c_str(),
8927                Segment::ToString(thr->sid()).c_str());
8928         if (G_flags->debug_level >= 1) {
8929           thr->ReportStackTrace();
8930         }
8931       }
8932     }
8933     if (seen_seq != 0) {
8934       // Mark the entry as seen so we won't return any older entry later.
8935       atomic->last_seen.update(thr->tid(), seen_seq);
8936     }
8937   } else {
8938     CHECK("should never happen as of now" == 0);
8939     PrintfIf(debug_atomic, "HIST(%p): UNITIALIZED LOAD\n", (void*)a);
8940     v = thr->random();
8941   }
8942   PrintfIf(debug_atomic, "HIST(%p): } -> %llu\n",
8943       (void*)a, (unsigned long long)v);
8944   return v;
8945 }
8946 
8947 
ClearMemoryState(uintptr_t a,uintptr_t b)8948 void TsanAtomicCore::ClearMemoryState(uintptr_t a, uintptr_t b) {
8949   DCHECK(a <= b);
8950   DCHECK(G_flags->enable_atomic || atomic_map_.empty());
8951   AtomicMap::iterator begin (atomic_map_.lower_bound(a));
8952   AtomicMap::iterator pos (begin);
8953   for (; pos != atomic_map_.end() && pos->first <= b; ++pos) {
8954     pos->second.reset();
8955   }
8956   atomic_map_.erase(begin, pos);
8957 }
8958 
8959 
AtomicFixHist(Atomic * atomic,uint64_t prev)8960 void TsanAtomicCore::AtomicFixHist(Atomic* atomic, uint64_t prev) {
8961   AtomicHistoryEntry& hprv = atomic->hist
8962       [(atomic->hist_pos - 1) % Atomic::kHistSize];
8963   // In case we had missed an atomic access (that is, an access from
8964   // non-instrumented code), reset whole history and initialize it
8965   // with a single entry that happened "before world creation".
8966   if (prev != hprv.val) {
8967     PrintfIf(debug_atomic, "HIST RESET\n");
8968     atomic->reset();
8969     AtomicHistoryEntry& hist = atomic->hist
8970         [atomic->hist_pos % Atomic::kHistSize];
8971     hist.val = prev;
8972     hist.tid = TID(0);
8973     hist.clk = 0;
8974     atomic->hist_pos += 1;
8975   }
8976 }
8977 
8978 
Atomic()8979 TsanAtomicCore::Atomic::Atomic() {
8980   reset(true);
8981 }
8982 
8983 
reset(bool init)8984 void TsanAtomicCore::Atomic::reset(bool init) {
8985   hist_pos = sizeof(hist)/sizeof(hist[0]) + 1;
8986   for (size_t i = 0; i != sizeof(hist)/sizeof(hist[0]); i += 1) {
8987     hist[i].val = 0xBCEBC041;
8988     hist[i].tid = TID(TID::kInvalidTID);
8989     hist[i].clk = -1;
8990     if (init == false && hist[i].vts != 0)
8991       VTS::Unref(hist[i].vts);
8992     hist[i].vts = 0;
8993   }
8994   last_seen.reset();
8995 }
8996 
8997 
8998 // -------- TODO -------------------------- {{{1
8999 // - Support configurable aliases for function names (is it doable in valgrind)?
9000 // - Correctly support atomic operations (not just ignore).
9001 // - Handle INC as just one write
9002 //   - same for memset, etc
9003 // - Implement correct handling of memory accesses with different sizes.
9004 // - Do not create HB arcs between RdUnlock and RdLock
9005 // - Compress cache lines
9006 // - Optimize the case where a threads signals twice in a row on the same
9007 //   address.
9008 // - Fix --ignore-in-dtor if --demangle=no.
9009 // - Use cpplint (http://code.google.com/p/google-styleguide)
9010 // - Get rid of annoying casts in printfs.
9011 // - Compress stack traces (64-bit only. may save up to 36 bytes per segment).
9012 // end. {{{1
9013 // vim:shiftwidth=2:softtabstop=2:expandtab:tw=80
9014