blob: c4de7499ce73773d87dd64ed6e39bc90be182815 [file] [log] [blame]
sewardjaf44c822007-11-25 14:01:38 +00001/*
2 This file is part of drd, a data race detector.
3
sewardj85642922008-01-14 11:54:56 +00004 Copyright (C) 2006-2008 Bart Van Assche
sewardjaf44c822007-11-25 14:01:38 +00005 bart.vanassche@gmail.com
6
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20 02111-1307, USA.
21
22 The GNU General Public License is contained in the file COPYING.
23*/
24
25
sewardj85642922008-01-14 11:54:56 +000026#include "drd_barrier.h"
sewardjaf44c822007-11-25 14:01:38 +000027#include "drd_clientreq.h"
bart4bb53d82008-02-28 19:06:34 +000028#include "drd_clientobj.h"
sewardjaf44c822007-11-25 14:01:38 +000029#include "drd_cond.h"
30#include "drd_error.h"
31#include "drd_malloc_wrappers.h"
32#include "drd_mutex.h"
33#include "drd_segment.h"
sewardj85642922008-01-14 11:54:56 +000034#include "drd_semaphore.h"
sewardjaf44c822007-11-25 14:01:38 +000035#include "drd_suppression.h"
36#include "drd_thread.h"
37#include "drd_track.h"
38#include "drd_vc.h"
sewardj721ad7b2007-11-30 08:30:29 +000039#include "priv_drd_clientreq.h"
sewardj85642922008-01-14 11:54:56 +000040#include "pub_drd_bitmap.h"
sewardjaf44c822007-11-25 14:01:38 +000041#include "pub_tool_basics.h"
42#include "pub_tool_debuginfo.h" // VG_(describe_IP)()
43#include "pub_tool_libcassert.h" // tl_assert()
44#include "pub_tool_libcbase.h" // VG_(strcmp)
45#include "pub_tool_libcprint.h" // VG_(printf)
sewardj85642922008-01-14 11:54:56 +000046#include "pub_tool_vki.h" // Must be included before pub_tool_libcproc
sewardjaf44c822007-11-25 14:01:38 +000047#include "pub_tool_libcproc.h"
48#include "pub_tool_machine.h"
49#include "pub_tool_options.h" // command line options
50#include "pub_tool_threadstate.h" // VG_(get_running_tid)
51#include "pub_tool_tooliface.h"
52
53
sewardjaf44c822007-11-25 14:01:38 +000054// Function declarations.
55
barteb8b8c82008-02-26 19:11:20 +000056static void instrument_memory_bus_event(IRSB* const bb,
57 const IRMBusEvent event);
sewardjaf44c822007-11-25 14:01:38 +000058static void drd_start_client_code(const ThreadId tid, const ULong bbs_done);
59static void drd_set_running_tid(const ThreadId tid);
barteb8b8c82008-02-26 19:11:20 +000060static void evh__bus_lock(void);
61static void evh__bus_unlock(void);
sewardjaf44c822007-11-25 14:01:38 +000062
63
64
65// Local variables.
66
67static Bool drd_print_stats = False;
sewardjaf44c822007-11-25 14:01:38 +000068static Bool drd_trace_fork_join = False;
sewardj85642922008-01-14 11:54:56 +000069static Bool drd_trace_mem = False;
sewardjaf44c822007-11-25 14:01:38 +000070static Addr drd_trace_address = 0;
sewardjaf44c822007-11-25 14:01:38 +000071
72
73//
74// Implement the needs_command_line_options for drd.
75//
76
77static Bool drd_process_cmd_line_option(Char* arg)
78{
sewardj85642922008-01-14 11:54:56 +000079 Bool trace_barrier = False;
sewardjaf44c822007-11-25 14:01:38 +000080 Bool trace_cond = False;
bartecbf1662008-02-24 18:46:05 +000081 Bool trace_csw = False;
82 Bool trace_danger_set = False;
sewardjaf44c822007-11-25 14:01:38 +000083 Bool trace_mutex = False;
84 Bool trace_segment = False;
bart28230a32008-02-29 17:27:03 +000085 Bool trace_semaphore = False;
sewardjaf44c822007-11-25 14:01:38 +000086 Bool trace_suppression = False;
87 Char* trace_address = 0;
88
89 VG_BOOL_CLO (arg, "--drd-stats", drd_print_stats)
sewardj85642922008-01-14 11:54:56 +000090 else VG_BOOL_CLO(arg, "--trace-barrier", trace_barrier)
sewardjaf44c822007-11-25 14:01:38 +000091 else VG_BOOL_CLO(arg, "--trace-cond", trace_cond)
bartecbf1662008-02-24 18:46:05 +000092 else VG_BOOL_CLO(arg, "--trace-csw", trace_csw)
93 else VG_BOOL_CLO(arg, "--trace-danger-set", trace_danger_set)
sewardjaf44c822007-11-25 14:01:38 +000094 else VG_BOOL_CLO(arg, "--trace-fork-join", drd_trace_fork_join)
95 else VG_BOOL_CLO(arg, "--trace-mem", drd_trace_mem)
96 else VG_BOOL_CLO(arg, "--trace-mutex", trace_mutex)
97 else VG_BOOL_CLO(arg, "--trace-segment", trace_segment)
bart28230a32008-02-29 17:27:03 +000098 else VG_BOOL_CLO(arg, "--trace-semaphore", trace_semaphore)
sewardjaf44c822007-11-25 14:01:38 +000099 else VG_BOOL_CLO(arg, "--trace-suppression", trace_suppression)
100 else VG_STR_CLO (arg, "--trace-address", trace_address)
101 else
102 return False;
103
104 if (trace_address)
sewardjc0be9252008-02-11 11:00:51 +0000105 {
sewardjaf44c822007-11-25 14:01:38 +0000106 drd_trace_address = VG_(strtoll16)(trace_address, 0);
sewardjc0be9252008-02-11 11:00:51 +0000107 }
sewardj85642922008-01-14 11:54:56 +0000108 if (trace_barrier)
109 barrier_set_trace(trace_barrier);
sewardjaf44c822007-11-25 14:01:38 +0000110 if (trace_cond)
111 cond_set_trace(trace_cond);
bartecbf1662008-02-24 18:46:05 +0000112 if (trace_csw)
113 thread_trace_context_switches(trace_csw);
114 if (trace_danger_set)
115 thread_trace_danger_set(trace_danger_set);
sewardjaf44c822007-11-25 14:01:38 +0000116 if (trace_mutex)
117 mutex_set_trace(trace_mutex);
118 if (trace_segment)
119 sg_set_trace(trace_segment);
bart28230a32008-02-29 17:27:03 +0000120 if (trace_semaphore)
121 semaphore_set_trace(trace_semaphore);
sewardjaf44c822007-11-25 14:01:38 +0000122 if (trace_suppression)
123 suppression_set_trace(trace_suppression);
124
125 return True;
126}
127
128static void drd_print_usage(void)
129{
130 VG_(printf)(" --trace-mem=no|yes Trace all memory accesses to stdout[no]"
131 "\n"
132 " --trace-fork-join=no|yes Trace all thread creation and join"
133 " activity\n"
134 " --trace-mutex=no|yes Trace all mutex activity\n"
135 " --trace-segment=no|yes Trace segment actions\n"
136 );
137}
138
139static void drd_print_debug_usage(void)
140{
141}
142
143
144//
145// Implements the thread-related core callbacks.
146//
147
148static
149VG_REGPARM(2) void drd_trace_load(Addr addr, SizeT size)
150{
151 Segment* sg;
152
sewardj8b09d4f2007-12-04 21:27:18 +0000153 thread_set_vg_running_tid(VG_(get_running_tid)());
154
sewardjaf44c822007-11-25 14:01:38 +0000155 if (! thread_is_recording(thread_get_running_tid()))
156 return;
157
158#if 1
159 if (drd_trace_mem || (addr == drd_trace_address))
160 {
161 VG_(message)(Vg_UserMsg, "load 0x%lx size %ld %s (vg %d / drd %d)",
162 addr,
163 size,
164 thread_get_name(thread_get_running_tid()),
165 VG_(get_running_tid)(),
166 thread_get_running_tid());
sewardj85642922008-01-14 11:54:56 +0000167 VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(),
168 VG_(clo_backtrace_size));
sewardjaf44c822007-11-25 14:01:38 +0000169 tl_assert(DrdThreadIdToVgThreadId(thread_get_running_tid())
170 == VG_(get_running_tid)());
171 }
172#endif
173 sg = thread_get_segment(thread_get_running_tid());
174 bm_access_range(sg->bm, addr, size, eLoad);
175 if (thread_conflicting_access(addr, size, eLoad))
176 {
177 DataRaceErrInfo drei;
178 drei.tid = VG_(get_running_tid)();
179 drei.addr = addr;
180 drei.size = size;
181 drei.access_type = eLoad;
182 VG_(maybe_record_error)(VG_(get_running_tid)(),
183 DataRaceErr,
184 VG_(get_IP)(VG_(get_running_tid)()),
185 "Conflicting accesses",
186 &drei);
187 }
188}
189
190static
191VG_REGPARM(2) void drd_trace_store(Addr addr, SizeT size)
192{
193 Segment* sg;
194
sewardj8b09d4f2007-12-04 21:27:18 +0000195 thread_set_vg_running_tid(VG_(get_running_tid)());
196
sewardjaf44c822007-11-25 14:01:38 +0000197 if (! thread_is_recording(thread_get_running_tid()))
198 return;
199
200#if 1
201 if (drd_trace_mem || (addr == drd_trace_address))
202 {
203 VG_(message)(Vg_UserMsg, "store 0x%lx size %ld %s (vg %d / drd %d / off %d)",
204 addr,
205 size,
206 thread_get_name(thread_get_running_tid()),
207 VG_(get_running_tid)(),
208 thread_get_running_tid(),
209 addr - thread_get_stack_min(thread_get_running_tid()));
sewardj85642922008-01-14 11:54:56 +0000210 VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(),
211 VG_(clo_backtrace_size));
sewardjaf44c822007-11-25 14:01:38 +0000212 tl_assert(DrdThreadIdToVgThreadId(thread_get_running_tid())
213 == VG_(get_running_tid)());
214 }
215#endif
216 sg = thread_get_segment(thread_get_running_tid());
217 bm_access_range(sg->bm, addr, size, eStore);
218 if (thread_conflicting_access(addr, size, eStore))
219 {
220 DataRaceErrInfo drei;
221 drei.tid = VG_(get_running_tid)();
222 drei.addr = addr;
223 drei.size = size;
224 drei.access_type = eStore;
225 VG_(maybe_record_error)(VG_(get_running_tid)(),
226 DataRaceErr,
227 VG_(get_IP)(VG_(get_running_tid)()),
228 "Conflicting accesses",
229 &drei);
230 }
231}
232
233static void drd_pre_mem_read(const CorePart part,
234 const ThreadId tid,
235 Char* const s,
236 const Addr a,
237 const SizeT size)
238{
sewardj8b09d4f2007-12-04 21:27:18 +0000239 if (size > 0)
sewardjaf44c822007-11-25 14:01:38 +0000240 {
241 drd_trace_load(a, size);
242 }
243}
244
245static void drd_post_mem_write(const CorePart part,
246 const ThreadId tid,
247 const Addr a,
248 const SizeT size)
249{
sewardj8b09d4f2007-12-04 21:27:18 +0000250 if (size > 0)
sewardjaf44c822007-11-25 14:01:38 +0000251 {
252 drd_trace_store(a, size);
253 }
254}
255
256static void drd_start_using_mem(const Addr a1, const Addr a2)
257{
sewardj8b09d4f2007-12-04 21:27:18 +0000258 thread_set_vg_running_tid(VG_(get_running_tid)());
259
sewardjaf44c822007-11-25 14:01:38 +0000260 if (a1 <= drd_trace_address && drd_trace_address < a2
261 && thread_is_recording(thread_get_running_tid()))
262 {
263 VG_(message)(Vg_UserMsg, "start 0x%lx size %ld %s (tracing 0x%lx)",
264 a1, a2 - a1, thread_get_name(thread_get_running_tid()),
265 drd_trace_address);
sewardj85642922008-01-14 11:54:56 +0000266 VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(),
267 VG_(clo_backtrace_size));
sewardjaf44c822007-11-25 14:01:38 +0000268 }
269}
270
271static void drd_stop_using_mem(const Addr a1, const Addr a2)
272{
273 if (a1 <= drd_trace_address && drd_trace_address < a2
274 && thread_is_recording(thread_get_running_tid()))
275 {
276 VG_(message)(Vg_UserMsg, "end 0x%lx size %ld %s (tracing 0x%lx)",
277 a1, a2 - a1, thread_get_name(thread_get_running_tid()),
278 drd_trace_address);
sewardj85642922008-01-14 11:54:56 +0000279 VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(),
280 VG_(clo_backtrace_size));
sewardjaf44c822007-11-25 14:01:38 +0000281 }
282 thread_stop_using_mem(a1, a2);
bart4bb53d82008-02-28 19:06:34 +0000283 drd_clientobj_stop_using_mem(a1, a2);
sewardjaf44c822007-11-25 14:01:38 +0000284 drd_suppression_stop_using_mem(a1, a2);
285}
286
sewardjaf44c822007-11-25 14:01:38 +0000287/* Called by the core when the stack of a thread grows, to indicate that */
288/* the addresses in range [ a, a + len [ may now be used by the client. */
289/* Assumption: stacks grow downward. */
290static void drd_start_using_mem_stack(const Addr a, const SizeT len)
291{
292 thread_set_stack_min(thread_get_running_tid(), a - VG_STACK_REDZONE_SZB);
bart33cb9d02008-02-28 20:28:00 +0000293 drd_start_using_mem(a, a + len);
sewardjaf44c822007-11-25 14:01:38 +0000294}
295
296/* Called by the core when the stack of a thread shrinks, to indicate that */
297/* the addresses [ a, a + len [ are no longer accessible for the client. */
298/* Assumption: stacks grow downward. */
299static void drd_stop_using_mem_stack(const Addr a, const SizeT len)
300{
sewardj8b09d4f2007-12-04 21:27:18 +0000301 thread_set_vg_running_tid(VG_(get_running_tid)());
sewardjaf44c822007-11-25 14:01:38 +0000302 thread_set_stack_min(thread_get_running_tid(),
303 a + len - VG_STACK_REDZONE_SZB);
bart33cb9d02008-02-28 20:28:00 +0000304 drd_stop_using_mem(a, a + len);
sewardjaf44c822007-11-25 14:01:38 +0000305}
306
307static void drd_start_using_mem_mmap(Addr a, SizeT len,
308 Bool rr, Bool ww, Bool xx)
309{
310 drd_start_using_mem(a, a + len);
311}
312
313static void drd_stop_using_mem_munmap(Addr a, SizeT len)
314{
315 drd_stop_using_mem(a, a + len);
316}
317
318static
319void drd_pre_thread_create(const ThreadId creator, const ThreadId created)
320{
321 const DrdThreadId drd_creator = VgThreadIdToDrdThreadId(creator);
322 tl_assert(created != VG_INVALID_THREADID);
323 thread_pre_create(drd_creator, created);
sewardjaf44c822007-11-25 14:01:38 +0000324 if (IsValidDrdThreadId(drd_creator))
325 {
326 thread_new_segment(drd_creator);
327 }
328 if (drd_trace_fork_join)
329 {
330 VG_(message)(Vg_DebugMsg,
331 "drd_pre_thread_create creator = %d/%d, created = %d",
332 creator, drd_creator, created);
333 }
334}
335
336/* Called by Valgrind's core before any loads or stores are performed on */
337/* the context of thread "created". At startup, this function is called */
338/* with arguments (0,1). */
339static
340void drd_post_thread_create(const ThreadId created)
341{
342 const DrdThreadId drd_created = thread_post_create(created);
343 tl_assert(created != VG_INVALID_THREADID);
344 if (drd_trace_fork_join)
345 {
346 VG_(message)(Vg_DebugMsg,
347 "drd_post_thread_create created = %d/%d",
348 created, drd_created);
349 }
350}
351
352/* Process VG_USERREQ__POST_THREAD_JOIN. This client request is invoked just */
353/* after thread drd_joiner joined thread drd_joinee. */
354void drd_post_thread_join(DrdThreadId drd_joiner, DrdThreadId drd_joinee)
355{
356 tl_assert(IsValidDrdThreadId(drd_joiner));
357 tl_assert(IsValidDrdThreadId(drd_joinee));
358 thread_new_segment(drd_joinee);
359 thread_combine_vc(drd_joiner, drd_joinee);
360 thread_new_segment(drd_joiner);
361
362 if (drd_trace_fork_join)
363 {
364 char msg[256];
365 const ThreadId joiner = DrdThreadIdToVgThreadId(drd_joiner);
366 const ThreadId joinee = DrdThreadIdToVgThreadId(drd_joinee);
367 VG_(snprintf)(msg, sizeof(msg),
368 "drd_post_thread_join joiner = %d/%d, joinee = %d/%d",
369 joiner, drd_joiner, joinee, drd_joinee);
370 if (joiner)
371 {
372 VG_(snprintf)(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
373 ", new vc: ");
374 vc_snprint(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
375 thread_get_vc(drd_joiner));
376 }
377 VG_(message)(Vg_DebugMsg, msg);
378 }
379
380 thread_delete(drd_joinee);
381 mutex_thread_delete(drd_joinee);
sewardj85642922008-01-14 11:54:56 +0000382 cond_thread_delete(drd_joinee);
383 semaphore_thread_delete(drd_joinee);
384 barrier_thread_delete(drd_joinee);
sewardjaf44c822007-11-25 14:01:38 +0000385}
386
387/* Called after a thread has performed its last memory access. */
388static void drd_thread_finished(ThreadId tid)
389{
sewardj85642922008-01-14 11:54:56 +0000390 DrdThreadId drd_tid;
391
392 drd_set_running_tid(tid);
393
394 drd_tid = VgThreadIdToDrdThreadId(tid);
sewardjaf44c822007-11-25 14:01:38 +0000395 if (drd_trace_fork_join)
396 {
397 VG_(message)(Vg_DebugMsg,
398 "drd_thread_finished tid = %d/%d%s",
399 tid,
400 drd_tid,
401 thread_get_joinable(drd_tid)
402 ? ""
403 : " (which is a detached thread)");
404
405 }
406 thread_finished(drd_tid);
407}
408
sewardj347eeba2008-01-21 14:19:07 +0000409void drd_pre_mutex_init(const Addr mutex, const SizeT size,
410 const MutexT mutex_type)
sewardjaf44c822007-11-25 14:01:38 +0000411{
sewardj721ad7b2007-11-30 08:30:29 +0000412 mutex_init(mutex, size, mutex_type);
sewardjaf44c822007-11-25 14:01:38 +0000413}
414
sewardj347eeba2008-01-21 14:19:07 +0000415void drd_post_mutex_destroy(const Addr mutex, const MutexT mutex_type)
sewardjaf44c822007-11-25 14:01:38 +0000416{
sewardj347eeba2008-01-21 14:19:07 +0000417 mutex_post_destroy(mutex);
sewardjaf44c822007-11-25 14:01:38 +0000418}
419
420void drd_pre_mutex_lock(const DrdThreadId drd_tid,
421 const Addr mutex,
sewardj721ad7b2007-11-30 08:30:29 +0000422 const SizeT size,
423 const MutexT mutex_type)
sewardjaf44c822007-11-25 14:01:38 +0000424{
bart8bba1f72008-02-27 16:13:05 +0000425 mutex_pre_lock(mutex, size, mutex_type);
sewardjaf44c822007-11-25 14:01:38 +0000426}
427
428void drd_post_mutex_lock(const DrdThreadId drd_tid,
429 const Addr mutex,
sewardj721ad7b2007-11-30 08:30:29 +0000430 const SizeT size,
bart3b1ee452008-02-29 19:28:15 +0000431 const MutexT mutex_type,
432 const Bool took_lock)
sewardjaf44c822007-11-25 14:01:38 +0000433{
bart3b1ee452008-02-29 19:28:15 +0000434 mutex_post_lock(mutex, size, mutex_type, took_lock);
sewardjaf44c822007-11-25 14:01:38 +0000435}
436
sewardj721ad7b2007-11-30 08:30:29 +0000437void drd_pre_mutex_unlock(const DrdThreadId drd_tid,
438 const Addr mutex,
439 const MutexT mutex_type)
sewardjaf44c822007-11-25 14:01:38 +0000440{
sewardj721ad7b2007-11-30 08:30:29 +0000441 mutex_unlock(mutex, mutex_type);
sewardjaf44c822007-11-25 14:01:38 +0000442}
443
444void drd_post_cond_init(Addr cond, SizeT s)
445{
sewardjaf44c822007-11-25 14:01:38 +0000446 if (cond_get(cond))
447 {
448 CondErrInfo cei = { .cond = cond };
449 VG_(maybe_record_error)(VG_(get_running_tid)(),
450 CondErr,
451 VG_(get_IP)(VG_(get_running_tid)()),
452 "initialized twice",
453 &cei);
454 }
sewardj721ad7b2007-11-30 08:30:29 +0000455 cond_init(cond, s);
sewardjaf44c822007-11-25 14:01:38 +0000456}
457
sewardj721ad7b2007-11-30 08:30:29 +0000458void drd_pre_cond_destroy(Addr cond)
sewardjaf44c822007-11-25 14:01:38 +0000459{
460 struct cond_info* cond_p;
461
sewardjaf44c822007-11-25 14:01:38 +0000462 cond_p = cond_get(cond);
463 if (cond_p)
464 {
465 cond_destroy(cond_p);
466 }
467 else
468 {
469 CondErrInfo cei = { .cond = cond };
470 VG_(maybe_record_error)(VG_(get_running_tid)(),
471 CondErr,
472 VG_(get_IP)(VG_(get_running_tid)()),
473 "destroy requested but not initialized",
474 &cei);
475 }
476}
477
sewardj85642922008-01-14 11:54:56 +0000478void drd_semaphore_init(const Addr semaphore, const SizeT size,
479 const Word pshared, const Word value)
480{
481 semaphore_init(semaphore, size, pshared, value);
482}
483
484void drd_semaphore_destroy(const Addr semaphore)
485{
486 struct semaphore_info* p;
487
488 p = semaphore_get(semaphore);
489 tl_assert(p);
490 if (p)
491 {
492 semaphore_destroy(p);
493 }
494}
495
bart28230a32008-02-29 17:27:03 +0000496void drd_semaphore_pre_wait(const DrdThreadId tid, const Addr semaphore,
497 const SizeT size)
sewardj85642922008-01-14 11:54:56 +0000498{
bart28230a32008-02-29 17:27:03 +0000499 semaphore_pre_wait(semaphore, size);
500}
501
502void drd_semaphore_post_wait(const DrdThreadId tid, const Addr semaphore,
503 const Bool waited)
504{
505 semaphore_post_wait(tid, semaphore, waited);
sewardj85642922008-01-14 11:54:56 +0000506}
507
508void drd_semaphore_pre_post(const DrdThreadId tid, const Addr semaphore,
509 const SizeT size)
510{
511 semaphore_pre_post(tid, semaphore, size);
512}
513
514void drd_semaphore_post_post(const DrdThreadId tid, const Addr semaphore,
sewardje3b57aa2008-01-18 07:42:01 +0000515 const SizeT size, const Bool waited)
sewardj85642922008-01-14 11:54:56 +0000516{
sewardje3b57aa2008-01-18 07:42:01 +0000517 semaphore_post_post(tid, semaphore, size, waited);
sewardj85642922008-01-14 11:54:56 +0000518}
519
520
521void drd_barrier_init(const Addr barrier, const SizeT size, const Word count)
522{
523 barrier_init(barrier, size, count);
524}
525
526void drd_barrier_destroy(const Addr barrier)
527{
528 struct barrier_info* p;
529
530 p = barrier_get(barrier);
531 if (p)
532 {
533 barrier_destroy(p);
534 }
535}
536
537void drd_barrier_pre_wait(const DrdThreadId tid, const Addr barrier)
538{
539 barrier_pre_wait(tid, barrier);
540}
541
542void drd_barrier_post_wait(const DrdThreadId tid, const Addr barrier,
543 const Bool waited)
544{
545 barrier_post_wait(tid, barrier, waited);
546}
547
sewardjaf44c822007-11-25 14:01:38 +0000548
549//
550// Implementation of the tool interface.
551//
552
553static
554void drd_post_clo_init(void)
sewardjdcbb8d32007-11-26 21:34:30 +0000555{
556# if defined(VGP_x86_linux) || defined(VGP_amd64_linux)
557 /* fine */
558# else
sewardj8b09d4f2007-12-04 21:27:18 +0000559 VG_(printf)("\nWARNING: DRD has only been tested on x86-linux and amd64-linux.\n\n");
sewardjdcbb8d32007-11-26 21:34:30 +0000560# endif
561}
sewardjaf44c822007-11-25 14:01:38 +0000562
563static
564IRSB* drd_instrument(VgCallbackClosure* const closure,
sewardj347eeba2008-01-21 14:19:07 +0000565 IRSB* const bb_in,
566 VexGuestLayout* const layout,
567 VexGuestExtents* const vge,
568 IRType const gWordTy,
569 IRType const hWordTy)
sewardjaf44c822007-11-25 14:01:38 +0000570{
571 IRDirty* di;
572 Int i;
573 IRSB* bb;
574 IRExpr** argv;
575 IRExpr* addr_expr;
576 IRExpr* size_expr;
577 Bool instrument = True;
578
579 /* Set up BB */
580 bb = emptyIRSB();
581 bb->tyenv = deepCopyIRTypeEnv(bb_in->tyenv);
582 bb->next = deepCopyIRExpr(bb_in->next);
583 bb->jumpkind = bb_in->jumpkind;
584
585 for (i = 0; i < bb_in->stmts_used; i++)
586 {
587 IRStmt* const st = bb_in->stmts[i];
barteb8b8c82008-02-26 19:11:20 +0000588 tl_assert(st);
589 if (st->tag == Ist_NoOp)
sewardjaf44c822007-11-25 14:01:38 +0000590 continue;
591
592 switch (st->tag)
593 {
594 case Ist_IMark:
595 instrument = VG_(seginfo_sect_kind)(st->Ist.IMark.addr) != Vg_SectPLT;
596 break;
597
barteb8b8c82008-02-26 19:11:20 +0000598 case Ist_MBE:
599 instrument_memory_bus_event(bb, st->Ist.MBE.event);
600 addStmtToIRSB(bb, st);
601 break;
602
sewardjaf44c822007-11-25 14:01:38 +0000603 case Ist_Store:
604 if (instrument)
605 {
606 addr_expr = st->Ist.Store.addr;
607 size_expr = mkIRExpr_HWord(
608 sizeofIRType(typeOfIRExpr(bb->tyenv, st->Ist.Store.data)));
609 argv = mkIRExprVec_2(addr_expr, size_expr);
610 di = unsafeIRDirty_0_N(/*regparms*/2,
611 "drd_trace_store",
612 VG_(fnptr_to_fnentry)(drd_trace_store),
613 argv);
614 addStmtToIRSB(bb, IRStmt_Dirty(di));
615 }
616 addStmtToIRSB(bb, st);
617 break;
618
619 case Ist_WrTmp:
620 if (instrument)
621 {
622 const IRExpr* const data = st->Ist.WrTmp.data;
623 if (data->tag == Iex_Load)
624 {
625 addr_expr = data->Iex.Load.addr;
626 size_expr = mkIRExpr_HWord(sizeofIRType(data->Iex.Load.ty));
627 argv = mkIRExprVec_2(addr_expr, size_expr);
628 di = unsafeIRDirty_0_N(/*regparms*/2,
629 "drd_trace_load",
630 VG_(fnptr_to_fnentry)(drd_trace_load),
631 argv);
632 addStmtToIRSB(bb, IRStmt_Dirty(di));
633 }
634 }
635 addStmtToIRSB(bb, st);
636 break;
637
638 case Ist_Dirty:
639 if (instrument)
640 {
641 IRDirty* d = st->Ist.Dirty.details;
642 IREffect const mFx = d->mFx;
643 switch (mFx) {
644 case Ifx_None:
645 break;
646 case Ifx_Read:
647 case Ifx_Write:
648 case Ifx_Modify:
649 tl_assert(d->mAddr);
650 tl_assert(d->mSize > 0);
651 argv = mkIRExprVec_2(d->mAddr, mkIRExpr_HWord(d->mSize));
652 if (mFx == Ifx_Read || mFx == Ifx_Modify) {
653 di = unsafeIRDirty_0_N(
654 /*regparms*/2,
655 "drd_trace_load",
656 VG_(fnptr_to_fnentry)(drd_trace_load),
657 argv);
658 addStmtToIRSB(bb, IRStmt_Dirty(di));
659 }
660 if (mFx == Ifx_Write || mFx == Ifx_Modify) {
661 di = unsafeIRDirty_0_N(
662 /*regparms*/2,
663 "drd_trace_store",
664 VG_(fnptr_to_fnentry)(drd_trace_store),
665 argv);
666 addStmtToIRSB(bb, IRStmt_Dirty(di));
667 }
668 break;
669 default:
670 tl_assert(0);
671 }
672 }
673 addStmtToIRSB(bb, st);
674 break;
675
676 default:
677 addStmtToIRSB(bb, st);
678 break;
679 }
680 }
681
682 return bb;
683}
684
barteb8b8c82008-02-26 19:11:20 +0000685/* Based on the function with the same name in Helgrind's hg_main.c */
686static void instrument_memory_bus_event(IRSB* const bb,
bartbbb67992008-03-01 07:41:17 +0000687 const IRMBusEvent event)
barteb8b8c82008-02-26 19:11:20 +0000688{
689 switch (event)
690 {
691 case Imbe_Fence:
692 break; /* not interesting */
693 case Imbe_BusLock:
694 addStmtToIRSB(bb,
695 IRStmt_Dirty(unsafeIRDirty_0_N(0/*regparms*/, "evh__bus_lock",
696 VG_(fnptr_to_fnentry)(&evh__bus_lock), mkIRExprVec_0())
697 ));
698 break;
699 case Imbe_BusUnlock:
700 addStmtToIRSB(bb,
701 IRStmt_Dirty(unsafeIRDirty_0_N(0/*regparms*/, "evh__bus_unlock",
702 VG_(fnptr_to_fnentry)(&evh__bus_unlock), mkIRExprVec_0())
703 ));
704 break;
705 default:
706 tl_assert(0);
707 }
708}
709
710/** Locking the memory bus is a way to serialize store operations.
711 * What the lwarx / stwcx instructions do on PowerPC is to detect whether
712 * any other CPU has invalidated the cache line in which the location
713 * specified by lwarx resides has been invalidated at the time the stwcx
714 * instruction is executed.
715 */
716static void evh__bus_lock(void)
717{
718 /* To do: implement this function. */
719}
720
721static void evh__bus_unlock(void)
722{
723 /* To do: implement this function. */
724}
725
sewardj8b09d4f2007-12-04 21:27:18 +0000726static void drd_set_running_tid(const ThreadId vg_tid)
sewardjaf44c822007-11-25 14:01:38 +0000727{
sewardj8b09d4f2007-12-04 21:27:18 +0000728 static ThreadId s_last_vg_tid = VG_INVALID_THREADID;
729 if (vg_tid != s_last_vg_tid)
sewardjaf44c822007-11-25 14:01:38 +0000730 {
sewardj8b09d4f2007-12-04 21:27:18 +0000731 const DrdThreadId drd_tid = VgThreadIdToDrdThreadId(vg_tid);
sewardjaf44c822007-11-25 14:01:38 +0000732 tl_assert(drd_tid != DRD_INVALID_THREADID);
sewardj8b09d4f2007-12-04 21:27:18 +0000733 s_last_vg_tid = vg_tid;
sewardjaf44c822007-11-25 14:01:38 +0000734 if (drd_trace_fork_join)
735 {
736 VG_(message)(Vg_DebugMsg,
737 "drd_track_thread_run tid = %d / drd tid %d",
sewardj8b09d4f2007-12-04 21:27:18 +0000738 vg_tid, drd_tid);
sewardjaf44c822007-11-25 14:01:38 +0000739 }
sewardj8b09d4f2007-12-04 21:27:18 +0000740 thread_set_running_tid(vg_tid, drd_tid);
sewardjaf44c822007-11-25 14:01:38 +0000741 }
742}
743
744static void drd_start_client_code(const ThreadId tid, const ULong bbs_done)
745{
746 drd_set_running_tid(tid);
747}
748
749static
750void drd_fini(Int exitcode)
751{
752 // thread_print_all();
sewardjaf44c822007-11-25 14:01:38 +0000753 if (VG_(clo_verbosity) > 1 || drd_print_stats)
754 {
755 VG_(message)(Vg_DebugMsg,
756 " thread: %lld context switches"
757 " / %lld updates of the danger set",
758 thread_get_context_switch_count(),
759 thread_get_update_danger_set_count());
sewardjaf44c822007-11-25 14:01:38 +0000760 VG_(message)(Vg_DebugMsg,
761 " segments: %lld total, %lld max, %lld discard points",
762 sg_get_segments_created_count(),
763 sg_get_max_segments_alive_count(),
764 thread_get_discard_ordered_segments_count());
765 VG_(message)(Vg_DebugMsg,
766 " bitmaps: %lld / %lld bitmaps were allocated"
767 " and %lld / %lld for danger set updates",
768 bm_get_bitmap_creation_count(),
769 bm_get_bitmap2_creation_count(),
770 thread_get_danger_set_bitmap_creation_count(),
771 thread_get_danger_set_bitmap2_creation_count());
772 VG_(message)(Vg_DebugMsg,
773 " mutex: %lld non-recursive lock/unlock events",
774 get_mutex_lock_count());
775 drd_print_malloc_stats();
776 }
777}
778
sewardjaf44c822007-11-25 14:01:38 +0000779static
780void drd_pre_clo_init(void)
781{
782 // Basic tool stuff.
783
784 VG_(details_name) ("exp-drd");
785 VG_(details_version) (NULL);
786 VG_(details_description) ("a data race detector");
sewardj85642922008-01-14 11:54:56 +0000787 VG_(details_copyright_author)("Copyright (C) 2006-2008, and GNU GPL'd,"
sewardjaf44c822007-11-25 14:01:38 +0000788 " by Bart Van Assche.");
789 VG_(details_bug_reports_to) (VG_BUGS_TO);
790
791 VG_(basic_tool_funcs) (drd_post_clo_init,
792 drd_instrument,
793 drd_fini);
794
795 // Command line stuff.
796 VG_(needs_command_line_options)(drd_process_cmd_line_option,
797 drd_print_usage,
798 drd_print_debug_usage);
799
800 drd_register_error_handlers();
801
802 // Core event tracking.
803 VG_(track_pre_mem_read) (drd_pre_mem_read);
804 VG_(track_post_mem_write) (drd_post_mem_write);
805 VG_(track_new_mem_stack) (drd_start_using_mem_stack);
806 VG_(track_die_mem_stack) (drd_stop_using_mem_stack);
807 VG_(track_new_mem_mmap) (drd_start_using_mem_mmap);
808 VG_(track_die_mem_munmap) (drd_stop_using_mem_munmap);
809 VG_(track_start_client_code) (drd_start_client_code);
810 VG_(track_pre_thread_ll_create) (drd_pre_thread_create);
811 VG_(track_pre_thread_first_insn)(drd_post_thread_create);
812 VG_(track_pre_thread_ll_exit) (drd_thread_finished);
813
814 // Other stuff.
815 VG_(needs_data_syms)();
816
817 drd_register_malloc_wrappers(drd_start_using_mem, drd_stop_using_mem);
818
819 drd_clientreq_init();
820
821 drd_suppression_init();
bart4bb53d82008-02-28 19:06:34 +0000822
823 drd_clientobj_init();
sewardjaf44c822007-11-25 14:01:38 +0000824}
825
826
827VG_DETERMINE_INTERFACE_VERSION(drd_pre_clo_init)
828
829
830/*
831 * Local variables:
832 * c-basic-offset: 3
833 * End:
834 */