• 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 // 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:
Push(const char * cc)315   void Push(const char *cc) {
316     malloc_cost_centers_[size_++] = cc;
317   }
Pop()318   void Pop() {
319     size_--;
320   }
Top()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:
ScopedMallocCostCenter(const char * cc)336   ScopedMallocCostCenter(const char *cc) {
337 #if defined(TS_VALGRIND)
338     g_malloc_stack.Push(cc);
339 #endif
340   }
~ScopedMallocCostCenter()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 
tsan_bswap(uintptr_t x)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
u32_log2(unsigned x)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__
u32_log2(unsigned x)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.
tsan_prng(prng_t * state)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