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