blob: 67b583f8f56a7ca1cee69eac2c00c115f8948e8b [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
bart5e85d262008-03-01 10:49:37 +0000153 tl_assert(thread_get_running_tid()
154 == VgThreadIdToDrdThreadId(VG_(get_running_tid())));
sewardjaf44c822007-11-25 14:01:38 +0000155
156#if 1
157 if (drd_trace_mem || (addr == drd_trace_address))
158 {
159 VG_(message)(Vg_UserMsg, "load 0x%lx size %ld %s (vg %d / drd %d)",
160 addr,
161 size,
162 thread_get_name(thread_get_running_tid()),
163 VG_(get_running_tid)(),
164 thread_get_running_tid());
sewardj85642922008-01-14 11:54:56 +0000165 VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(),
166 VG_(clo_backtrace_size));
sewardjaf44c822007-11-25 14:01:38 +0000167 tl_assert(DrdThreadIdToVgThreadId(thread_get_running_tid())
168 == VG_(get_running_tid)());
169 }
170#endif
171 sg = thread_get_segment(thread_get_running_tid());
172 bm_access_range(sg->bm, addr, size, eLoad);
173 if (thread_conflicting_access(addr, size, eLoad))
174 {
175 DataRaceErrInfo drei;
176 drei.tid = VG_(get_running_tid)();
177 drei.addr = addr;
178 drei.size = size;
179 drei.access_type = eLoad;
180 VG_(maybe_record_error)(VG_(get_running_tid)(),
181 DataRaceErr,
182 VG_(get_IP)(VG_(get_running_tid)()),
183 "Conflicting accesses",
184 &drei);
185 }
186}
187
188static
189VG_REGPARM(2) void drd_trace_store(Addr addr, SizeT size)
190{
191 Segment* sg;
192
bart5e85d262008-03-01 10:49:37 +0000193 tl_assert(thread_get_running_tid()
194 == VgThreadIdToDrdThreadId(VG_(get_running_tid())));
sewardjaf44c822007-11-25 14:01:38 +0000195
196#if 1
197 if (drd_trace_mem || (addr == drd_trace_address))
198 {
199 VG_(message)(Vg_UserMsg, "store 0x%lx size %ld %s (vg %d / drd %d / off %d)",
200 addr,
201 size,
202 thread_get_name(thread_get_running_tid()),
203 VG_(get_running_tid)(),
204 thread_get_running_tid(),
205 addr - thread_get_stack_min(thread_get_running_tid()));
sewardj85642922008-01-14 11:54:56 +0000206 VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(),
207 VG_(clo_backtrace_size));
sewardjaf44c822007-11-25 14:01:38 +0000208 tl_assert(DrdThreadIdToVgThreadId(thread_get_running_tid())
209 == VG_(get_running_tid)());
210 }
211#endif
212 sg = thread_get_segment(thread_get_running_tid());
213 bm_access_range(sg->bm, addr, size, eStore);
214 if (thread_conflicting_access(addr, size, eStore))
215 {
216 DataRaceErrInfo drei;
217 drei.tid = VG_(get_running_tid)();
218 drei.addr = addr;
219 drei.size = size;
220 drei.access_type = eStore;
221 VG_(maybe_record_error)(VG_(get_running_tid)(),
222 DataRaceErr,
223 VG_(get_IP)(VG_(get_running_tid)()),
224 "Conflicting accesses",
225 &drei);
226 }
227}
228
229static void drd_pre_mem_read(const CorePart part,
230 const ThreadId tid,
231 Char* const s,
232 const Addr a,
233 const SizeT size)
234{
sewardj8b09d4f2007-12-04 21:27:18 +0000235 if (size > 0)
sewardjaf44c822007-11-25 14:01:38 +0000236 {
237 drd_trace_load(a, size);
238 }
239}
240
bart5e85d262008-03-01 10:49:37 +0000241static void drd_pre_mem_read_asciiz(const CorePart part,
242 const ThreadId tid,
243 Char* const s,
244 const Addr a)
245{
246 const char* p = (void*)a;
247 SizeT size = 0;
248
249 /* Note: the expression '*p' reads client memory and may crash if the */
250 /* client provided an invalid pointer ! */
251 while (*p)
252 {
253 p++;
254 size++;
255 }
256 // To do: find out what a reasonable upper limit on 'size' is.
257 tl_assert(size < 4096);
258 if (size > 0)
259 {
260 drd_trace_load(a, size);
261 }
262}
263
sewardjaf44c822007-11-25 14:01:38 +0000264static void drd_post_mem_write(const CorePart part,
265 const ThreadId tid,
266 const Addr a,
267 const SizeT size)
268{
bart5e85d262008-03-01 10:49:37 +0000269 thread_set_vg_running_tid(VG_(get_running_tid)());
sewardj8b09d4f2007-12-04 21:27:18 +0000270 if (size > 0)
sewardjaf44c822007-11-25 14:01:38 +0000271 {
272 drd_trace_store(a, size);
273 }
274}
275
bart5e85d262008-03-01 10:49:37 +0000276static void drd_start_using_mem(const Addr a1, const SizeT len)
sewardjaf44c822007-11-25 14:01:38 +0000277{
bart5e85d262008-03-01 10:49:37 +0000278 const Addr a2 = a1 + len;
279
280 tl_assert(a1 < a2);
281
sewardj8b09d4f2007-12-04 21:27:18 +0000282 thread_set_vg_running_tid(VG_(get_running_tid)());
283
bart5e85d262008-03-01 10:49:37 +0000284 if (a1 <= drd_trace_address && drd_trace_address < a2)
sewardjaf44c822007-11-25 14:01:38 +0000285 {
286 VG_(message)(Vg_UserMsg, "start 0x%lx size %ld %s (tracing 0x%lx)",
287 a1, a2 - a1, thread_get_name(thread_get_running_tid()),
288 drd_trace_address);
sewardj85642922008-01-14 11:54:56 +0000289 VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(),
290 VG_(clo_backtrace_size));
sewardjaf44c822007-11-25 14:01:38 +0000291 }
292}
293
bart5e85d262008-03-01 10:49:37 +0000294static void drd_stop_using_mem(const Addr a1, const SizeT len)
sewardjaf44c822007-11-25 14:01:38 +0000295{
bart5e85d262008-03-01 10:49:37 +0000296 const Addr a2 = a1 + len;
297
298 tl_assert(a1 < a2);
299
300 if (a1 <= drd_trace_address && drd_trace_address < a2)
sewardjaf44c822007-11-25 14:01:38 +0000301 {
302 VG_(message)(Vg_UserMsg, "end 0x%lx size %ld %s (tracing 0x%lx)",
303 a1, a2 - a1, thread_get_name(thread_get_running_tid()),
304 drd_trace_address);
sewardj85642922008-01-14 11:54:56 +0000305 VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(),
306 VG_(clo_backtrace_size));
sewardjaf44c822007-11-25 14:01:38 +0000307 }
308 thread_stop_using_mem(a1, a2);
bart4bb53d82008-02-28 19:06:34 +0000309 drd_clientobj_stop_using_mem(a1, a2);
sewardjaf44c822007-11-25 14:01:38 +0000310 drd_suppression_stop_using_mem(a1, a2);
311}
312
bart5e85d262008-03-01 10:49:37 +0000313static
314void drd_start_using_mem_w_perms(const Addr a, const SizeT len,
315 const Bool rr, const Bool ww, const Bool xx)
316{
317 drd_start_using_mem(a, len);
318}
319
sewardjaf44c822007-11-25 14:01:38 +0000320/* Called by the core when the stack of a thread grows, to indicate that */
321/* the addresses in range [ a, a + len [ may now be used by the client. */
322/* Assumption: stacks grow downward. */
323static void drd_start_using_mem_stack(const Addr a, const SizeT len)
324{
325 thread_set_stack_min(thread_get_running_tid(), a - VG_STACK_REDZONE_SZB);
bart5e85d262008-03-01 10:49:37 +0000326 drd_start_using_mem(a, len);
sewardjaf44c822007-11-25 14:01:38 +0000327}
328
329/* Called by the core when the stack of a thread shrinks, to indicate that */
330/* the addresses [ a, a + len [ are no longer accessible for the client. */
331/* Assumption: stacks grow downward. */
332static void drd_stop_using_mem_stack(const Addr a, const SizeT len)
333{
sewardj8b09d4f2007-12-04 21:27:18 +0000334 thread_set_vg_running_tid(VG_(get_running_tid)());
sewardjaf44c822007-11-25 14:01:38 +0000335 thread_set_stack_min(thread_get_running_tid(),
336 a + len - VG_STACK_REDZONE_SZB);
bart5e85d262008-03-01 10:49:37 +0000337 drd_stop_using_mem(a, len);
sewardjaf44c822007-11-25 14:01:38 +0000338}
339
bart5e85d262008-03-01 10:49:37 +0000340static void drd_start_using_mem_stack_signal(const Addr a, const SizeT len)
sewardjaf44c822007-11-25 14:01:38 +0000341{
bart5e85d262008-03-01 10:49:37 +0000342 drd_start_using_mem(a, len);
sewardjaf44c822007-11-25 14:01:38 +0000343}
344
bart5e85d262008-03-01 10:49:37 +0000345static void drd_stop_using_mem_stack_signal(Addr a, SizeT len)
sewardjaf44c822007-11-25 14:01:38 +0000346{
bart5e85d262008-03-01 10:49:37 +0000347 drd_stop_using_mem(a, len);
sewardjaf44c822007-11-25 14:01:38 +0000348}
349
350static
351void drd_pre_thread_create(const ThreadId creator, const ThreadId created)
352{
353 const DrdThreadId drd_creator = VgThreadIdToDrdThreadId(creator);
354 tl_assert(created != VG_INVALID_THREADID);
355 thread_pre_create(drd_creator, created);
sewardjaf44c822007-11-25 14:01:38 +0000356 if (IsValidDrdThreadId(drd_creator))
357 {
358 thread_new_segment(drd_creator);
359 }
360 if (drd_trace_fork_join)
361 {
362 VG_(message)(Vg_DebugMsg,
363 "drd_pre_thread_create creator = %d/%d, created = %d",
364 creator, drd_creator, created);
365 }
366}
367
368/* Called by Valgrind's core before any loads or stores are performed on */
369/* the context of thread "created". At startup, this function is called */
370/* with arguments (0,1). */
371static
372void drd_post_thread_create(const ThreadId created)
373{
374 const DrdThreadId drd_created = thread_post_create(created);
375 tl_assert(created != VG_INVALID_THREADID);
376 if (drd_trace_fork_join)
377 {
378 VG_(message)(Vg_DebugMsg,
379 "drd_post_thread_create created = %d/%d",
380 created, drd_created);
381 }
382}
383
384/* Process VG_USERREQ__POST_THREAD_JOIN. This client request is invoked just */
385/* after thread drd_joiner joined thread drd_joinee. */
386void drd_post_thread_join(DrdThreadId drd_joiner, DrdThreadId drd_joinee)
387{
388 tl_assert(IsValidDrdThreadId(drd_joiner));
389 tl_assert(IsValidDrdThreadId(drd_joinee));
390 thread_new_segment(drd_joinee);
391 thread_combine_vc(drd_joiner, drd_joinee);
392 thread_new_segment(drd_joiner);
393
394 if (drd_trace_fork_join)
395 {
396 char msg[256];
397 const ThreadId joiner = DrdThreadIdToVgThreadId(drd_joiner);
398 const ThreadId joinee = DrdThreadIdToVgThreadId(drd_joinee);
399 VG_(snprintf)(msg, sizeof(msg),
400 "drd_post_thread_join joiner = %d/%d, joinee = %d/%d",
401 joiner, drd_joiner, joinee, drd_joinee);
402 if (joiner)
403 {
404 VG_(snprintf)(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
405 ", new vc: ");
406 vc_snprint(msg + VG_(strlen)(msg), sizeof(msg) - VG_(strlen)(msg),
407 thread_get_vc(drd_joiner));
408 }
409 VG_(message)(Vg_DebugMsg, msg);
410 }
411
412 thread_delete(drd_joinee);
413 mutex_thread_delete(drd_joinee);
sewardj85642922008-01-14 11:54:56 +0000414 cond_thread_delete(drd_joinee);
415 semaphore_thread_delete(drd_joinee);
416 barrier_thread_delete(drd_joinee);
sewardjaf44c822007-11-25 14:01:38 +0000417}
418
419/* Called after a thread has performed its last memory access. */
420static void drd_thread_finished(ThreadId tid)
421{
sewardj85642922008-01-14 11:54:56 +0000422 DrdThreadId drd_tid;
423
424 drd_set_running_tid(tid);
425
426 drd_tid = VgThreadIdToDrdThreadId(tid);
sewardjaf44c822007-11-25 14:01:38 +0000427 if (drd_trace_fork_join)
428 {
429 VG_(message)(Vg_DebugMsg,
430 "drd_thread_finished tid = %d/%d%s",
431 tid,
432 drd_tid,
433 thread_get_joinable(drd_tid)
434 ? ""
435 : " (which is a detached thread)");
436
437 }
438 thread_finished(drd_tid);
439}
440
sewardj347eeba2008-01-21 14:19:07 +0000441void drd_pre_mutex_init(const Addr mutex, const SizeT size,
442 const MutexT mutex_type)
sewardjaf44c822007-11-25 14:01:38 +0000443{
sewardj721ad7b2007-11-30 08:30:29 +0000444 mutex_init(mutex, size, mutex_type);
sewardjaf44c822007-11-25 14:01:38 +0000445}
446
sewardj347eeba2008-01-21 14:19:07 +0000447void drd_post_mutex_destroy(const Addr mutex, const MutexT mutex_type)
sewardjaf44c822007-11-25 14:01:38 +0000448{
sewardj347eeba2008-01-21 14:19:07 +0000449 mutex_post_destroy(mutex);
sewardjaf44c822007-11-25 14:01:38 +0000450}
451
452void drd_pre_mutex_lock(const DrdThreadId drd_tid,
453 const Addr mutex,
sewardj721ad7b2007-11-30 08:30:29 +0000454 const SizeT size,
455 const MutexT mutex_type)
sewardjaf44c822007-11-25 14:01:38 +0000456{
bart8bba1f72008-02-27 16:13:05 +0000457 mutex_pre_lock(mutex, size, mutex_type);
sewardjaf44c822007-11-25 14:01:38 +0000458}
459
460void drd_post_mutex_lock(const DrdThreadId drd_tid,
461 const Addr mutex,
sewardj721ad7b2007-11-30 08:30:29 +0000462 const SizeT size,
bart3b1ee452008-02-29 19:28:15 +0000463 const MutexT mutex_type,
464 const Bool took_lock)
sewardjaf44c822007-11-25 14:01:38 +0000465{
bart3b1ee452008-02-29 19:28:15 +0000466 mutex_post_lock(mutex, size, mutex_type, took_lock);
sewardjaf44c822007-11-25 14:01:38 +0000467}
468
sewardj721ad7b2007-11-30 08:30:29 +0000469void drd_pre_mutex_unlock(const DrdThreadId drd_tid,
470 const Addr mutex,
471 const MutexT mutex_type)
sewardjaf44c822007-11-25 14:01:38 +0000472{
sewardj721ad7b2007-11-30 08:30:29 +0000473 mutex_unlock(mutex, mutex_type);
sewardjaf44c822007-11-25 14:01:38 +0000474}
475
476void drd_post_cond_init(Addr cond, SizeT s)
477{
sewardjaf44c822007-11-25 14:01:38 +0000478 if (cond_get(cond))
479 {
480 CondErrInfo cei = { .cond = cond };
481 VG_(maybe_record_error)(VG_(get_running_tid)(),
482 CondErr,
483 VG_(get_IP)(VG_(get_running_tid)()),
484 "initialized twice",
485 &cei);
486 }
sewardj721ad7b2007-11-30 08:30:29 +0000487 cond_init(cond, s);
sewardjaf44c822007-11-25 14:01:38 +0000488}
489
sewardj721ad7b2007-11-30 08:30:29 +0000490void drd_pre_cond_destroy(Addr cond)
sewardjaf44c822007-11-25 14:01:38 +0000491{
492 struct cond_info* cond_p;
493
sewardjaf44c822007-11-25 14:01:38 +0000494 cond_p = cond_get(cond);
495 if (cond_p)
496 {
497 cond_destroy(cond_p);
498 }
499 else
500 {
501 CondErrInfo cei = { .cond = cond };
502 VG_(maybe_record_error)(VG_(get_running_tid)(),
503 CondErr,
504 VG_(get_IP)(VG_(get_running_tid)()),
505 "destroy requested but not initialized",
506 &cei);
507 }
508}
509
sewardj85642922008-01-14 11:54:56 +0000510void drd_semaphore_init(const Addr semaphore, const SizeT size,
511 const Word pshared, const Word value)
512{
513 semaphore_init(semaphore, size, pshared, value);
514}
515
516void drd_semaphore_destroy(const Addr semaphore)
517{
518 struct semaphore_info* p;
519
520 p = semaphore_get(semaphore);
521 tl_assert(p);
522 if (p)
523 {
524 semaphore_destroy(p);
525 }
526}
527
bart28230a32008-02-29 17:27:03 +0000528void drd_semaphore_pre_wait(const DrdThreadId tid, const Addr semaphore,
529 const SizeT size)
sewardj85642922008-01-14 11:54:56 +0000530{
bart28230a32008-02-29 17:27:03 +0000531 semaphore_pre_wait(semaphore, size);
532}
533
534void drd_semaphore_post_wait(const DrdThreadId tid, const Addr semaphore,
535 const Bool waited)
536{
537 semaphore_post_wait(tid, semaphore, waited);
sewardj85642922008-01-14 11:54:56 +0000538}
539
540void drd_semaphore_pre_post(const DrdThreadId tid, const Addr semaphore,
541 const SizeT size)
542{
543 semaphore_pre_post(tid, semaphore, size);
544}
545
546void drd_semaphore_post_post(const DrdThreadId tid, const Addr semaphore,
sewardje3b57aa2008-01-18 07:42:01 +0000547 const SizeT size, const Bool waited)
sewardj85642922008-01-14 11:54:56 +0000548{
sewardje3b57aa2008-01-18 07:42:01 +0000549 semaphore_post_post(tid, semaphore, size, waited);
sewardj85642922008-01-14 11:54:56 +0000550}
551
552
553void drd_barrier_init(const Addr barrier, const SizeT size, const Word count)
554{
555 barrier_init(barrier, size, count);
556}
557
558void drd_barrier_destroy(const Addr barrier)
559{
560 struct barrier_info* p;
561
562 p = barrier_get(barrier);
563 if (p)
564 {
565 barrier_destroy(p);
566 }
567}
568
569void drd_barrier_pre_wait(const DrdThreadId tid, const Addr barrier)
570{
571 barrier_pre_wait(tid, barrier);
572}
573
574void drd_barrier_post_wait(const DrdThreadId tid, const Addr barrier,
575 const Bool waited)
576{
577 barrier_post_wait(tid, barrier, waited);
578}
579
sewardjaf44c822007-11-25 14:01:38 +0000580
581//
582// Implementation of the tool interface.
583//
584
585static
586void drd_post_clo_init(void)
sewardjdcbb8d32007-11-26 21:34:30 +0000587{
588# if defined(VGP_x86_linux) || defined(VGP_amd64_linux)
589 /* fine */
590# else
sewardj8b09d4f2007-12-04 21:27:18 +0000591 VG_(printf)("\nWARNING: DRD has only been tested on x86-linux and amd64-linux.\n\n");
sewardjdcbb8d32007-11-26 21:34:30 +0000592# endif
593}
sewardjaf44c822007-11-25 14:01:38 +0000594
595static
596IRSB* drd_instrument(VgCallbackClosure* const closure,
sewardj347eeba2008-01-21 14:19:07 +0000597 IRSB* const bb_in,
598 VexGuestLayout* const layout,
599 VexGuestExtents* const vge,
600 IRType const gWordTy,
601 IRType const hWordTy)
sewardjaf44c822007-11-25 14:01:38 +0000602{
603 IRDirty* di;
604 Int i;
605 IRSB* bb;
606 IRExpr** argv;
607 IRExpr* addr_expr;
608 IRExpr* size_expr;
609 Bool instrument = True;
610
611 /* Set up BB */
612 bb = emptyIRSB();
613 bb->tyenv = deepCopyIRTypeEnv(bb_in->tyenv);
614 bb->next = deepCopyIRExpr(bb_in->next);
615 bb->jumpkind = bb_in->jumpkind;
616
617 for (i = 0; i < bb_in->stmts_used; i++)
618 {
619 IRStmt* const st = bb_in->stmts[i];
barteb8b8c82008-02-26 19:11:20 +0000620 tl_assert(st);
621 if (st->tag == Ist_NoOp)
sewardjaf44c822007-11-25 14:01:38 +0000622 continue;
623
624 switch (st->tag)
625 {
626 case Ist_IMark:
627 instrument = VG_(seginfo_sect_kind)(st->Ist.IMark.addr) != Vg_SectPLT;
628 break;
629
barteb8b8c82008-02-26 19:11:20 +0000630 case Ist_MBE:
631 instrument_memory_bus_event(bb, st->Ist.MBE.event);
632 addStmtToIRSB(bb, st);
633 break;
634
sewardjaf44c822007-11-25 14:01:38 +0000635 case Ist_Store:
636 if (instrument)
637 {
638 addr_expr = st->Ist.Store.addr;
639 size_expr = mkIRExpr_HWord(
640 sizeofIRType(typeOfIRExpr(bb->tyenv, st->Ist.Store.data)));
641 argv = mkIRExprVec_2(addr_expr, size_expr);
642 di = unsafeIRDirty_0_N(/*regparms*/2,
643 "drd_trace_store",
644 VG_(fnptr_to_fnentry)(drd_trace_store),
645 argv);
646 addStmtToIRSB(bb, IRStmt_Dirty(di));
647 }
648 addStmtToIRSB(bb, st);
649 break;
650
651 case Ist_WrTmp:
652 if (instrument)
653 {
654 const IRExpr* const data = st->Ist.WrTmp.data;
655 if (data->tag == Iex_Load)
656 {
657 addr_expr = data->Iex.Load.addr;
658 size_expr = mkIRExpr_HWord(sizeofIRType(data->Iex.Load.ty));
659 argv = mkIRExprVec_2(addr_expr, size_expr);
660 di = unsafeIRDirty_0_N(/*regparms*/2,
661 "drd_trace_load",
662 VG_(fnptr_to_fnentry)(drd_trace_load),
663 argv);
664 addStmtToIRSB(bb, IRStmt_Dirty(di));
665 }
666 }
667 addStmtToIRSB(bb, st);
668 break;
669
670 case Ist_Dirty:
671 if (instrument)
672 {
673 IRDirty* d = st->Ist.Dirty.details;
674 IREffect const mFx = d->mFx;
675 switch (mFx) {
676 case Ifx_None:
677 break;
678 case Ifx_Read:
679 case Ifx_Write:
680 case Ifx_Modify:
681 tl_assert(d->mAddr);
682 tl_assert(d->mSize > 0);
683 argv = mkIRExprVec_2(d->mAddr, mkIRExpr_HWord(d->mSize));
684 if (mFx == Ifx_Read || mFx == Ifx_Modify) {
685 di = unsafeIRDirty_0_N(
686 /*regparms*/2,
687 "drd_trace_load",
688 VG_(fnptr_to_fnentry)(drd_trace_load),
689 argv);
690 addStmtToIRSB(bb, IRStmt_Dirty(di));
691 }
692 if (mFx == Ifx_Write || mFx == Ifx_Modify) {
693 di = unsafeIRDirty_0_N(
694 /*regparms*/2,
695 "drd_trace_store",
696 VG_(fnptr_to_fnentry)(drd_trace_store),
697 argv);
698 addStmtToIRSB(bb, IRStmt_Dirty(di));
699 }
700 break;
701 default:
702 tl_assert(0);
703 }
704 }
705 addStmtToIRSB(bb, st);
706 break;
707
708 default:
709 addStmtToIRSB(bb, st);
710 break;
711 }
712 }
713
714 return bb;
715}
716
barteb8b8c82008-02-26 19:11:20 +0000717/* Based on the function with the same name in Helgrind's hg_main.c */
718static void instrument_memory_bus_event(IRSB* const bb,
bartbbb67992008-03-01 07:41:17 +0000719 const IRMBusEvent event)
barteb8b8c82008-02-26 19:11:20 +0000720{
721 switch (event)
722 {
723 case Imbe_Fence:
724 break; /* not interesting */
725 case Imbe_BusLock:
726 addStmtToIRSB(bb,
727 IRStmt_Dirty(unsafeIRDirty_0_N(0/*regparms*/, "evh__bus_lock",
728 VG_(fnptr_to_fnentry)(&evh__bus_lock), mkIRExprVec_0())
729 ));
730 break;
731 case Imbe_BusUnlock:
732 addStmtToIRSB(bb,
733 IRStmt_Dirty(unsafeIRDirty_0_N(0/*regparms*/, "evh__bus_unlock",
734 VG_(fnptr_to_fnentry)(&evh__bus_unlock), mkIRExprVec_0())
735 ));
736 break;
737 default:
738 tl_assert(0);
739 }
740}
741
742/** Locking the memory bus is a way to serialize store operations.
743 * What the lwarx / stwcx instructions do on PowerPC is to detect whether
744 * any other CPU has invalidated the cache line in which the location
745 * specified by lwarx resides has been invalidated at the time the stwcx
746 * instruction is executed.
747 */
748static void evh__bus_lock(void)
749{
750 /* To do: implement this function. */
751}
752
753static void evh__bus_unlock(void)
754{
755 /* To do: implement this function. */
756}
757
sewardj8b09d4f2007-12-04 21:27:18 +0000758static void drd_set_running_tid(const ThreadId vg_tid)
sewardjaf44c822007-11-25 14:01:38 +0000759{
sewardj8b09d4f2007-12-04 21:27:18 +0000760 static ThreadId s_last_vg_tid = VG_INVALID_THREADID;
761 if (vg_tid != s_last_vg_tid)
sewardjaf44c822007-11-25 14:01:38 +0000762 {
sewardj8b09d4f2007-12-04 21:27:18 +0000763 const DrdThreadId drd_tid = VgThreadIdToDrdThreadId(vg_tid);
sewardjaf44c822007-11-25 14:01:38 +0000764 tl_assert(drd_tid != DRD_INVALID_THREADID);
sewardj8b09d4f2007-12-04 21:27:18 +0000765 s_last_vg_tid = vg_tid;
sewardjaf44c822007-11-25 14:01:38 +0000766 if (drd_trace_fork_join)
767 {
768 VG_(message)(Vg_DebugMsg,
769 "drd_track_thread_run tid = %d / drd tid %d",
sewardj8b09d4f2007-12-04 21:27:18 +0000770 vg_tid, drd_tid);
sewardjaf44c822007-11-25 14:01:38 +0000771 }
sewardj8b09d4f2007-12-04 21:27:18 +0000772 thread_set_running_tid(vg_tid, drd_tid);
sewardjaf44c822007-11-25 14:01:38 +0000773 }
774}
775
776static void drd_start_client_code(const ThreadId tid, const ULong bbs_done)
777{
778 drd_set_running_tid(tid);
779}
780
781static
782void drd_fini(Int exitcode)
783{
784 // thread_print_all();
sewardjaf44c822007-11-25 14:01:38 +0000785 if (VG_(clo_verbosity) > 1 || drd_print_stats)
786 {
787 VG_(message)(Vg_DebugMsg,
788 " thread: %lld context switches"
789 " / %lld updates of the danger set",
790 thread_get_context_switch_count(),
791 thread_get_update_danger_set_count());
sewardjaf44c822007-11-25 14:01:38 +0000792 VG_(message)(Vg_DebugMsg,
793 " segments: %lld total, %lld max, %lld discard points",
794 sg_get_segments_created_count(),
795 sg_get_max_segments_alive_count(),
796 thread_get_discard_ordered_segments_count());
797 VG_(message)(Vg_DebugMsg,
798 " bitmaps: %lld / %lld bitmaps were allocated"
799 " and %lld / %lld for danger set updates",
800 bm_get_bitmap_creation_count(),
801 bm_get_bitmap2_creation_count(),
802 thread_get_danger_set_bitmap_creation_count(),
803 thread_get_danger_set_bitmap2_creation_count());
804 VG_(message)(Vg_DebugMsg,
805 " mutex: %lld non-recursive lock/unlock events",
806 get_mutex_lock_count());
807 drd_print_malloc_stats();
808 }
809}
810
sewardjaf44c822007-11-25 14:01:38 +0000811static
812void drd_pre_clo_init(void)
813{
814 // Basic tool stuff.
815
816 VG_(details_name) ("exp-drd");
817 VG_(details_version) (NULL);
818 VG_(details_description) ("a data race detector");
sewardj85642922008-01-14 11:54:56 +0000819 VG_(details_copyright_author)("Copyright (C) 2006-2008, and GNU GPL'd,"
sewardjaf44c822007-11-25 14:01:38 +0000820 " by Bart Van Assche.");
821 VG_(details_bug_reports_to) (VG_BUGS_TO);
822
823 VG_(basic_tool_funcs) (drd_post_clo_init,
824 drd_instrument,
825 drd_fini);
826
827 // Command line stuff.
828 VG_(needs_command_line_options)(drd_process_cmd_line_option,
829 drd_print_usage,
830 drd_print_debug_usage);
831
bart5e85d262008-03-01 10:49:37 +0000832 // Error handling.
sewardjaf44c822007-11-25 14:01:38 +0000833 drd_register_error_handlers();
834
835 // Core event tracking.
836 VG_(track_pre_mem_read) (drd_pre_mem_read);
bart5e85d262008-03-01 10:49:37 +0000837 VG_(track_pre_mem_read_asciiz) (drd_pre_mem_read_asciiz);
sewardjaf44c822007-11-25 14:01:38 +0000838 VG_(track_post_mem_write) (drd_post_mem_write);
bart5e85d262008-03-01 10:49:37 +0000839 VG_(track_new_mem_brk) (drd_start_using_mem);
840 VG_(track_new_mem_mmap) (drd_start_using_mem_w_perms);
sewardjaf44c822007-11-25 14:01:38 +0000841 VG_(track_new_mem_stack) (drd_start_using_mem_stack);
bart5e85d262008-03-01 10:49:37 +0000842 VG_(track_new_mem_stack_signal) (drd_start_using_mem_stack_signal);
843 VG_(track_new_mem_startup) (drd_start_using_mem_w_perms);
844 VG_(track_die_mem_brk) (drd_stop_using_mem);
845 VG_(track_die_mem_munmap) (drd_stop_using_mem);
sewardjaf44c822007-11-25 14:01:38 +0000846 VG_(track_die_mem_stack) (drd_stop_using_mem_stack);
bart5e85d262008-03-01 10:49:37 +0000847 VG_(track_die_mem_stack_signal) (drd_stop_using_mem_stack_signal);
sewardjaf44c822007-11-25 14:01:38 +0000848 VG_(track_start_client_code) (drd_start_client_code);
849 VG_(track_pre_thread_ll_create) (drd_pre_thread_create);
850 VG_(track_pre_thread_first_insn)(drd_post_thread_create);
851 VG_(track_pre_thread_ll_exit) (drd_thread_finished);
852
853 // Other stuff.
854 VG_(needs_data_syms)();
855
856 drd_register_malloc_wrappers(drd_start_using_mem, drd_stop_using_mem);
857
858 drd_clientreq_init();
859
860 drd_suppression_init();
bart4bb53d82008-02-28 19:06:34 +0000861
862 drd_clientobj_init();
sewardjaf44c822007-11-25 14:01:38 +0000863}
864
865
866VG_DETERMINE_INTERFACE_VERSION(drd_pre_clo_init)
867
868
869/*
870 * Local variables:
871 * c-basic-offset: 3
872 * End:
873 */