@@ -22,115 +22,102 @@ using namespace v3;
22
22
23
23
// We need to run all trace tests in a new thread,
24
24
// so that the thread trace is empty initially.
25
- template <uptr N>
26
- struct ThreadArray {
27
- ThreadArray () {
28
- for (auto *&thr : threads) {
29
- thr = static_cast <ThreadState *>(
30
- MmapOrDie (sizeof (ThreadState), " ThreadState" ));
31
- Tid tid = ThreadCreate (cur_thread (), 0 , 0 , true );
32
- Processor *proc = ProcCreate ();
33
- ProcWire (proc, thr);
34
- ThreadStart (thr, tid, 0 , ThreadType::Regular);
35
- }
36
- }
37
-
38
- ~ThreadArray () {
39
- for (uptr i = 0 ; i < N; i++) {
40
- if (threads[i])
41
- Finish (i);
42
- }
43
- }
44
-
45
- void Finish (uptr i) {
46
- auto *thr = threads[i];
47
- threads[i] = nullptr ;
48
- Processor *proc = thr->proc ();
49
- ThreadFinish (thr);
50
- ProcUnwire (proc, thr);
51
- ProcDestroy (proc);
52
- UnmapOrDie (thr, sizeof (ThreadState));
53
- }
25
+ static void run_in_thread (void *(*f)(void *), void *arg = nullptr) {
26
+ pthread_t th;
27
+ pthread_create (&th, nullptr , f, arg);
28
+ pthread_join (th, nullptr );
29
+ }
54
30
55
- ThreadState *threads[N];
56
- ThreadState *operator [](uptr i) { return threads[i]; }
57
- ThreadState *operator ->() { return threads[0 ]; }
58
- operator ThreadState *() { return threads[0 ]; }
59
- };
31
+ #if SANITIZER_MAC
32
+ // These tests are currently failing on Mac.
33
+ // See https://reviews.llvm.org/D107911 for more details.
34
+ # define MAYBE_RestoreAccess DISABLED_RestoreAccess
35
+ # define MAYBE_MemoryAccessSize DISABLED_MemoryAccessSize
36
+ # define MAYBE_RestoreMutexLock DISABLED_RestoreMutexLock
37
+ # define MAYBE_MultiPart DISABLED_MultiPart
38
+ #else
39
+ # define MAYBE_RestoreAccess RestoreAccess
40
+ # define MAYBE_MemoryAccessSize MemoryAccessSize
41
+ # define MAYBE_RestoreMutexLock RestoreMutexLock
42
+ # define MAYBE_MultiPart MultiPart
43
+ #endif
60
44
61
- TEST (Trace, RestoreAccess) {
62
- // A basic test with some function entry/exit events,
63
- // some mutex lock/unlock events and some other distracting
64
- // memory events.
65
- ThreadArray<1 > thr;
66
- TraceFunc (thr, 0x1000 );
67
- TraceFunc (thr, 0x1001 );
68
- TraceMutexLock (thr, v3::EventType::kLock , 0x4000 , 0x5000 , 0x6000 );
69
- TraceMutexLock (thr, v3::EventType::kLock , 0x4001 , 0x5001 , 0x6001 );
70
- TraceMutexUnlock (thr, 0x5000 );
71
- TraceFunc (thr);
72
- CHECK (TryTraceMemoryAccess (thr, 0x2001 , 0x3001 , 8 , kAccessRead ));
73
- TraceMutexLock (thr, v3::EventType::kRLock , 0x4002 , 0x5002 , 0x6002 );
74
- TraceFunc (thr, 0x1002 );
75
- CHECK (TryTraceMemoryAccess (thr, 0x2000 , 0x3000 , 8 , kAccessRead ));
76
- // This is the access we want to find.
77
- // The previous one is equivalent, but RestoreStack must prefer
78
- // the last of the matchig accesses.
79
- CHECK (TryTraceMemoryAccess (thr, 0x2002 , 0x3000 , 8 , kAccessRead ));
80
- Lock lock1 (&ctx->slot_mtx );
81
- ThreadRegistryLock lock2 (&ctx->thread_registry );
82
- VarSizeStackTrace stk;
83
- MutexSet mset;
84
- uptr tag = kExternalTagNone ;
85
- bool res =
86
- RestoreStack (thr->tid , v3::EventType::kAccessExt , thr->sid , thr->epoch ,
87
- 0x3000 , 8 , kAccessRead , &stk, &mset, &tag);
88
- CHECK (res);
89
- CHECK_EQ (stk.size , 3 );
90
- CHECK_EQ (stk.trace [0 ], 0x1000 );
91
- CHECK_EQ (stk.trace [1 ], 0x1002 );
92
- CHECK_EQ (stk.trace [2 ], 0x2002 );
93
- CHECK_EQ (mset.Size (), 2 );
94
- CHECK_EQ (mset.Get (0 ).addr , 0x5001 );
95
- CHECK_EQ (mset.Get (0 ).stack_id , 0x6001 );
96
- CHECK_EQ (mset.Get (0 ).write , true );
97
- CHECK_EQ (mset.Get (1 ).addr , 0x5002 );
98
- CHECK_EQ (mset.Get (1 ).stack_id , 0x6002 );
99
- CHECK_EQ (mset.Get (1 ).write , false );
100
- CHECK_EQ (tag, kExternalTagNone );
45
+ TEST (Trace, MAYBE_RestoreAccess) {
46
+ struct Thread {
47
+ static void *Func (void *arg) {
48
+ // A basic test with some function entry/exit events,
49
+ // some mutex lock/unlock events and some other distracting
50
+ // memory events.
51
+ ThreadState *thr = cur_thread ();
52
+ TraceFunc (thr, 0x1000 );
53
+ TraceFunc (thr, 0x1001 );
54
+ TraceMutexLock (thr, v3::EventType::kLock , 0x4000 , 0x5000 , 0x6000 );
55
+ TraceMutexLock (thr, v3::EventType::kLock , 0x4001 , 0x5001 , 0x6001 );
56
+ TraceMutexUnlock (thr, 0x5000 );
57
+ TraceFunc (thr);
58
+ CHECK (TryTraceMemoryAccess (thr, 0x2001 , 0x3001 , 8 , kAccessRead ));
59
+ TraceMutexLock (thr, v3::EventType::kRLock , 0x4002 , 0x5002 , 0x6002 );
60
+ TraceFunc (thr, 0x1002 );
61
+ CHECK (TryTraceMemoryAccess (thr, 0x2000 , 0x3000 , 8 , kAccessRead ));
62
+ // This is the access we want to find.
63
+ // The previous one is equivalent, but RestoreStack must prefer
64
+ // the last of the matchig accesses.
65
+ CHECK (TryTraceMemoryAccess (thr, 0x2002 , 0x3000 , 8 , kAccessRead ));
66
+ Lock lock1 (&ctx->slot_mtx );
67
+ ThreadRegistryLock lock2 (&ctx->thread_registry );
68
+ VarSizeStackTrace stk;
69
+ MutexSet mset;
70
+ uptr tag = kExternalTagNone ;
71
+ bool res =
72
+ RestoreStack (thr->tid , v3::EventType::kAccessExt , thr->sid ,
73
+ thr->epoch , 0x3000 , 8 , kAccessRead , &stk, &mset, &tag);
74
+ CHECK (res);
75
+ CHECK_EQ (stk.size , 3 );
76
+ CHECK_EQ (stk.trace [0 ], 0x1000 );
77
+ CHECK_EQ (stk.trace [1 ], 0x1002 );
78
+ CHECK_EQ (stk.trace [2 ], 0x2002 );
79
+ CHECK_EQ (mset.Size (), 2 );
80
+ CHECK_EQ (mset.Get (0 ).addr , 0x5001 );
81
+ CHECK_EQ (mset.Get (0 ).stack_id , 0x6001 );
82
+ CHECK_EQ (mset.Get (0 ).write , true );
83
+ CHECK_EQ (mset.Get (1 ).addr , 0x5002 );
84
+ CHECK_EQ (mset.Get (1 ).stack_id , 0x6002 );
85
+ CHECK_EQ (mset.Get (1 ).write , false );
86
+ CHECK_EQ (tag, kExternalTagNone );
87
+ return nullptr ;
88
+ }
89
+ };
90
+ run_in_thread (Thread::Func);
101
91
}
102
92
103
- TEST (Trace, MemoryAccessSize) {
104
- // Test tracing and matching of accesses of different sizes.
105
- struct Params {
106
- uptr access_size, offset, size;
107
- bool res;
108
- };
109
- Params tests[] = {
110
- {1 , 0 , 1 , true }, {4 , 0 , 2 , true },
111
- {4 , 2 , 2 , true }, {8 , 3 , 1 , true },
112
- {2 , 1 , 1 , true }, {1 , 1 , 1 , false },
113
- {8 , 5 , 4 , false }, {4 , static_cast <uptr>(-1l ), 4 , false },
114
- };
115
- for (auto params : tests) {
116
- for (int type = 0 ; type < 3 ; type++) {
117
- ThreadArray<1 > thr;
93
+ TEST (Trace, MAYBE_MemoryAccessSize) {
94
+ struct Thread {
95
+ struct Params {
96
+ uptr access_size, offset, size;
97
+ bool res;
98
+ int type;
99
+ };
100
+ static void *Func (void *arg) {
101
+ // Test tracing and matching of accesses of different sizes.
102
+ const Params *params = static_cast <Params *>(arg);
118
103
Printf (" access_size=%zu, offset=%zu, size=%zu, res=%d, type=%d\n " ,
119
- params.access_size , params.offset , params.size , params.res , type);
104
+ params->access_size , params->offset , params->size , params->res ,
105
+ params->type );
106
+ ThreadState *thr = cur_thread ();
120
107
TraceFunc (thr, 0x1000 );
121
- switch (type) {
108
+ switch (params-> type ) {
122
109
case 0 :
123
110
// This should emit compressed event.
124
- CHECK (TryTraceMemoryAccess (thr, 0x2000 , 0x3000 , params. access_size ,
111
+ CHECK (TryTraceMemoryAccess (thr, 0x2000 , 0x3000 , params-> access_size ,
125
112
kAccessRead ));
126
113
break ;
127
114
case 1 :
128
115
// This should emit full event.
129
- CHECK (TryTraceMemoryAccess (thr, 0x2000000 , 0x3000 , params. access_size ,
130
- kAccessRead ));
116
+ CHECK (TryTraceMemoryAccess (thr, 0x2000000 , 0x3000 ,
117
+ params-> access_size , kAccessRead ));
131
118
break ;
132
119
case 2 :
133
- TraceMemoryAccessRange (thr, 0x2000000 , 0x3000 , params. access_size ,
120
+ TraceMemoryAccessRange (thr, 0x2000000 , 0x3000 , params-> access_size ,
134
121
kAccessRead );
135
122
break ;
136
123
}
@@ -140,82 +127,105 @@ TEST(Trace, MemoryAccessSize) {
140
127
MutexSet mset;
141
128
uptr tag = kExternalTagNone ;
142
129
bool res = RestoreStack (thr->tid , v3::EventType::kAccessExt , thr->sid ,
143
- thr->epoch , 0x3000 + params. offset , params. size ,
130
+ thr->epoch , 0x3000 + params-> offset , params-> size ,
144
131
kAccessRead , &stk, &mset, &tag);
145
- CHECK_EQ (res, params. res );
146
- if (params. res ) {
132
+ CHECK_EQ (res, params-> res );
133
+ if (params-> res ) {
147
134
CHECK_EQ (stk.size , 2 );
148
135
CHECK_EQ (stk.trace [0 ], 0x1000 );
149
- CHECK_EQ (stk.trace [1 ], type ? 0x2000000 : 0x2000 );
136
+ CHECK_EQ (stk.trace [1 ], params-> type ? 0x2000000 : 0x2000 );
150
137
}
138
+ return nullptr ;
151
139
}
140
+ };
141
+ Thread::Params tests[] = {
142
+ {1 , 0 , 1 , true , 0 }, {4 , 0 , 2 , true , 0 },
143
+ {4 , 2 , 2 , true , 0 }, {8 , 3 , 1 , true , 0 },
144
+ {2 , 1 , 1 , true , 0 }, {1 , 1 , 1 , false , 0 },
145
+ {8 , 5 , 4 , false , 0 }, {4 , static_cast <uptr>(-1l ), 4 , false , 0 },
146
+ };
147
+ for (auto params : tests) {
148
+ for (params.type = 0 ; params.type < 3 ; params.type ++)
149
+ run_in_thread (Thread::Func, ¶ms);
152
150
}
153
151
}
154
152
155
- TEST (Trace, RestoreMutexLock) {
156
- // Check of restoration of a mutex lock event.
157
- ThreadArray<1 > thr;
158
- TraceFunc (thr, 0x1000 );
159
- TraceMutexLock (thr, v3::EventType::kLock , 0x4000 , 0x5000 , 0x6000 );
160
- TraceMutexLock (thr, v3::EventType::kRLock , 0x4001 , 0x5001 , 0x6001 );
161
- TraceMutexLock (thr, v3::EventType::kRLock , 0x4002 , 0x5001 , 0x6002 );
162
- Lock lock1 (&ctx->slot_mtx );
163
- ThreadRegistryLock lock2 (&ctx->thread_registry );
164
- VarSizeStackTrace stk;
165
- MutexSet mset;
166
- uptr tag = kExternalTagNone ;
167
- bool res = RestoreStack (thr->tid , v3::EventType::kLock , thr->sid , thr->epoch ,
168
- 0x5001 , 0 , 0 , &stk, &mset, &tag);
169
- CHECK (res);
170
- CHECK_EQ (stk.size , 2 );
171
- CHECK_EQ (stk.trace [0 ], 0x1000 );
172
- CHECK_EQ (stk.trace [1 ], 0x4002 );
173
- CHECK_EQ (mset.Size (), 2 );
174
- CHECK_EQ (mset.Get (0 ).addr , 0x5000 );
175
- CHECK_EQ (mset.Get (0 ).stack_id , 0x6000 );
176
- CHECK_EQ (mset.Get (0 ).write , true );
177
- CHECK_EQ (mset.Get (1 ).addr , 0x5001 );
178
- CHECK_EQ (mset.Get (1 ).stack_id , 0x6001 );
179
- CHECK_EQ (mset.Get (1 ).write , false );
153
+ TEST (Trace, MAYBE_RestoreMutexLock) {
154
+ struct Thread {
155
+ static void *Func (void *arg) {
156
+ // Check of restoration of a mutex lock event.
157
+ ThreadState *thr = cur_thread ();
158
+ TraceFunc (thr, 0x1000 );
159
+ TraceMutexLock (thr, v3::EventType::kLock , 0x4000 , 0x5000 , 0x6000 );
160
+ TraceMutexLock (thr, v3::EventType::kRLock , 0x4001 , 0x5001 , 0x6001 );
161
+ TraceMutexLock (thr, v3::EventType::kRLock , 0x4002 , 0x5001 , 0x6002 );
162
+ Lock lock1 (&ctx->slot_mtx );
163
+ ThreadRegistryLock lock2 (&ctx->thread_registry );
164
+ VarSizeStackTrace stk;
165
+ MutexSet mset;
166
+ uptr tag = kExternalTagNone ;
167
+ bool res = RestoreStack (thr->tid , v3::EventType::kLock , thr->sid ,
168
+ thr->epoch , 0x5001 , 0 , 0 , &stk, &mset, &tag);
169
+ CHECK (res);
170
+ CHECK_EQ (stk.size , 2 );
171
+ CHECK_EQ (stk.trace [0 ], 0x1000 );
172
+ CHECK_EQ (stk.trace [1 ], 0x4002 );
173
+ CHECK_EQ (mset.Size (), 2 );
174
+ CHECK_EQ (mset.Get (0 ).addr , 0x5000 );
175
+ CHECK_EQ (mset.Get (0 ).stack_id , 0x6000 );
176
+ CHECK_EQ (mset.Get (0 ).write , true );
177
+ CHECK_EQ (mset.Get (1 ).addr , 0x5001 );
178
+ CHECK_EQ (mset.Get (1 ).stack_id , 0x6001 );
179
+ CHECK_EQ (mset.Get (1 ).write , false );
180
+ return nullptr ;
181
+ }
182
+ };
183
+ run_in_thread (Thread::Func);
180
184
}
181
185
182
- TEST (Trace, MultiPart) {
183
- // Check replay of a trace with multiple parts.
184
- ThreadArray<1 > thr;
185
- TraceFunc (thr, 0x1000 );
186
- TraceFunc (thr, 0x2000 );
187
- TraceMutexLock (thr, v3::EventType::kLock , 0x4000 , 0x5000 , 0x6000 );
188
- const uptr kEvents = 3 * sizeof (TracePart) / sizeof (v3::Event);
189
- for (uptr i = 0 ; i < kEvents ; i++) {
190
- TraceFunc (thr, 0x3000 );
191
- TraceMutexLock (thr, v3::EventType::kLock , 0x4002 , 0x5002 , 0x6002 );
192
- TraceMutexUnlock (thr, 0x5002 );
193
- TraceFunc (thr);
194
- }
195
- TraceFunc (thr, 0x4000 );
196
- TraceMutexLock (thr, v3::EventType::kRLock , 0x4001 , 0x5001 , 0x6001 );
197
- CHECK (TryTraceMemoryAccess (thr, 0x2002 , 0x3000 , 8 , kAccessRead ));
198
- Lock lock1 (&ctx->slot_mtx );
199
- ThreadRegistryLock lock2 (&ctx->thread_registry );
200
- VarSizeStackTrace stk;
201
- MutexSet mset;
202
- uptr tag = kExternalTagNone ;
203
- bool res =
204
- RestoreStack (thr->tid , v3::EventType::kAccessExt , thr->sid , thr->epoch ,
205
- 0x3000 , 8 , kAccessRead , &stk, &mset, &tag);
206
- CHECK (res);
207
- CHECK_EQ (stk.size , 4 );
208
- CHECK_EQ (stk.trace [0 ], 0x1000 );
209
- CHECK_EQ (stk.trace [1 ], 0x2000 );
210
- CHECK_EQ (stk.trace [2 ], 0x4000 );
211
- CHECK_EQ (stk.trace [3 ], 0x2002 );
212
- CHECK_EQ (mset.Size (), 2 );
213
- CHECK_EQ (mset.Get (0 ).addr , 0x5000 );
214
- CHECK_EQ (mset.Get (0 ).stack_id , 0x6000 );
215
- CHECK_EQ (mset.Get (0 ).write , true );
216
- CHECK_EQ (mset.Get (1 ).addr , 0x5001 );
217
- CHECK_EQ (mset.Get (1 ).stack_id , 0x6001 );
218
- CHECK_EQ (mset.Get (1 ).write , false );
186
+ TEST (Trace, MAYBE_MultiPart) {
187
+ struct Thread {
188
+ static void *Func (void *arg) {
189
+ // Check replay of a trace with multiple parts.
190
+ ThreadState *thr = cur_thread ();
191
+ TraceFunc (thr, 0x1000 );
192
+ TraceFunc (thr, 0x2000 );
193
+ TraceMutexLock (thr, v3::EventType::kLock , 0x4000 , 0x5000 , 0x6000 );
194
+ const uptr kEvents = 3 * sizeof (TracePart) / sizeof (v3::Event);
195
+ for (uptr i = 0 ; i < kEvents ; i++) {
196
+ TraceFunc (thr, 0x3000 );
197
+ TraceMutexLock (thr, v3::EventType::kLock , 0x4002 , 0x5002 , 0x6002 );
198
+ TraceMutexUnlock (thr, 0x5002 );
199
+ TraceFunc (thr);
200
+ }
201
+ TraceFunc (thr, 0x4000 );
202
+ TraceMutexLock (thr, v3::EventType::kRLock , 0x4001 , 0x5001 , 0x6001 );
203
+ CHECK (TryTraceMemoryAccess (thr, 0x2002 , 0x3000 , 8 , kAccessRead ));
204
+ Lock lock1 (&ctx->slot_mtx );
205
+ ThreadRegistryLock lock2 (&ctx->thread_registry );
206
+ VarSizeStackTrace stk;
207
+ MutexSet mset;
208
+ uptr tag = kExternalTagNone ;
209
+ bool res =
210
+ RestoreStack (thr->tid , v3::EventType::kAccessExt , thr->sid ,
211
+ thr->epoch , 0x3000 , 8 , kAccessRead , &stk, &mset, &tag);
212
+ CHECK (res);
213
+ CHECK_EQ (stk.size , 4 );
214
+ CHECK_EQ (stk.trace [0 ], 0x1000 );
215
+ CHECK_EQ (stk.trace [1 ], 0x2000 );
216
+ CHECK_EQ (stk.trace [2 ], 0x4000 );
217
+ CHECK_EQ (stk.trace [3 ], 0x2002 );
218
+ CHECK_EQ (mset.Size (), 2 );
219
+ CHECK_EQ (mset.Get (0 ).addr , 0x5000 );
220
+ CHECK_EQ (mset.Get (0 ).stack_id , 0x6000 );
221
+ CHECK_EQ (mset.Get (0 ).write , true );
222
+ CHECK_EQ (mset.Get (1 ).addr , 0x5001 );
223
+ CHECK_EQ (mset.Get (1 ).stack_id , 0x6001 );
224
+ CHECK_EQ (mset.Get (1 ).write , false );
225
+ return nullptr ;
226
+ }
227
+ };
228
+ run_in_thread (Thread::Func);
219
229
}
220
230
221
231
} // namespace __tsan
0 commit comments