Home | History | Annotate | Download | only in tsan
      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 // This file contains utility classes and functions used by ThreadSanitizer.
     32 // TODO(kcc): move more utilities from thread_sanitizer.cc to this file.
     33 
     34 #ifndef TS_UTIL_H_
     35 #define TS_UTIL_H_
     36 
     37 //--------- Head ------------------- {{{1
     38 #if defined(TS_VALGRIND)
     39 # define CHECK tl_assert
     40 #elif defined(TS_PIN)
     41 extern void Printf(const char *format, ...);
     42 extern void ThreadSanitizerDumpAllStacks();
     43 # define CHECK(x) do { if (!(x)) { \
     44    Printf("Assertion failed: %s (%s:%d) %s\n", \
     45           __FUNCTION__, __FILE__, __LINE__, #x); \
     46    ThreadSanitizerDumpAllStacks(); \
     47    exit(1); }} while ((void)0, 0)
     48 #elif defined(TS_OFFLINE)
     49 extern unsigned long offline_line_n;
     50 # define CHECK(x) do { if (!(x)) { \
     51     Printf("ASSERT on line %ld\n", offline_line_n); \
     52      assert(x);}} while ((void)0, 0)
     53 #else
     54 # define CHECK assert
     55 #endif
     56 
     57 // support for stlport in stlp_std:: namespace (or other custom ns)
     58 #ifdef TS_STL_NS
     59 # define STD TS_STL_NS
     60 #else
     61 # define STD std
     62 #endif
     63 
     64 #if defined(TS_VALGRIND)
     65 # include "ts_valgrind.h"
     66 # define TS_USE_STLPORT
     67 #if defined(VGP_arm_linux)
     68 // This macro is explicitly undefined in glibc for ARM.
     69 #define _GLIBCXX_USE_C99 1
     70 #endif  // ARM
     71 
     72 // __WORDSIZE is GLibC-specific. Get it from Valgrind if needed.
     73 #if !defined(__WORDSIZE)
     74 #if VG_WORDSIZE == 4
     75 #define __WORDSIZE 32
     76 #elif VG_WORDSIZE == 8
     77 #define __WORDSIZE 64
     78 #endif // VG_WORDSIZE
     79 #endif // TS_VALGRIND && !__WORDSIZE
     80 
     81 #elif defined(TS_LLVM)
     82 #  define TS_USE_STLPORT
     83 # include <assert.h>
     84 # include <fcntl.h>
     85 # include <time.h>
     86 
     87 #elif defined(__GNUC__)
     88 # undef NDEBUG  // Assert is always on.
     89 # include <assert.h>
     90 # include <sys/types.h>
     91 # include <sys/stat.h>
     92 # include <fcntl.h>
     93 # define TS_USE_GNUC_STL
     94 
     95 #elif defined(_MSC_VER)
     96 # undef NDEBUG  // Assert is always on.
     97 # include <assert.h>
     98 # include <stdio.h>
     99 # include <intrin.h>
    100 # define TS_USE_WIN_STL
    101 
    102 #else
    103 # error "Unknown configuration"
    104 #endif
    105 
    106 //--------- STL ------------------- {{{1
    107 #if defined(TS_USE_GNUC_STL)  // ----------- g++ STL -----------
    108 #include <string.h>
    109 #include <limits.h>
    110 #include <set>
    111 #include <map>
    112 #include <vector>
    113 #include <deque>
    114 #include <stack>
    115 #include <algorithm>
    116 #include <string>
    117 #include <bitset>
    118 #include <new>
    119 #include <ext/algorithm>
    120 
    121 #ifdef __APPLE__
    122 // Apple's unordered_map in gcc 4.0 does not support -fno-exceptions.
    123 #include "ext/hash_map"
    124 #include "ext/hash_set"
    125 #define unordered_map __gnu_cxx::hash_map
    126 #define unordered_set __gnu_cxx::hash_set
    127 #else
    128 #include "tr1/unordered_map"
    129 #include "tr1/unordered_set"
    130 using STD::tr1::unordered_map;
    131 using STD::tr1::unordered_set;
    132 #endif
    133 
    134 #elif defined(TS_USE_STLPORT)  // ------------- STLport ----------
    135 #include "set"
    136 #include "map"
    137 #include "hash_map"
    138 #include "hash_set"
    139 #include "vector"
    140 #include "deque"
    141 #include "stack"
    142 #include "algorithm"
    143 #include "string"
    144 #include "bitset"
    145 #include "algorithm"
    146 #include "new"
    147 
    148 #include "unordered_map"
    149 #include "unordered_set"
    150 using STD::tr1::unordered_map;
    151 using STD::tr1::unordered_set;
    152 
    153 #elif defined(TS_USE_WIN_STL)  // ------------- MSVC STL ---------
    154 #include <string.h>
    155 #include <limits.h>
    156 #include <set>
    157 #include <map>
    158 #include <vector>
    159 #include <deque>
    160 #include <stack>
    161 #include <algorithm>
    162 #include <string>
    163 #include <bitset>
    164 #include <new>
    165 
    166 // No such thing in VC 2005
    167 //#include <unordered_map>
    168 //#include <unordered_set>
    169 //using std::tr1::unordered_map;
    170 //using std::tr1::unordered_set;
    171 #include <hash_map>
    172 #include <hash_set>
    173 #define unordered_map stdext::hash_map
    174 #define unordered_set stdext::hash_set
    175 
    176 #else
    177 # error "Unknown STL"
    178 #endif  // TS_USE_STANDARD_STL
    179 
    180 using STD::string;
    181 using STD::set;
    182 using STD::multiset;
    183 using STD::multimap;
    184 using STD::map;
    185 using STD::deque;
    186 using STD::stack;
    187 using STD::vector;
    188 using STD::bitset;
    189 using STD::nothrow_t;
    190 using STD::nothrow;
    191 
    192 using STD::min;
    193 using STD::max;
    194 using STD::sort;
    195 using STD::pair;
    196 using STD::make_pair;
    197 using STD::unique_copy;
    198 using STD::count;
    199 using STD::set_intersection;
    200 using STD::lower_bound;
    201 using STD::copy;
    202 using STD::binary_search;
    203 
    204 #ifdef TS_LLVM
    205 # include "tsan_rtl_wrap.h"
    206 #endif
    207 
    208 //--------- defines ------------------- {{{1
    209 #ifdef TS_VALGRIND
    210 // TODO(kcc) get rid of these macros.
    211 #define sprintf(arg1, arg2...) VG_(sprintf)((Char*)arg1, (HChar*)arg2)
    212 #define vsnprintf(a1, a2, a3, a4) VG_(vsnprintf)((Char*)a1, a2, a3, a4)
    213 #define getpid VG_(getpid)
    214 #define strchr(a,b)    VG_(strchr)((Char*)a,b)
    215 #define strdup(a) (char*)VG_(strdup)((HChar*)"strdup", (const Char*)a)
    216 #define snprintf(a,b,c...)     VG_(snprintf)((Char*)a,b,c)
    217 #define read VG_(read)
    218 #define getenv(x) VG_(getenv)((Char*)x)
    219 #define close VG_(close)
    220 #define write VG_(write)
    221 #define usleep(a) /*nothing. TODO.*/
    222 
    223 #elif defined(__GNUC__)
    224 #include <unistd.h>
    225 #include <stdint.h>
    226 #include <stdio.h>
    227 
    228 #define UNLIKELY(x) __builtin_expect((x), 0)
    229 #define LIKELY(x)   __builtin_expect(!!(x), 1)
    230 
    231 #elif defined(_MSC_VER)
    232 typedef __int8 int8_t;
    233 typedef __int16 int16_t;
    234 typedef __int32 int32_t;
    235 typedef __int64 int64_t;
    236 typedef unsigned __int8 uint8_t;
    237 typedef unsigned __int16 uint16_t;
    238 typedef unsigned __int32 uint32_t;
    239 typedef unsigned __int64 uint64_t;
    240 
    241 typedef int pthread_t;
    242 int getpid();
    243 #define snprintf _snprintf
    244 #define strtoll strtol  // TODO(kcc): _MSC_VER hmm...
    245 #define UNLIKELY(x) (x)  // TODO(kcc): how to say this in MSVC?
    246 #define LIKELY(x)   (x)
    247 
    248 #else
    249 # error "Unknown configuration"
    250 #endif // TS_VALGRIND
    251 
    252 #define CHECK_GT(X, Y) CHECK((X) >  (Y))
    253 #define CHECK_LT(X, Y) CHECK((X) < (Y))
    254 #define CHECK_GE(X, Y) CHECK((X) >= (Y))
    255 #define CHECK_LE(X, Y) CHECK((X) <= (Y))
    256 #define CHECK_NE(X, Y) CHECK((X) != (Y))
    257 #define CHECK_EQ(X, Y) CHECK((X) == (Y))
    258 
    259 #if defined(DEBUG) && DEBUG >= 1
    260   #define DCHECK(a) CHECK(a)
    261   #define DEBUG_MODE (1)
    262 #else
    263   #define DCHECK(a) do { if (0) { if (a) {} } } while((void)0, 0)
    264   #define DEBUG_MODE (0)
    265 #endif
    266 
    267 #ifndef ALWAYS_INLINE
    268   #if defined (__GNUC__)
    269     #define ALWAYS_INLINE  inline __attribute__ ((always_inline))
    270   #elif defined(_MSC_VER)
    271     #define ALWAYS_INLINE __forceinline
    272   #else
    273     #error "Unknown Configuration"
    274   #endif
    275 #endif
    276 
    277 #if defined(DEBUG) && DEBUG >= 1
    278   #define INLINE
    279   #define NOINLINE
    280 #elif defined (__GNUC__)
    281   #define INLINE  ALWAYS_INLINE
    282   #define NOINLINE __attribute__ ((noinline))
    283 #elif defined(_MSC_VER)
    284   #define INLINE ALWAYS_INLINE
    285   #define NOINLINE __declspec(noinline)
    286 #else
    287   #error "Unknown Configuration"
    288 #endif
    289 
    290 // When TS_SERIALIZED==1, all calls to ThreadSanitizer* functions
    291 // should be serialized somehow. For example:
    292 //  - Valgrind serializes threads by using a pipe-based semaphore.
    293 //  - ThreadSanitizerOffline is single-threaded by nature.
    294 //  - A Multi-threaded environment (e.g. PIN) can use a single global Mutex.
    295 // When TS_SERIALIZED==0, ThreadSanitizer takes care of synchronization itself.
    296 
    297 #if defined(TS_SERIALIZED)
    298  // someone defined this already, leave it as is.
    299 #elif defined(TS_PIN)
    300 # define TS_SERIALIZED 1
    301 #elif defined(TS_LLVM)
    302 # define TS_SERIALIZED 0
    303 #elif defined(TS_GO)
    304 # define TS_SERIALIZED 0
    305 #else
    306 # define TS_SERIALIZED 1
    307 #endif
    308 
    309 
    310 #define TS_ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
    311 
    312 //--------- Malloc profiling ------------------- {{{1
    313 class MallocCostCenterStack {
    314  public:
    315   void Push(const char *cc) {
    316     malloc_cost_centers_[size_++] = cc;
    317   }
    318   void Pop() {
    319     size_--;
    320   }
    321   const char *Top() {
    322     return size_ ? malloc_cost_centers_[size_ - 1] : "default_cc";
    323   }
    324  private:
    325   enum { kMaxMallocStackSize = 100 };
    326   int size_;
    327   const char *malloc_cost_centers_[kMaxMallocStackSize];
    328 };
    329 
    330 // Not thread-safe. Need to make it thread-local if we allow
    331 // malloc to be called concurrently.
    332 extern MallocCostCenterStack g_malloc_stack;
    333 
    334 class ScopedMallocCostCenter {
    335  public:
    336   ScopedMallocCostCenter(const char *cc) {
    337 #if defined(TS_VALGRIND)
    338     g_malloc_stack.Push(cc);
    339 #endif
    340   }
    341   ~ScopedMallocCostCenter() {
    342 #if defined(TS_VALGRIND)
    343     g_malloc_stack.Pop();
    344 #endif
    345   }
    346 };
    347 
    348 //--------- Forward decls ------------------- {{{1
    349 class ThreadSanitizerReport;
    350 
    351 // Time since some moment before the program start.
    352 extern size_t TimeInMilliSeconds();
    353 extern void YIELD();
    354 extern void PROCESSOR_YIELD();
    355 
    356 extern "C" long my_strtol(const char *str, char **end, int base);
    357 extern void Printf(const char *format, ...);
    358 
    359 // Strip (.*) and <.*>, also handle "function returns a function pointer" case.
    360 string NormalizeFunctionName(const string &mangled_fname);
    361 
    362 string ReadFileToString(const string &file_name, bool die_if_failed);
    363 
    364 // Get the current memory footprint of myself (parse /proc/self/status).
    365 size_t GetVmSizeInMb();
    366 
    367 // Sets the contents of the file 'file_name' to 'str'.
    368 void OpenFileWriteStringAndClose(const string &file_name, const string &str);
    369 
    370 // If host_and_port looks like myhost:12345, open a socket for writing
    371 // and returns a FILE object. Retuns NULL on failure.
    372 FILE *OpenSocketForWriting(const string &host_and_port);
    373 
    374 // If addr is inside a global object, returns true and sets 'name' and 'offset'
    375 bool GetNameAndOffsetOfGlobalObject(uintptr_t addr,
    376                                     string *name, uintptr_t *offset);
    377 
    378 extern uintptr_t GetPcOfCurrentThread();
    379 
    380 extern void GetThreadStack(int tid, uintptr_t *min_addr, uintptr_t *max_addr);
    381 
    382 extern void SetNumberOfFoundErrors(int n_errs);
    383 extern int GetNumberOfFoundErrors();
    384 
    385 bool LiteRaceSkipTrace(int tid, uint32_t trace_no, uint32_t sampling_rate);
    386 
    387 
    388 inline uintptr_t tsan_bswap(uintptr_t x) {
    389 #if defined(VGP_arm_linux) && __WORDSIZE == 64
    390   return __builtin_bswap64(x);
    391 #elif defined(VGP_arm_linux) && __WORDSIZE == 32
    392   return __builtin_bswap32(x);
    393 #elif defined(__GNUC__) && __WORDSIZE == 64
    394   __asm__("bswapq %0" : "=r" (x) : "0" (x));
    395   return x;
    396 #elif defined(__GNUC__) && __WORDSIZE == 32
    397   __asm__("bswapl %0" : "=r" (x) : "0" (x));
    398   return x;
    399 #elif defined(_WIN32)
    400   return x;  // TODO(kcc)
    401 #else
    402 # error  "Unknown Configuration"
    403 #endif // arch && VG_WORDSIZE
    404 }
    405 
    406 #ifdef _MSC_VER
    407 inline unsigned u32_log2(unsigned x) {
    408   unsigned long y;
    409   _BitScanReverse(&y, x);
    410   return y;
    411 }
    412 #endif
    413 
    414 #ifdef __GNUC__
    415 inline unsigned u32_log2(unsigned x) {
    416   return 31 - __builtin_clz(x);
    417 }
    418 #endif
    419 
    420 typedef unsigned prng_t;
    421 
    422 /// Simple stand-alone pseudorandom number generator.
    423 /// Current algorithm is ANSI C linear congruential PRNG.
    424 inline unsigned tsan_prng(prng_t* state) {
    425   return (*state = *state * 1103515245 + 12345) >> 16;
    426 }
    427 
    428 
    429 #endif  // TS_UTIL_H_
    430 // end. {{{1
    431 // vim:shiftwidth=2:softtabstop=2:expandtab:tw=80
    432