blob: e9a801d2979ca186c91bff8009991b3363982728 [file] [log] [blame]
Kostya Serebryany7ac41482012-05-10 13:48:04 +00001//===-- tsan_defs.h ---------------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file is a part of ThreadSanitizer (TSan), a race detector.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef TSAN_DEFS_H
15#define TSAN_DEFS_H
16
17#include "tsan_compiler.h"
18#include "tsan_stat.h"
19
20#ifndef TSAN_DEBUG
21#define TSAN_DEBUG 0
22#endif // TSAN_DEBUG
23
24namespace __tsan {
25
26typedef unsigned u32; // NOLINT
27typedef unsigned long long u64; // NOLINT
28typedef signed long long s64; // NOLINT
29typedef unsigned long uptr; // NOLINT
30
31const uptr kPageSize = 4096;
Dmitry Vyukov069ce822012-05-17 14:17:51 +000032const int kTidBits = 15;
Kostya Serebryany3d6ae152012-05-11 14:42:24 +000033const unsigned kMaxTid = 1 << kTidBits;
Dmitry Vyukov069ce822012-05-17 14:17:51 +000034const unsigned kMaxTidInClock = kMaxTid * 2; // This includes msb 'freed' bit.
Kostya Serebryany7ac41482012-05-10 13:48:04 +000035const int kClkBits = 40;
36
37#ifdef TSAN_SHADOW_COUNT
38# if TSAN_SHADOW_COUNT == 2 \
39 || TSAN_SHADOW_COUNT == 4 || TSAN_SHADOW_COUNT == 8
40const unsigned kShadowCnt = TSAN_SHADOW_COUNT;
41# else
42# error "TSAN_SHADOW_COUNT must be one of 2,4,8"
43# endif
44#else
45// Count of shadow values in a shadow cell.
46const unsigned kShadowCnt = 8;
47#endif
48
49// That many user bytes are mapped onto a single shadow cell.
50const unsigned kShadowCell = 8;
51
52// Size of a single shadow value (u64).
53const unsigned kShadowSize = 8;
54
55#if defined(TSAN_COLLECT_STATS) && TSAN_COLLECT_STATS
56const bool kCollectStats = true;
57#else
58const bool kCollectStats = false;
59#endif
60
61#define CHECK_IMPL(c1, op, c2) \
62 do { \
63 __tsan::u64 v1 = (u64)(c1); \
64 __tsan::u64 v2 = (u64)(c2); \
65 if (!(v1 op v2)) \
66 __tsan::CheckFailed(__FILE__, __LINE__, \
67 "(" #c1 ") " #op " (" #c2 ")", v1, v2); \
68 } while (false) \
69/**/
70
71#define CHECK(a) CHECK_IMPL((a), !=, 0)
72#define CHECK_EQ(a, b) CHECK_IMPL((a), ==, (b))
73#define CHECK_NE(a, b) CHECK_IMPL((a), !=, (b))
74#define CHECK_LT(a, b) CHECK_IMPL((a), <, (b))
75#define CHECK_LE(a, b) CHECK_IMPL((a), <=, (b))
76#define CHECK_GT(a, b) CHECK_IMPL((a), >, (b))
77#define CHECK_GE(a, b) CHECK_IMPL((a), >=, (b))
78
79#if TSAN_DEBUG
80#define DCHECK(a) CHECK(a)
81#define DCHECK_EQ(a, b) CHECK_EQ(a, b)
82#define DCHECK_NE(a, b) CHECK_NE(a, b)
83#define DCHECK_LT(a, b) CHECK_LT(a, b)
84#define DCHECK_LE(a, b) CHECK_LE(a, b)
85#define DCHECK_GT(a, b) CHECK_GT(a, b)
86#define DCHECK_GE(a, b) CHECK_GE(a, b)
87#else
88#define DCHECK(a)
89#define DCHECK_EQ(a, b)
90#define DCHECK_NE(a, b)
91#define DCHECK_LT(a, b)
92#define DCHECK_LE(a, b)
93#define DCHECK_GT(a, b)
94#define DCHECK_GE(a, b)
95#endif
96
97void CheckFailed(const char *file, int line, const char *cond, u64 v1, u64 v2);
98
99// The following "build consistency" machinery ensures that all source files
100// are built in the same configuration. Inconsistent builds lead to
101// hard to debug crashes.
102#if TSAN_DEBUG
103void build_consistency_debug();
104#else
105void build_consistency_release();
106#endif
107
108#if TSAN_COLLECT_STATS
109void build_consistency_stats();
110#else
111void build_consistency_nostats();
112#endif
113
114#if TSAN_SHADOW_COUNT == 1
115void build_consistency_shadow1();
116#elif TSAN_SHADOW_COUNT == 2
117void build_consistency_shadow2();
118#elif TSAN_SHADOW_COUNT == 4
119void build_consistency_shadow4();
120#else
121void build_consistency_shadow8();
122#endif
123
124static inline void USED build_consistency() {
125#if TSAN_DEBUG
126 void(*volatile cfg)() = &build_consistency_debug;
127#else
128 void(*volatile cfg)() = &build_consistency_release;
129#endif
130#if TSAN_COLLECT_STATS
131 void(*volatile stats)() = &build_consistency_stats;
132#else
133 void(*volatile stats)() = &build_consistency_nostats;
134#endif
135#if TSAN_SHADOW_COUNT == 1
136 void(*volatile shadow)() = &build_consistency_shadow1;
137#elif TSAN_SHADOW_COUNT == 2
138 void(*volatile shadow)() = &build_consistency_shadow2;
139#elif TSAN_SHADOW_COUNT == 4
140 void(*volatile shadow)() = &build_consistency_shadow4;
141#else
142 void(*volatile shadow)() = &build_consistency_shadow8;
143#endif
144 (void)cfg;
145 (void)stats;
146 (void)shadow;
147}
148
149template<typename T>
150T min(T a, T b) {
151 return a < b ? a : b;
152}
153
154template<typename T>
155T max(T a, T b) {
156 return a > b ? a : b;
157}
158
159template<typename T>
160T RoundUp(T p, int align) {
161 DCHECK_EQ(align & (align - 1), 0);
162 return (T)(((u64)p + align - 1) & ~(align - 1));
163}
164
165void internal_memset(void *ptr, int c, uptr size);
166void internal_memcpy(void *dst, const void *src, uptr size);
167int internal_memcmp(const void *s1, const void *s2, uptr size);
168int internal_strcmp(const char *s1, const char *s2);
169int internal_strncmp(const char *s1, const char *s2, uptr size);
170void internal_strcpy(char *s1, const char *s2);
171uptr internal_strlen(const char *s);
172char* internal_strdup(const char *s);
173const char *internal_strstr(const char *where, const char *what);
174const char *internal_strchr(const char *where, char what);
175
176struct MD5Hash {
177 u64 hash[2];
178 bool operator==(const MD5Hash &other) const {
179 return hash[0] == other.hash[0] && hash[1] == other.hash[1];
180 }
181};
182
183MD5Hash md5_hash(const void *data, uptr size);
184
185struct ThreadState;
186struct ThreadContext;
187struct Context;
188struct ReportStack;
189class ReportDesc;
190class RegionAlloc;
191class StackTrace;
192
193} // namespace __tsan
194
195#endif // TSAN_DEFS_H