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