| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 1 | /* | 
 | 2 |   This file is part of drd, a data race detector. | 
 | 3 |  | 
| sewardj | 8564292 | 2008-01-14 11:54:56 +0000 | [diff] [blame] | 4 |   Copyright (C) 2006-2008 Bart Van Assche | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 5 |   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 |  | 
| sewardj | 8564292 | 2008-01-14 11:54:56 +0000 | [diff] [blame] | 26 | #include "drd_barrier.h" | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 27 | #include "drd_clientreq.h" | 
| bart | 4bb53d8 | 2008-02-28 19:06:34 +0000 | [diff] [blame] | 28 | #include "drd_clientobj.h" | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 29 | #include "drd_cond.h" | 
 | 30 | #include "drd_error.h" | 
 | 31 | #include "drd_malloc_wrappers.h" | 
 | 32 | #include "drd_mutex.h" | 
| bart | 5bd9f2d | 2008-03-03 20:31:58 +0000 | [diff] [blame] | 33 | #include "drd_rwlock.h" | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 34 | #include "drd_segment.h" | 
| sewardj | 8564292 | 2008-01-14 11:54:56 +0000 | [diff] [blame] | 35 | #include "drd_semaphore.h" | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 36 | #include "drd_suppression.h" | 
 | 37 | #include "drd_thread.h" | 
| bart | d59bb0f | 2008-06-08 08:08:31 +0000 | [diff] [blame] | 38 | #include "drd_thread_bitmap.h" | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 39 | #include "drd_track.h" | 
 | 40 | #include "drd_vc.h" | 
| bart | eacd916 | 2008-06-16 20:22:18 +0000 | [diff] [blame] | 41 | #include "libvex_guest_offsets.h" | 
| sewardj | 8564292 | 2008-01-14 11:54:56 +0000 | [diff] [blame] | 42 | #include "pub_drd_bitmap.h" | 
| bart | 024a95a | 2008-04-01 18:27:41 +0000 | [diff] [blame] | 43 | #include "pub_tool_vki.h"         // Must be included before pub_tool_libcproc | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 44 | #include "pub_tool_basics.h" | 
 | 45 | #include "pub_tool_debuginfo.h"   // VG_(describe_IP)() | 
 | 46 | #include "pub_tool_libcassert.h"  // tl_assert() | 
 | 47 | #include "pub_tool_libcbase.h"    // VG_(strcmp) | 
 | 48 | #include "pub_tool_libcprint.h"   // VG_(printf) | 
 | 49 | #include "pub_tool_libcproc.h" | 
 | 50 | #include "pub_tool_machine.h" | 
| bart | 024a95a | 2008-04-01 18:27:41 +0000 | [diff] [blame] | 51 | #include "pub_tool_mallocfree.h"  // VG_(malloc)(), VG_(free)() | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 52 | #include "pub_tool_options.h"     // command line options | 
| bart | ceded21 | 2008-03-26 17:39:52 +0000 | [diff] [blame] | 53 | #include "pub_tool_replacemalloc.h" | 
| bart | 72b751c | 2008-03-01 13:44:24 +0000 | [diff] [blame] | 54 | #include "pub_tool_threadstate.h" // VG_(get_running_tid)() | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 55 | #include "pub_tool_tooliface.h" | 
 | 56 |  | 
 | 57 |  | 
| bart | bf80e12 | 2008-06-06 10:18:24 +0000 | [diff] [blame] | 58 | /* Include several source files here in order to allow the compiler to */ | 
 | 59 | /* do more inlining.                                                   */ | 
 | 60 | #include "drd_bitmap.c" | 
 | 61 | #include "drd_segment.c" | 
 | 62 | #include "drd_thread.c" | 
 | 63 | #include "drd_vc.c" | 
 | 64 |  | 
 | 65 |  | 
 | 66 |  | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 67 | // Function declarations. | 
 | 68 |  | 
 | 69 | static void drd_start_client_code(const ThreadId tid, const ULong bbs_done); | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 70 |  | 
 | 71 |  | 
 | 72 | // Local variables. | 
 | 73 |  | 
| bart | 0886562 | 2008-06-06 14:31:36 +0000 | [diff] [blame] | 74 | static Bool s_drd_check_stack_accesses = False; | 
 | 75 | static Bool s_drd_print_stats          = False; | 
 | 76 | static Bool s_drd_trace_fork_join      = False; | 
 | 77 | static Bool s_drd_var_info             = False; | 
 | 78 | static Bool s_show_stack_usage         = False; | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 79 |  | 
 | 80 |  | 
 | 81 | // | 
 | 82 | // Implement the needs_command_line_options for drd. | 
 | 83 | // | 
 | 84 |  | 
 | 85 | static Bool drd_process_cmd_line_option(Char* arg) | 
 | 86 | { | 
| bart | 9d5b796 | 2008-05-14 12:25:00 +0000 | [diff] [blame] | 87 |   int exclusive_threshold_ms = -1; | 
| bart | 0886562 | 2008-06-06 14:31:36 +0000 | [diff] [blame] | 88 |   int segment_merging        = -1; | 
| bart | 9d5b796 | 2008-05-14 12:25:00 +0000 | [diff] [blame] | 89 |   int shared_threshold_ms    = -1; | 
| bart | 0886562 | 2008-06-06 14:31:36 +0000 | [diff] [blame] | 90 |   int show_confl_seg         = -1; | 
 | 91 |   int trace_barrier          = -1; | 
 | 92 |   int trace_clientobj        = -1; | 
 | 93 |   int trace_cond             = -1; | 
 | 94 |   int trace_csw              = -1; | 
| bart | e73b0aa | 2008-06-28 07:19:56 +0000 | [diff] [blame] | 95 |   int trace_conflict_set     = -1; | 
| bart | 0886562 | 2008-06-06 14:31:36 +0000 | [diff] [blame] | 96 |   int trace_mutex            = -1; | 
 | 97 |   int trace_rwlock           = -1; | 
 | 98 |   int trace_segment          = -1; | 
 | 99 |   int trace_semaphore        = -1; | 
 | 100 |   int trace_suppression      = -1; | 
 | 101 |   Char* trace_address        = 0; | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 102 |  | 
| bart | 0886562 | 2008-06-06 14:31:36 +0000 | [diff] [blame] | 103 |   VG_BOOL_CLO     (arg, "--check-stack-var",     s_drd_check_stack_accesses) | 
| bart | 9d5b796 | 2008-05-14 12:25:00 +0000 | [diff] [blame] | 104 |   else VG_BOOL_CLO(arg, "--drd-stats",           s_drd_print_stats) | 
| bart | 46b5fce | 2008-06-28 13:01:30 +0000 | [diff] [blame] | 105 |   else VG_BOOL_CLO(arg,"--report-signal-unlocked",s_drd_report_signal_unlocked) | 
| bart | 9d5b796 | 2008-05-14 12:25:00 +0000 | [diff] [blame] | 106 |   else VG_BOOL_CLO(arg, "--segment-merging",     segment_merging) | 
 | 107 |   else VG_BOOL_CLO(arg, "--show-confl-seg",      show_confl_seg) | 
 | 108 |   else VG_BOOL_CLO(arg, "--show-stack-usage",    s_show_stack_usage) | 
 | 109 |   else VG_BOOL_CLO(arg, "--trace-barrier",       trace_barrier) | 
 | 110 |   else VG_BOOL_CLO(arg, "--trace-clientobj",     trace_clientobj) | 
 | 111 |   else VG_BOOL_CLO(arg, "--trace-cond",          trace_cond) | 
| bart | e73b0aa | 2008-06-28 07:19:56 +0000 | [diff] [blame] | 112 |   else VG_BOOL_CLO(arg, "--trace-conflict-set",  trace_conflict_set) | 
| bart | 46b5fce | 2008-06-28 13:01:30 +0000 | [diff] [blame] | 113 |   else VG_BOOL_CLO(arg, "--trace-csw",           trace_csw) | 
| bart | 9d5b796 | 2008-05-14 12:25:00 +0000 | [diff] [blame] | 114 |   else VG_BOOL_CLO(arg, "--trace-fork-join",     s_drd_trace_fork_join) | 
 | 115 |   else VG_BOOL_CLO(arg, "--trace-mutex",         trace_mutex) | 
 | 116 |   else VG_BOOL_CLO(arg, "--trace-rwlock",        trace_rwlock) | 
 | 117 |   else VG_BOOL_CLO(arg, "--trace-segment",       trace_segment) | 
 | 118 |   else VG_BOOL_CLO(arg, "--trace-semaphore",     trace_semaphore) | 
 | 119 |   else VG_BOOL_CLO(arg, "--trace-suppr",         trace_suppression) | 
 | 120 |   else VG_BOOL_CLO(arg, "--var-info",            s_drd_var_info) | 
 | 121 |   else VG_NUM_CLO (arg, "--exclusive-threshold", exclusive_threshold_ms) | 
 | 122 |   else VG_NUM_CLO (arg, "--shared-threshold",    shared_threshold_ms) | 
 | 123 |   else VG_STR_CLO (arg, "--trace-addr",          trace_address) | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 124 |   else | 
| bart | ceded21 | 2008-03-26 17:39:52 +0000 | [diff] [blame] | 125 |     return VG_(replacement_malloc_process_cmd_line_option)(arg); | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 126 |  | 
| bart | 9d5b796 | 2008-05-14 12:25:00 +0000 | [diff] [blame] | 127 |   if (exclusive_threshold_ms != -1) | 
 | 128 |   { | 
 | 129 |     mutex_set_lock_threshold(exclusive_threshold_ms); | 
 | 130 |     rwlock_set_exclusive_threshold(exclusive_threshold_ms); | 
 | 131 |   } | 
 | 132 |   if (shared_threshold_ms != -1) | 
 | 133 |   { | 
 | 134 |     rwlock_set_shared_threshold(shared_threshold_ms); | 
 | 135 |   } | 
| bart | a9c3739 | 2008-03-22 09:38:48 +0000 | [diff] [blame] | 136 |   if (segment_merging != -1) | 
 | 137 |     thread_set_segment_merging(segment_merging); | 
 | 138 |   if (show_confl_seg != -1) | 
| bart | 16d76e5 | 2008-03-18 17:08:08 +0000 | [diff] [blame] | 139 |     set_show_conflicting_segments(show_confl_seg); | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 140 |   if (trace_address) | 
 | 141 |   { | 
| bart | 005dc97 | 2008-03-29 14:42:59 +0000 | [diff] [blame] | 142 |     const Addr addr = VG_(strtoll16)(trace_address, 0); | 
 | 143 |     drd_start_tracing_address_range(addr, addr + 1); | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 144 |   } | 
| bart | a9c3739 | 2008-03-22 09:38:48 +0000 | [diff] [blame] | 145 |   if (trace_barrier != -1) | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 146 |     barrier_set_trace(trace_barrier); | 
| bart | a9c3739 | 2008-03-22 09:38:48 +0000 | [diff] [blame] | 147 |   if (trace_clientobj != -1) | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 148 |     clientobj_set_trace(trace_clientobj); | 
| bart | a9c3739 | 2008-03-22 09:38:48 +0000 | [diff] [blame] | 149 |   if (trace_cond != -1) | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 150 |     cond_set_trace(trace_cond); | 
| bart | a9c3739 | 2008-03-22 09:38:48 +0000 | [diff] [blame] | 151 |   if (trace_csw != -1) | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 152 |     thread_trace_context_switches(trace_csw); | 
| bart | e73b0aa | 2008-06-28 07:19:56 +0000 | [diff] [blame] | 153 |   if (trace_conflict_set != -1) | 
 | 154 |     thread_trace_conflict_set(trace_conflict_set); | 
| bart | a9c3739 | 2008-03-22 09:38:48 +0000 | [diff] [blame] | 155 |   if (trace_mutex != -1) | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 156 |     mutex_set_trace(trace_mutex); | 
| bart | a9c3739 | 2008-03-22 09:38:48 +0000 | [diff] [blame] | 157 |   if (trace_rwlock != -1) | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 158 |     rwlock_set_trace(trace_rwlock); | 
| bart | a9c3739 | 2008-03-22 09:38:48 +0000 | [diff] [blame] | 159 |   if (trace_segment != -1) | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 160 |     sg_set_trace(trace_segment); | 
| bart | a9c3739 | 2008-03-22 09:38:48 +0000 | [diff] [blame] | 161 |   if (trace_semaphore != -1) | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 162 |     semaphore_set_trace(trace_semaphore); | 
| bart | a9c3739 | 2008-03-22 09:38:48 +0000 | [diff] [blame] | 163 |   if (trace_suppression != -1) | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 164 |     suppression_set_trace(trace_suppression); | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 165 |  | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 166 |   return True; | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 167 | } | 
 | 168 |  | 
 | 169 | static void drd_print_usage(void) | 
| bart | bd7e56e | 2008-03-31 18:14:12 +0000 | [diff] [blame] | 170 | { | 
 | 171 |   VG_(printf)( | 
| bart | 0ffa483 | 2008-04-05 12:57:01 +0000 | [diff] [blame] | 172 | "    --check-stack-var=yes|no  Whether or not to report data races on\n" | 
 | 173 | "                              stack variables [no].\n" | 
| bart | 9d5b796 | 2008-05-14 12:25:00 +0000 | [diff] [blame] | 174 | "    --exclusive-threshold=<n> Print an error message if any mutex or\n" | 
 | 175 | "        writer lock is held longer than the specified time (in milliseconds).\n" | 
| bart | 46b5fce | 2008-06-28 13:01:30 +0000 | [diff] [blame] | 176 | "    --report-signal-unlocked=yes|no Whether to report calls to\n" | 
 | 177 | "                              pthread_cond_signal() where the mutex associated\n" | 
 | 178 | "                              with the signal via pthread_cond_wait() is not\n" | 
 | 179 | "                              locked at the time the signal is sent [yes].\n" | 
| bart | 130463a | 2008-04-01 17:03:33 +0000 | [diff] [blame] | 180 | "    --segment-merging=yes|no  Controls segment merging [yes].\n" | 
| bart | bd7e56e | 2008-03-31 18:14:12 +0000 | [diff] [blame] | 181 | "        Segment merging is an algorithm to limit memory usage of the\n" | 
 | 182 | "        data race detection algorithm. Disabling segment merging may\n" | 
 | 183 | "        improve the accuracy of the so-called 'other segments' displayed\n" | 
 | 184 | "        in race reports but can also trigger an out of memory error.\n" | 
| bart | 9d5b796 | 2008-05-14 12:25:00 +0000 | [diff] [blame] | 185 | "    --shared-threshold=<n>    Print an error message if a reader lock\n" | 
 | 186 | "        is held longer than the specified time (in milliseconds).\n" | 
| bart | 130463a | 2008-04-01 17:03:33 +0000 | [diff] [blame] | 187 | "    --show-confl-seg=yes|no   Show conflicting segments in race reports [yes].\n" | 
 | 188 | "    --show-stack-usage=yes|no Print stack usage at thread exit time [no].\n" | 
 | 189 | "    --var-info=yes|no         Display the names of global, static and\n" | 
| bart | bd7e56e | 2008-03-31 18:14:12 +0000 | [diff] [blame] | 190 | "        stack variables when a race is reported on such a variable. This\n" | 
 | 191 | "        information is by default not displayed since for big programs\n" | 
| bart | 85d2253 | 2008-06-26 07:30:32 +0000 | [diff] [blame] | 192 | "        reading in all debug information at once may cause an out of\n" | 
 | 193 | "        memory error [no].\n" | 
| bart | bd7e56e | 2008-03-31 18:14:12 +0000 | [diff] [blame] | 194 | "\n" | 
| bart | ef1b972 | 2008-07-04 15:34:23 +0000 | [diff] [blame^] | 195 | "  drd options for monitoring process behavior:\n" | 
| bart | 952e1a0 | 2008-04-06 13:06:36 +0000 | [diff] [blame] | 196 | "    --trace-addr=<address>    Trace all load and store activity for the.\n" | 
| bart | 130463a | 2008-04-01 17:03:33 +0000 | [diff] [blame] | 197 | "                              specified address [off].\n" | 
 | 198 | "    --trace-barrier=yes|no    Trace all barrier activity [no].\n" | 
 | 199 | "    --trace-cond=yes|no       Trace all condition variable activity [no].\n" | 
 | 200 | "    --trace-fork-join=yes|no  Trace all thread fork/join activity [no].\n" | 
 | 201 | "    --trace-mutex=yes|no      Trace all mutex activity [no].\n" | 
 | 202 | "    --trace-rwlock=yes|no     Trace all reader-writer lock activity[no].\n" | 
| bart | 130463a | 2008-04-01 17:03:33 +0000 | [diff] [blame] | 203 | "    --trace-semaphore=yes|no  Trace all semaphore activity [no].\n" | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 204 |               ); | 
| bart | 130463a | 2008-04-01 17:03:33 +0000 | [diff] [blame] | 205 |    VG_(replacement_malloc_print_usage)(); | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 206 | } | 
 | 207 |  | 
 | 208 | static void drd_print_debug_usage(void) | 
 | 209 | {   | 
| bart | 130463a | 2008-04-01 17:03:33 +0000 | [diff] [blame] | 210 |   VG_(printf)( | 
 | 211 | "    --drd-stats=yes|no        Print statistics about DRD activity [no].\n" | 
 | 212 | "    --trace-clientobj=yes|no  Trace all client object activity [no].\n" | 
 | 213 | "    --trace-csw=yes|no        Trace all scheduler context switches [no].\n" | 
| bart | e73b0aa | 2008-06-28 07:19:56 +0000 | [diff] [blame] | 214 | "    --trace-conflict-set=yes|no Trace all conflict set updates [no].\n" | 
| bart | 987781d | 2008-06-27 15:00:07 +0000 | [diff] [blame] | 215 | "    --trace-segment=yes|no    Trace segment actions [no].\n" | 
 | 216 | "    --trace-suppr=yes|no      Trace all address suppression actions [no].\n" | 
| bart | 130463a | 2008-04-01 17:03:33 +0000 | [diff] [blame] | 217 |               ); | 
 | 218 |    VG_(replacement_malloc_print_debug_usage)(); | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 219 | } | 
 | 220 |  | 
 | 221 |  | 
 | 222 | // | 
 | 223 | // Implements the thread-related core callbacks. | 
 | 224 | // | 
 | 225 |  | 
| bart | a79df6e | 2008-03-14 17:07:51 +0000 | [diff] [blame] | 226 | static void drd_trace_mem_access(const Addr addr, const SizeT size, | 
 | 227 |                                  const BmAccessTypeT access_type) | 
 | 228 | { | 
| bart | b9c7d74 | 2008-06-10 12:51:51 +0000 | [diff] [blame] | 229 |   if (drd_is_any_traced(addr, addr + size)) | 
 | 230 |   { | 
 | 231 |     char vc[80]; | 
 | 232 |     vc_snprint(vc, sizeof(vc), thread_get_vc(thread_get_running_tid())); | 
 | 233 |     VG_(message)(Vg_UserMsg, | 
 | 234 |                  "%s 0x%lx size %ld (vg %d / drd %d / vc %s)", | 
 | 235 |                  access_type == eLoad | 
 | 236 |                  ? "load " | 
 | 237 |                  : access_type == eStore | 
 | 238 |                  ? "store" | 
 | 239 |                  : access_type == eStart | 
 | 240 |                  ? "start" | 
 | 241 |                  : access_type == eEnd | 
 | 242 |                  ? "end  " | 
 | 243 |                  : "????", | 
 | 244 |                  addr, | 
 | 245 |                  size, | 
 | 246 |                  VG_(get_running_tid)(), | 
 | 247 |                  thread_get_running_tid(), | 
 | 248 |                  vc); | 
 | 249 |     VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(), | 
 | 250 |                                VG_(clo_backtrace_size)); | 
 | 251 |     tl_assert(DrdThreadIdToVgThreadId(thread_get_running_tid()) | 
 | 252 |               == VG_(get_running_tid)()); | 
 | 253 |   } | 
| bart | a79df6e | 2008-03-14 17:07:51 +0000 | [diff] [blame] | 254 | } | 
 | 255 |  | 
| bart | 29a0e2a | 2008-06-10 13:55:13 +0000 | [diff] [blame] | 256 | static VG_REGPARM(2) void drd_trace_mem_load(const Addr addr, const SizeT size) | 
 | 257 | { | 
 | 258 |   return drd_trace_mem_access(addr, size, eLoad); | 
 | 259 | } | 
 | 260 |  | 
 | 261 | static VG_REGPARM(2) void drd_trace_mem_store(const Addr addr,const SizeT size) | 
 | 262 | { | 
 | 263 |   return drd_trace_mem_access(addr, size, eStore); | 
 | 264 | } | 
 | 265 |  | 
| bart | a79df6e | 2008-03-14 17:07:51 +0000 | [diff] [blame] | 266 | static void drd_report_race(const Addr addr, const SizeT size, | 
 | 267 |                             const BmAccessTypeT access_type) | 
 | 268 | { | 
| bart | 49c3a11 | 2008-03-15 10:28:36 +0000 | [diff] [blame] | 269 |   DataRaceErrInfo drei; | 
 | 270 |  | 
| bart | 354009c | 2008-03-16 10:42:33 +0000 | [diff] [blame] | 271 |   drei.tid  = thread_get_running_tid(); | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 272 |   drei.addr = addr; | 
 | 273 |   drei.size = size; | 
 | 274 |   drei.access_type = access_type; | 
 | 275 |   VG_(maybe_record_error)(VG_(get_running_tid)(), | 
 | 276 |                           DataRaceErr, | 
 | 277 |                           VG_(get_IP)(VG_(get_running_tid)()), | 
 | 278 |                           "Conflicting accesses", | 
 | 279 |                           &drei); | 
| bart | a79df6e | 2008-03-14 17:07:51 +0000 | [diff] [blame] | 280 | } | 
 | 281 |  | 
 | 282 | static VG_REGPARM(2) void drd_trace_load(Addr addr, SizeT size) | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 283 | { | 
| bart | 8b4b2ee | 2008-06-11 13:17:56 +0000 | [diff] [blame] | 284 | #ifdef ENABLE_DRD_CONSISTENCY_CHECKS | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 285 |   /* The assert below has been commented out because of performance reasons.*/ | 
 | 286 |   tl_assert(thread_get_running_tid() | 
 | 287 |             == VgThreadIdToDrdThreadId(VG_(get_running_tid()))); | 
| bart | f00a85b | 2008-03-13 18:49:23 +0000 | [diff] [blame] | 288 | #endif | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 289 |  | 
| bart | 0e5c04f | 2008-06-09 15:18:59 +0000 | [diff] [blame] | 290 |   if (running_thread_is_recording() | 
 | 291 |       && (s_drd_check_stack_accesses || ! thread_address_on_stack(addr)) | 
| bart | 3e3296d | 2008-06-08 11:21:34 +0000 | [diff] [blame] | 292 |       && bm_access_load_triggers_conflict(addr, addr + size) | 
 | 293 |       && ! drd_is_suppressed(addr, addr + size)) | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 294 |   { | 
 | 295 |     drd_report_race(addr, size, eLoad); | 
 | 296 |   } | 
| bart | a79df6e | 2008-03-14 17:07:51 +0000 | [diff] [blame] | 297 | } | 
 | 298 |  | 
 | 299 | static VG_REGPARM(1) void drd_trace_load_1(Addr addr) | 
 | 300 | { | 
| bart | 0e5c04f | 2008-06-09 15:18:59 +0000 | [diff] [blame] | 301 |   if (running_thread_is_recording() | 
 | 302 |       && (s_drd_check_stack_accesses || ! thread_address_on_stack(addr)) | 
| bart | 3e3296d | 2008-06-08 11:21:34 +0000 | [diff] [blame] | 303 |       && bm_access_load_1_triggers_conflict(addr) | 
 | 304 |       && ! drd_is_suppressed(addr, addr + 1)) | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 305 |   { | 
 | 306 |     drd_report_race(addr, 1, eLoad); | 
 | 307 |   } | 
| bart | a79df6e | 2008-03-14 17:07:51 +0000 | [diff] [blame] | 308 | } | 
 | 309 |  | 
 | 310 | static VG_REGPARM(1) void drd_trace_load_2(Addr addr) | 
 | 311 | { | 
| bart | 0e5c04f | 2008-06-09 15:18:59 +0000 | [diff] [blame] | 312 |   if (running_thread_is_recording() | 
 | 313 |       && (s_drd_check_stack_accesses || ! thread_address_on_stack(addr)) | 
| bart | 3e3296d | 2008-06-08 11:21:34 +0000 | [diff] [blame] | 314 |       && bm_access_load_2_triggers_conflict(addr) | 
 | 315 |       && ! drd_is_suppressed(addr, addr + 2)) | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 316 |   { | 
 | 317 |     drd_report_race(addr, 2, eLoad); | 
 | 318 |   } | 
| bart | a79df6e | 2008-03-14 17:07:51 +0000 | [diff] [blame] | 319 | } | 
 | 320 |  | 
 | 321 | static VG_REGPARM(1) void drd_trace_load_4(Addr addr) | 
 | 322 | { | 
| bart | 0e5c04f | 2008-06-09 15:18:59 +0000 | [diff] [blame] | 323 |   if (running_thread_is_recording() | 
 | 324 |       && (s_drd_check_stack_accesses || ! thread_address_on_stack(addr)) | 
| bart | 3e3296d | 2008-06-08 11:21:34 +0000 | [diff] [blame] | 325 |       && bm_access_load_4_triggers_conflict(addr) | 
 | 326 |       && ! drd_is_suppressed(addr, addr + 4)) | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 327 |   { | 
 | 328 |     drd_report_race(addr, 4, eLoad); | 
 | 329 |   } | 
| bart | a79df6e | 2008-03-14 17:07:51 +0000 | [diff] [blame] | 330 | } | 
 | 331 |  | 
 | 332 | static VG_REGPARM(1) void drd_trace_load_8(Addr addr) | 
 | 333 | { | 
| bart | 0e5c04f | 2008-06-09 15:18:59 +0000 | [diff] [blame] | 334 |   if (running_thread_is_recording() | 
 | 335 |       && (s_drd_check_stack_accesses || ! thread_address_on_stack(addr)) | 
| bart | 3e3296d | 2008-06-08 11:21:34 +0000 | [diff] [blame] | 336 |       && bm_access_load_8_triggers_conflict(addr) | 
 | 337 |       && ! drd_is_suppressed(addr, addr + 8)) | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 338 |   { | 
 | 339 |     drd_report_race(addr, 8, eLoad); | 
 | 340 |   } | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 341 | } | 
 | 342 |  | 
 | 343 | static | 
 | 344 | VG_REGPARM(2) void drd_trace_store(Addr addr, SizeT size) | 
 | 345 | { | 
| bart | 8b4b2ee | 2008-06-11 13:17:56 +0000 | [diff] [blame] | 346 | #ifdef ENABLE_DRD_CONSISTENCY_CHECKS | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 347 |   /* The assert below has been commented out because of performance reasons.*/ | 
 | 348 |   tl_assert(thread_get_running_tid() | 
 | 349 |             == VgThreadIdToDrdThreadId(VG_(get_running_tid()))); | 
| bart | f00a85b | 2008-03-13 18:49:23 +0000 | [diff] [blame] | 350 | #endif | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 351 |  | 
| bart | 0e5c04f | 2008-06-09 15:18:59 +0000 | [diff] [blame] | 352 |   if (running_thread_is_recording() | 
 | 353 |       && (s_drd_check_stack_accesses || ! thread_address_on_stack(addr)) | 
| bart | 3e3296d | 2008-06-08 11:21:34 +0000 | [diff] [blame] | 354 |       && bm_access_store_triggers_conflict(addr, addr + size) | 
 | 355 |       && ! drd_is_suppressed(addr, addr + size)) | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 356 |   { | 
 | 357 |     drd_report_race(addr, size, eStore); | 
 | 358 |   } | 
| bart | a79df6e | 2008-03-14 17:07:51 +0000 | [diff] [blame] | 359 | } | 
 | 360 |  | 
 | 361 | static VG_REGPARM(1) void drd_trace_store_1(Addr addr) | 
 | 362 | { | 
| bart | 0e5c04f | 2008-06-09 15:18:59 +0000 | [diff] [blame] | 363 |   if (running_thread_is_recording() | 
 | 364 |       && (s_drd_check_stack_accesses || ! thread_address_on_stack(addr)) | 
| bart | 3e3296d | 2008-06-08 11:21:34 +0000 | [diff] [blame] | 365 |       && bm_access_store_1_triggers_conflict(addr) | 
 | 366 |       && ! drd_is_suppressed(addr, addr + 1)) | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 367 |   { | 
 | 368 |     drd_report_race(addr, 1, eStore); | 
 | 369 |   } | 
| bart | a79df6e | 2008-03-14 17:07:51 +0000 | [diff] [blame] | 370 | } | 
 | 371 |  | 
 | 372 | static VG_REGPARM(1) void drd_trace_store_2(Addr addr) | 
 | 373 | { | 
| bart | 0e5c04f | 2008-06-09 15:18:59 +0000 | [diff] [blame] | 374 |   if (running_thread_is_recording() | 
 | 375 |       && (s_drd_check_stack_accesses || ! thread_address_on_stack(addr)) | 
| bart | 3e3296d | 2008-06-08 11:21:34 +0000 | [diff] [blame] | 376 |       && bm_access_store_2_triggers_conflict(addr) | 
 | 377 |       && ! drd_is_suppressed(addr, addr + 2)) | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 378 |   { | 
 | 379 |     drd_report_race(addr, 2, eStore); | 
 | 380 |   } | 
| bart | a79df6e | 2008-03-14 17:07:51 +0000 | [diff] [blame] | 381 | } | 
 | 382 |  | 
 | 383 | static VG_REGPARM(1) void drd_trace_store_4(Addr addr) | 
 | 384 | { | 
| bart | 0e5c04f | 2008-06-09 15:18:59 +0000 | [diff] [blame] | 385 |   if (running_thread_is_recording() | 
 | 386 |       && (s_drd_check_stack_accesses || ! thread_address_on_stack(addr)) | 
| bart | 3e3296d | 2008-06-08 11:21:34 +0000 | [diff] [blame] | 387 |       && bm_access_store_4_triggers_conflict(addr) | 
 | 388 |       && ! drd_is_suppressed(addr, addr + 4)) | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 389 |   { | 
 | 390 |     drd_report_race(addr, 4, eStore); | 
 | 391 |   } | 
| bart | a79df6e | 2008-03-14 17:07:51 +0000 | [diff] [blame] | 392 | } | 
 | 393 |  | 
 | 394 | static VG_REGPARM(1) void drd_trace_store_8(Addr addr) | 
 | 395 | { | 
| bart | 0e5c04f | 2008-06-09 15:18:59 +0000 | [diff] [blame] | 396 |   if (running_thread_is_recording() | 
 | 397 |       && (s_drd_check_stack_accesses || ! thread_address_on_stack(addr)) | 
| bart | 3e3296d | 2008-06-08 11:21:34 +0000 | [diff] [blame] | 398 |       && bm_access_store_8_triggers_conflict(addr) | 
 | 399 |       && ! drd_is_suppressed(addr, addr + 8)) | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 400 |   { | 
 | 401 |     drd_report_race(addr, 8, eStore); | 
 | 402 |   } | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 403 | } | 
 | 404 |  | 
 | 405 | static void drd_pre_mem_read(const CorePart part, | 
 | 406 |                              const ThreadId tid, | 
 | 407 |                              Char* const s, | 
 | 408 |                              const Addr a, | 
 | 409 |                              const SizeT size) | 
 | 410 | { | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 411 |   if (size > 0) | 
 | 412 |   { | 
 | 413 |     drd_trace_load(a, size); | 
 | 414 |   } | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 415 | } | 
 | 416 |  | 
| bart | 5e85d26 | 2008-03-01 10:49:37 +0000 | [diff] [blame] | 417 | static void drd_pre_mem_read_asciiz(const CorePart part, | 
 | 418 |                                     const ThreadId tid, | 
 | 419 |                                     Char* const s, | 
 | 420 |                                     const Addr a) | 
 | 421 | { | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 422 |   const char* p = (void*)a; | 
 | 423 |   SizeT size = 0; | 
| bart | 5e85d26 | 2008-03-01 10:49:37 +0000 | [diff] [blame] | 424 |  | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 425 |   /* Note: the expression '*p' reads client memory and may crash if the */ | 
 | 426 |   /* client provided an invalid pointer !                               */ | 
 | 427 |   while (*p) | 
 | 428 |   { | 
 | 429 |     p++; | 
 | 430 |     size++; | 
 | 431 |   } | 
 | 432 |   // To do: find out what a reasonable upper limit on 'size' is. | 
 | 433 |   tl_assert(size < 4096); | 
 | 434 |   if (size > 0) | 
 | 435 |   { | 
 | 436 |     drd_trace_load(a, size); | 
 | 437 |   } | 
| bart | 5e85d26 | 2008-03-01 10:49:37 +0000 | [diff] [blame] | 438 | } | 
 | 439 |  | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 440 | static void drd_post_mem_write(const CorePart part, | 
 | 441 |                                const ThreadId tid, | 
 | 442 |                                const Addr a, | 
 | 443 |                                const SizeT size) | 
 | 444 | { | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 445 |   thread_set_vg_running_tid(VG_(get_running_tid)()); | 
 | 446 |   if (size > 0) | 
 | 447 |   { | 
 | 448 |     drd_trace_store(a, size); | 
 | 449 |   } | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 450 | } | 
 | 451 |  | 
| bart | 0886562 | 2008-06-06 14:31:36 +0000 | [diff] [blame] | 452 | static __inline__ | 
 | 453 | void drd_start_using_mem(const Addr a1, const SizeT len) | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 454 | { | 
| bart | 005dc97 | 2008-03-29 14:42:59 +0000 | [diff] [blame] | 455 |   tl_assert(a1 < a1 + len); | 
| bart | 5e85d26 | 2008-03-01 10:49:37 +0000 | [diff] [blame] | 456 |  | 
| bart | b9c7d74 | 2008-06-10 12:51:51 +0000 | [diff] [blame] | 457 |   if (UNLIKELY(drd_any_address_is_traced())) | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 458 |   { | 
| bart | d576591 | 2008-03-16 08:40:55 +0000 | [diff] [blame] | 459 |     drd_trace_mem_access(a1, len, eStart); | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 460 |   } | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 461 | } | 
 | 462 |  | 
| sewardj | 7cf4e6b | 2008-05-01 20:24:26 +0000 | [diff] [blame] | 463 | static void drd_start_using_mem_w_ecu(const Addr a1, | 
 | 464 |                                       const SizeT len, | 
 | 465 |                                       UInt ec_uniq) | 
 | 466 | { | 
 | 467 |   drd_start_using_mem(a1, len); | 
 | 468 | } | 
 | 469 |  | 
 | 470 | static void drd_start_using_mem_w_tid(const Addr a1, | 
 | 471 |                                       const SizeT len, | 
 | 472 |                                       ThreadId tid) | 
 | 473 | { | 
 | 474 |   drd_start_using_mem(a1, len); | 
 | 475 | } | 
 | 476 |  | 
| bart | 0ffa483 | 2008-04-05 12:57:01 +0000 | [diff] [blame] | 477 | static __inline__ | 
 | 478 | void drd_stop_using_mem(const Addr a1, const SizeT len, | 
 | 479 |                         const Bool is_stack_mem) | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 480 | { | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 481 |   const Addr a2 = a1 + len; | 
| bart | 5e85d26 | 2008-03-01 10:49:37 +0000 | [diff] [blame] | 482 |  | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 483 |   tl_assert(a1 < a2); | 
| bart | 5e85d26 | 2008-03-01 10:49:37 +0000 | [diff] [blame] | 484 |  | 
| bart | b9c7d74 | 2008-06-10 12:51:51 +0000 | [diff] [blame] | 485 |   if (UNLIKELY(drd_any_address_is_traced())) | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 486 |   { | 
| bart | d43f8d3 | 2008-03-16 17:29:20 +0000 | [diff] [blame] | 487 |     drd_trace_mem_access(a1, len, eEnd); | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 488 |   } | 
| bart | 0886562 | 2008-06-06 14:31:36 +0000 | [diff] [blame] | 489 |   if (! is_stack_mem || s_drd_check_stack_accesses) | 
| bart | 0ffa483 | 2008-04-05 12:57:01 +0000 | [diff] [blame] | 490 |   { | 
 | 491 |     thread_stop_using_mem(a1, a2); | 
 | 492 |     clientobj_stop_using_mem(a1, a2); | 
 | 493 |     drd_suppression_stop_using_mem(a1, a2); | 
 | 494 |   } | 
 | 495 | } | 
 | 496 |  | 
 | 497 | static __inline__ | 
 | 498 | void drd_stop_using_nonstack_mem(const Addr a1, const SizeT len) | 
 | 499 | { | 
 | 500 |   drd_stop_using_mem(a1, len, False); | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 501 | } | 
 | 502 |  | 
| bart | cb2d007 | 2008-05-31 07:55:51 +0000 | [diff] [blame] | 503 | /** Suppress data race reports on all addresses contained in .plt and | 
 | 504 |  *  .got.plt sections inside the address range [ a, a + len [. The data in | 
 | 505 |  *  these sections is modified by _dl_relocate_object() every time a function | 
 | 506 |  *  in a shared library is called for the first time. Since the first call | 
 | 507 |  *  to a function in a shared library can happen from a multithreaded context, | 
 | 508 |  *  such calls can cause conflicting accesses. See also Ulrich Drepper's | 
 | 509 |  *  paper "How to Write Shared Libraries" for more information about relocation | 
 | 510 |  *  (http://people.redhat.com/drepper/dsohowto.pdf). | 
 | 511 |  */ | 
 | 512 | static void suppress_relocation_conflicts(const Addr a, const SizeT len) | 
 | 513 | { | 
 | 514 |   const DebugInfo* di; | 
 | 515 |  | 
 | 516 | #if 0 | 
 | 517 |   VG_(printf)("Evaluating range @ 0x%lx size %ld\n", a, len); | 
 | 518 | #endif | 
 | 519 |  | 
 | 520 |   for (di = VG_(next_seginfo)(0); di; di = VG_(next_seginfo)(di)) | 
 | 521 |   { | 
 | 522 |     Addr  avma; | 
 | 523 |     SizeT size; | 
 | 524 |  | 
 | 525 |     avma = VG_(seginfo_get_plt_avma)(di); | 
 | 526 |     size = VG_(seginfo_get_plt_size)(di); | 
| bart | d5beeac | 2008-07-02 11:47:46 +0000 | [diff] [blame] | 527 |     if (size > 0 && a <= avma && avma + size <= a + len) | 
| bart | cb2d007 | 2008-05-31 07:55:51 +0000 | [diff] [blame] | 528 |     { | 
 | 529 | #if 0 | 
 | 530 |       VG_(printf)("Suppressing .plt @ 0x%lx size %ld\n", avma, size); | 
 | 531 | #endif | 
 | 532 |       tl_assert(VG_(seginfo_sect_kind)(NULL, 0, avma) == Vg_SectPLT); | 
 | 533 |       drd_start_suppression(avma, avma + size, ".plt"); | 
 | 534 |     } | 
 | 535 |  | 
 | 536 |     avma = VG_(seginfo_get_gotplt_avma)(di); | 
 | 537 |     size = VG_(seginfo_get_gotplt_size)(di); | 
| bart | d5beeac | 2008-07-02 11:47:46 +0000 | [diff] [blame] | 538 |     if (size > 0 && a <= avma && avma + size <= a + len) | 
| bart | cb2d007 | 2008-05-31 07:55:51 +0000 | [diff] [blame] | 539 |     { | 
 | 540 | #if 0 | 
 | 541 |       VG_(printf)("Suppressing .got.plt @ 0x%lx size %ld\n", avma, size); | 
 | 542 | #endif | 
 | 543 |       tl_assert(VG_(seginfo_sect_kind)(NULL, 0, avma) == Vg_SectGOTPLT); | 
 | 544 |       drd_start_suppression(avma, avma + size, ".gotplt"); | 
 | 545 |     } | 
 | 546 |   } | 
 | 547 | } | 
 | 548 |  | 
| bart | 5e85d26 | 2008-03-01 10:49:37 +0000 | [diff] [blame] | 549 | static | 
 | 550 | void drd_start_using_mem_w_perms(const Addr a, const SizeT len, | 
 | 551 |                                  const Bool rr, const Bool ww, const Bool xx) | 
 | 552 | { | 
| bart | d576591 | 2008-03-16 08:40:55 +0000 | [diff] [blame] | 553 |   thread_set_vg_running_tid(VG_(get_running_tid)()); | 
 | 554 |  | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 555 |   drd_start_using_mem(a, len); | 
| bart | cb2d007 | 2008-05-31 07:55:51 +0000 | [diff] [blame] | 556 |  | 
 | 557 |   suppress_relocation_conflicts(a, len); | 
| bart | 5e85d26 | 2008-03-01 10:49:37 +0000 | [diff] [blame] | 558 | } | 
 | 559 |  | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 560 | /* Called by the core when the stack of a thread grows, to indicate that */ | 
 | 561 | /* the addresses in range [ a, a + len [ may now be used by the client.  */ | 
 | 562 | /* Assumption: stacks grow downward.                                     */ | 
| bart | 0886562 | 2008-06-06 14:31:36 +0000 | [diff] [blame] | 563 | static __inline__ | 
 | 564 | void drd_start_using_mem_stack(const Addr a, const SizeT len) | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 565 | { | 
| bart | d43f8d3 | 2008-03-16 17:29:20 +0000 | [diff] [blame] | 566 |   thread_set_stack_min(thread_get_running_tid(), a - VG_STACK_REDZONE_SZB); | 
| sewardj | 7cf4e6b | 2008-05-01 20:24:26 +0000 | [diff] [blame] | 567 |   drd_start_using_mem(a - VG_STACK_REDZONE_SZB,  | 
 | 568 |                       len + VG_STACK_REDZONE_SZB); | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 569 | } | 
 | 570 |  | 
 | 571 | /* Called by the core when the stack of a thread shrinks, to indicate that */ | 
 | 572 | /* the addresses [ a, a + len [ are no longer accessible for the client.   */ | 
 | 573 | /* Assumption: stacks grow downward.                                       */ | 
| bart | 0886562 | 2008-06-06 14:31:36 +0000 | [diff] [blame] | 574 | static __inline__ | 
 | 575 | void drd_stop_using_mem_stack(const Addr a, const SizeT len) | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 576 | { | 
| bart | d43f8d3 | 2008-03-16 17:29:20 +0000 | [diff] [blame] | 577 |   thread_set_stack_min(thread_get_running_tid(), | 
 | 578 |                        a + len - VG_STACK_REDZONE_SZB); | 
| bart | 0ffa483 | 2008-04-05 12:57:01 +0000 | [diff] [blame] | 579 |   drd_stop_using_mem(a - VG_STACK_REDZONE_SZB, len + VG_STACK_REDZONE_SZB, | 
 | 580 |                      True); | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 581 | } | 
 | 582 |  | 
| sewardj | 7cf4e6b | 2008-05-01 20:24:26 +0000 | [diff] [blame] | 583 | static void drd_start_using_mem_stack_signal( | 
 | 584 |                const Addr a, const SizeT len, | 
 | 585 |                ThreadId tid_for_whom_the_signal_frame_is_being_constructed) | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 586 | { | 
| bart | d576591 | 2008-03-16 08:40:55 +0000 | [diff] [blame] | 587 |   thread_set_vg_running_tid(VG_(get_running_tid)()); | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 588 |   drd_start_using_mem(a, len); | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 589 | } | 
 | 590 |  | 
| bart | 5e85d26 | 2008-03-01 10:49:37 +0000 | [diff] [blame] | 591 | static void drd_stop_using_mem_stack_signal(Addr a, SizeT len) | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 592 | { | 
| bart | 0ffa483 | 2008-04-05 12:57:01 +0000 | [diff] [blame] | 593 |   drd_stop_using_mem(a, len, True); | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 594 | } | 
 | 595 |  | 
 | 596 | static | 
 | 597 | void drd_pre_thread_create(const ThreadId creator, const ThreadId created) | 
 | 598 | { | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 599 |   const DrdThreadId drd_creator = VgThreadIdToDrdThreadId(creator); | 
 | 600 |   tl_assert(created != VG_INVALID_THREADID); | 
 | 601 |   thread_pre_create(drd_creator, created); | 
 | 602 |   if (IsValidDrdThreadId(drd_creator)) | 
 | 603 |   { | 
 | 604 |     thread_new_segment(drd_creator); | 
 | 605 |   } | 
| bart | bd7e56e | 2008-03-31 18:14:12 +0000 | [diff] [blame] | 606 |   if (s_drd_trace_fork_join) | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 607 |   { | 
 | 608 |     VG_(message)(Vg_DebugMsg, | 
 | 609 |                  "drd_pre_thread_create creator = %d/%d, created = %d", | 
 | 610 |                  creator, drd_creator, created); | 
 | 611 |   } | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 612 | } | 
 | 613 |  | 
 | 614 | /* Called by Valgrind's core before any loads or stores are performed on */ | 
 | 615 | /* the context of thread "created". At startup, this function is called  */ | 
 | 616 | /* with arguments (0,1).                                                 */ | 
 | 617 | static | 
| bart | 0ffa483 | 2008-04-05 12:57:01 +0000 | [diff] [blame] | 618 | void drd_post_thread_create(const ThreadId vg_created) | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 619 | { | 
| bart | 0ffa483 | 2008-04-05 12:57:01 +0000 | [diff] [blame] | 620 |   DrdThreadId drd_created; | 
 | 621 |  | 
 | 622 |   tl_assert(vg_created != VG_INVALID_THREADID); | 
 | 623 |  | 
 | 624 |   drd_created = thread_post_create(vg_created); | 
| bart | bd7e56e | 2008-03-31 18:14:12 +0000 | [diff] [blame] | 625 |   if (s_drd_trace_fork_join) | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 626 |   { | 
 | 627 |     VG_(message)(Vg_DebugMsg, | 
 | 628 |                  "drd_post_thread_create created = %d/%d", | 
| bart | 0ffa483 | 2008-04-05 12:57:01 +0000 | [diff] [blame] | 629 |                  vg_created, drd_created); | 
 | 630 |   } | 
| bart | 0886562 | 2008-06-06 14:31:36 +0000 | [diff] [blame] | 631 |   if (! s_drd_check_stack_accesses) | 
| bart | 0ffa483 | 2008-04-05 12:57:01 +0000 | [diff] [blame] | 632 |   { | 
 | 633 |     drd_start_suppression(thread_get_stack_max(drd_created) | 
 | 634 |                           - thread_get_stack_size(drd_created), | 
 | 635 |                           thread_get_stack_max(drd_created), | 
 | 636 |                           "stack"); | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 637 |   } | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 638 | } | 
 | 639 |  | 
 | 640 | /* Process VG_USERREQ__POST_THREAD_JOIN. This client request is invoked just */ | 
 | 641 | /* after thread drd_joiner joined thread drd_joinee.                         */ | 
 | 642 | void drd_post_thread_join(DrdThreadId drd_joiner, DrdThreadId drd_joinee) | 
 | 643 | { | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 644 |   tl_assert(IsValidDrdThreadId(drd_joiner)); | 
 | 645 |   tl_assert(IsValidDrdThreadId(drd_joinee)); | 
 | 646 |   thread_new_segment(drd_joinee); | 
 | 647 |   thread_combine_vc(drd_joiner, drd_joinee); | 
 | 648 |   thread_new_segment(drd_joiner); | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 649 |  | 
| bart | bd7e56e | 2008-03-31 18:14:12 +0000 | [diff] [blame] | 650 |   if (s_drd_trace_fork_join) | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 651 |   { | 
| bart | fdd8d4e | 2008-04-01 18:38:29 +0000 | [diff] [blame] | 652 |     const ThreadId joiner = DrdThreadIdToVgThreadId(drd_joiner); | 
 | 653 |     const ThreadId joinee = DrdThreadIdToVgThreadId(drd_joinee); | 
| bart | 024a95a | 2008-04-01 18:27:41 +0000 | [diff] [blame] | 654 |     const unsigned msg_size = 256; | 
 | 655 |     char* msg; | 
 | 656 |  | 
 | 657 |     msg = VG_(malloc)(msg_size); | 
| bart | fdd8d4e | 2008-04-01 18:38:29 +0000 | [diff] [blame] | 658 |     tl_assert(msg); | 
| bart | 024a95a | 2008-04-01 18:27:41 +0000 | [diff] [blame] | 659 |     VG_(snprintf)(msg, msg_size, | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 660 |                   "drd_post_thread_join joiner = %d/%d, joinee = %d/%d", | 
 | 661 |                   joiner, drd_joiner, joinee, drd_joinee); | 
 | 662 |     if (joiner) | 
 | 663 |     { | 
| bart | 024a95a | 2008-04-01 18:27:41 +0000 | [diff] [blame] | 664 |       VG_(snprintf)(msg + VG_(strlen)(msg), msg_size - VG_(strlen)(msg), | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 665 |                     ", new vc: "); | 
| bart | 024a95a | 2008-04-01 18:27:41 +0000 | [diff] [blame] | 666 |       vc_snprint(msg + VG_(strlen)(msg), msg_size - VG_(strlen)(msg), | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 667 |                  thread_get_vc(drd_joiner)); | 
 | 668 |     } | 
 | 669 |     VG_(message)(Vg_DebugMsg, msg); | 
| bart | 024a95a | 2008-04-01 18:27:41 +0000 | [diff] [blame] | 670 |     VG_(free)(msg); | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 671 |   } | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 672 |  | 
| bart | 0886562 | 2008-06-06 14:31:36 +0000 | [diff] [blame] | 673 |   if (! s_drd_check_stack_accesses) | 
| bart | 0ffa483 | 2008-04-05 12:57:01 +0000 | [diff] [blame] | 674 |   { | 
 | 675 |     drd_finish_suppression(thread_get_stack_max(drd_joinee) | 
 | 676 |                            - thread_get_stack_size(drd_joinee), | 
 | 677 |                            thread_get_stack_max(drd_joinee)); | 
 | 678 |   } | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 679 |   thread_delete(drd_joinee); | 
 | 680 |   mutex_thread_delete(drd_joinee); | 
 | 681 |   cond_thread_delete(drd_joinee); | 
 | 682 |   semaphore_thread_delete(drd_joinee); | 
 | 683 |   barrier_thread_delete(drd_joinee); | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 684 | } | 
 | 685 |  | 
| bart | 5bd9f2d | 2008-03-03 20:31:58 +0000 | [diff] [blame] | 686 |  | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 687 | /* Called after a thread has performed its last memory access. */ | 
| bart | d43f8d3 | 2008-03-16 17:29:20 +0000 | [diff] [blame] | 688 | static void drd_thread_finished(ThreadId vg_tid) | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 689 | { | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 690 |   DrdThreadId drd_tid; | 
| sewardj | 8564292 | 2008-01-14 11:54:56 +0000 | [diff] [blame] | 691 |  | 
| bart | d43f8d3 | 2008-03-16 17:29:20 +0000 | [diff] [blame] | 692 |   tl_assert(VG_(get_running_tid)() == vg_tid); | 
| sewardj | 8564292 | 2008-01-14 11:54:56 +0000 | [diff] [blame] | 693 |  | 
| bart | d43f8d3 | 2008-03-16 17:29:20 +0000 | [diff] [blame] | 694 |   drd_tid = VgThreadIdToDrdThreadId(vg_tid); | 
| bart | bd7e56e | 2008-03-31 18:14:12 +0000 | [diff] [blame] | 695 |   if (s_drd_trace_fork_join) | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 696 |   { | 
 | 697 |     VG_(message)(Vg_DebugMsg, | 
 | 698 |                  "drd_thread_finished tid = %d/%d%s", | 
| bart | d43f8d3 | 2008-03-16 17:29:20 +0000 | [diff] [blame] | 699 |                  vg_tid, | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 700 |                  drd_tid, | 
 | 701 |                  thread_get_joinable(drd_tid) | 
 | 702 |                  ? "" | 
 | 703 |                  : " (which is a detached thread)"); | 
| bart | 912ab8d | 2008-03-29 09:31:43 +0000 | [diff] [blame] | 704 |   } | 
 | 705 |   if (s_show_stack_usage) | 
 | 706 |   { | 
 | 707 |     const SizeT stack_size = thread_get_stack_size(drd_tid); | 
 | 708 |     const SizeT used_stack | 
 | 709 |       = thread_get_stack_max(drd_tid) - thread_get_stack_min_min(drd_tid); | 
 | 710 |     VG_(message)(Vg_UserMsg, | 
 | 711 |                  "thread %d/%d%s finished and used %ld bytes out of %ld" | 
 | 712 |                  " on its stack. Margin: %ld bytes.", | 
 | 713 |                  vg_tid, | 
 | 714 |                  drd_tid, | 
 | 715 |                  thread_get_joinable(drd_tid) | 
 | 716 |                  ? "" | 
 | 717 |                  : " (which is a detached thread)", | 
 | 718 |                  used_stack, | 
 | 719 |                  stack_size, | 
 | 720 |                  stack_size - used_stack); | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 721 |  | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 722 |   } | 
| bart | d43f8d3 | 2008-03-16 17:29:20 +0000 | [diff] [blame] | 723 |   drd_stop_using_mem(thread_get_stack_min(drd_tid), | 
 | 724 |                      thread_get_stack_max(drd_tid) | 
| bart | 0ffa483 | 2008-04-05 12:57:01 +0000 | [diff] [blame] | 725 |                      - thread_get_stack_min(drd_tid), | 
 | 726 |                      True); | 
| bart | d43f8d3 | 2008-03-16 17:29:20 +0000 | [diff] [blame] | 727 |   thread_stop_recording(drd_tid); | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 728 |   thread_finished(drd_tid); | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 729 | } | 
 | 730 |  | 
| bart | 0268dfa | 2008-03-11 20:10:21 +0000 | [diff] [blame] | 731 | void drd_pre_mutex_init(const Addr mutex, const MutexT mutex_type) | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 732 | { | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 733 |   mutex_init(mutex, mutex_type); | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 734 | } | 
 | 735 |  | 
| sewardj | 347eeba | 2008-01-21 14:19:07 +0000 | [diff] [blame] | 736 | void drd_post_mutex_destroy(const Addr mutex, const MutexT mutex_type) | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 737 | { | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 738 |   mutex_post_destroy(mutex); | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 739 | } | 
 | 740 |  | 
| bart | 2e3a3c1 | 2008-03-24 08:33:47 +0000 | [diff] [blame] | 741 | void drd_pre_mutex_lock(const Addr mutex, const MutexT mutex_type, | 
 | 742 |                         const Bool trylock) | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 743 | { | 
| bart | 2e3a3c1 | 2008-03-24 08:33:47 +0000 | [diff] [blame] | 744 |   mutex_pre_lock(mutex, mutex_type, trylock); | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 745 | } | 
 | 746 |  | 
| bart | 0034464 | 2008-03-01 15:27:41 +0000 | [diff] [blame] | 747 | void drd_post_mutex_lock(const Addr mutex, const Bool took_lock) | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 748 | { | 
| bart | 4a975e1 | 2008-03-30 13:28:33 +0000 | [diff] [blame] | 749 |   mutex_post_lock(mutex, took_lock, False); | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 750 | } | 
 | 751 |  | 
| bart | 0034464 | 2008-03-01 15:27:41 +0000 | [diff] [blame] | 752 | void drd_pre_mutex_unlock(const Addr mutex, const MutexT mutex_type) | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 753 | { | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 754 |   mutex_unlock(mutex, mutex_type); | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 755 | } | 
 | 756 |  | 
| bart | 0268dfa | 2008-03-11 20:10:21 +0000 | [diff] [blame] | 757 | void drd_pre_cond_init(Addr cond) | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 758 | { | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 759 |   cond_pre_init(cond); | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 760 | } | 
 | 761 |  | 
| bart | 72b751c | 2008-03-01 13:44:24 +0000 | [diff] [blame] | 762 | void drd_post_cond_destroy(Addr cond) | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 763 | { | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 764 |   cond_post_destroy(cond); | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 765 | } | 
 | 766 |  | 
| bart | 0268dfa | 2008-03-11 20:10:21 +0000 | [diff] [blame] | 767 | void drd_semaphore_init(const Addr semaphore, | 
| sewardj | 8564292 | 2008-01-14 11:54:56 +0000 | [diff] [blame] | 768 |                         const Word pshared, const Word value) | 
 | 769 | { | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 770 |   semaphore_init(semaphore, pshared, value); | 
| sewardj | 8564292 | 2008-01-14 11:54:56 +0000 | [diff] [blame] | 771 | } | 
 | 772 |  | 
 | 773 | void drd_semaphore_destroy(const Addr semaphore) | 
 | 774 | { | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 775 |   semaphore_destroy(semaphore); | 
| sewardj | 8564292 | 2008-01-14 11:54:56 +0000 | [diff] [blame] | 776 | } | 
 | 777 |  | 
| bart | 0268dfa | 2008-03-11 20:10:21 +0000 | [diff] [blame] | 778 | void drd_semaphore_pre_wait(const DrdThreadId tid, const Addr semaphore) | 
| sewardj | 8564292 | 2008-01-14 11:54:56 +0000 | [diff] [blame] | 779 | { | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 780 |   semaphore_pre_wait(semaphore); | 
| bart | 28230a3 | 2008-02-29 17:27:03 +0000 | [diff] [blame] | 781 | } | 
 | 782 |  | 
 | 783 | void drd_semaphore_post_wait(const DrdThreadId tid, const Addr semaphore, | 
 | 784 |                              const Bool waited) | 
 | 785 | { | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 786 |   semaphore_post_wait(tid, semaphore, waited); | 
| sewardj | 8564292 | 2008-01-14 11:54:56 +0000 | [diff] [blame] | 787 | } | 
 | 788 |  | 
| bart | 0268dfa | 2008-03-11 20:10:21 +0000 | [diff] [blame] | 789 | void drd_semaphore_pre_post(const DrdThreadId tid, const Addr semaphore) | 
| sewardj | 8564292 | 2008-01-14 11:54:56 +0000 | [diff] [blame] | 790 | { | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 791 |   semaphore_pre_post(tid, semaphore); | 
| sewardj | 8564292 | 2008-01-14 11:54:56 +0000 | [diff] [blame] | 792 | } | 
 | 793 |  | 
 | 794 | void drd_semaphore_post_post(const DrdThreadId tid, const Addr semaphore, | 
| bart | 0268dfa | 2008-03-11 20:10:21 +0000 | [diff] [blame] | 795 |                              const Bool waited) | 
| sewardj | 8564292 | 2008-01-14 11:54:56 +0000 | [diff] [blame] | 796 | { | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 797 |   semaphore_post_post(tid, semaphore, waited); | 
| sewardj | 8564292 | 2008-01-14 11:54:56 +0000 | [diff] [blame] | 798 | } | 
 | 799 |  | 
 | 800 |  | 
| bart | 0268dfa | 2008-03-11 20:10:21 +0000 | [diff] [blame] | 801 | void drd_barrier_init(const Addr barrier, | 
 | 802 |                       const BarrierT barrier_type, const Word count, | 
 | 803 |                       const Bool reinitialization) | 
| sewardj | 8564292 | 2008-01-14 11:54:56 +0000 | [diff] [blame] | 804 | { | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 805 |   barrier_init(barrier, barrier_type, count, reinitialization); | 
| sewardj | 8564292 | 2008-01-14 11:54:56 +0000 | [diff] [blame] | 806 | } | 
 | 807 |  | 
| bart | 0268dfa | 2008-03-11 20:10:21 +0000 | [diff] [blame] | 808 | void drd_barrier_destroy(const Addr barrier, const BarrierT barrier_type) | 
| sewardj | 8564292 | 2008-01-14 11:54:56 +0000 | [diff] [blame] | 809 | { | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 810 |   barrier_destroy(barrier, barrier_type); | 
| sewardj | 8564292 | 2008-01-14 11:54:56 +0000 | [diff] [blame] | 811 | } | 
 | 812 |  | 
| bart | 0268dfa | 2008-03-11 20:10:21 +0000 | [diff] [blame] | 813 | void drd_barrier_pre_wait(const DrdThreadId tid, const Addr barrier, | 
 | 814 |                           const BarrierT barrier_type) | 
| sewardj | 8564292 | 2008-01-14 11:54:56 +0000 | [diff] [blame] | 815 | { | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 816 |   barrier_pre_wait(tid, barrier, barrier_type); | 
| sewardj | 8564292 | 2008-01-14 11:54:56 +0000 | [diff] [blame] | 817 | } | 
 | 818 |  | 
 | 819 | void drd_barrier_post_wait(const DrdThreadId tid, const Addr barrier, | 
| bart | 0268dfa | 2008-03-11 20:10:21 +0000 | [diff] [blame] | 820 |                            const BarrierT barrier_type, const Bool waited) | 
| sewardj | 8564292 | 2008-01-14 11:54:56 +0000 | [diff] [blame] | 821 | { | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 822 |   barrier_post_wait(tid, barrier, barrier_type, waited); | 
| sewardj | 8564292 | 2008-01-14 11:54:56 +0000 | [diff] [blame] | 823 | } | 
 | 824 |  | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 825 |  | 
 | 826 | // | 
 | 827 | // Implementation of the tool interface. | 
 | 828 | // | 
 | 829 |  | 
 | 830 | static | 
 | 831 | void drd_post_clo_init(void) | 
| sewardj | dcbb8d3 | 2007-11-26 21:34:30 +0000 | [diff] [blame] | 832 | { | 
| bart | 5403f21 | 2008-06-30 10:56:18 +0000 | [diff] [blame] | 833 | #  if defined(VGP_x86_linux) || defined(VGP_amd64_linux) \ | 
 | 834 |       || defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 835 |   /* fine */ | 
| sewardj | dcbb8d3 | 2007-11-26 21:34:30 +0000 | [diff] [blame] | 836 | #  else | 
| bart | 5403f21 | 2008-06-30 10:56:18 +0000 | [diff] [blame] | 837 |   VG_(printf)("\nWARNING: DRD has only been tested on Linux.\n\n"); | 
| sewardj | dcbb8d3 | 2007-11-26 21:34:30 +0000 | [diff] [blame] | 838 | #  endif | 
| bart | 95761b5 | 2008-03-29 08:34:03 +0000 | [diff] [blame] | 839 |  | 
 | 840 |   if (s_drd_var_info) | 
 | 841 |   { | 
 | 842 |     VG_(needs_var_info)(); | 
 | 843 |   } | 
| sewardj | dcbb8d3 | 2007-11-26 21:34:30 +0000 | [diff] [blame] | 844 | } | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 845 |  | 
| bart | eacd916 | 2008-06-16 20:22:18 +0000 | [diff] [blame] | 846 | #if defined(VGA_x86) | 
 | 847 | #define STACK_POINTER_OFFSET OFFSET_x86_ESP | 
 | 848 | #elif defined(VGA_amd64) | 
 | 849 | #define STACK_POINTER_OFFSET OFFSET_amd64_RSP | 
 | 850 | #elif defined(VGA_ppc32) | 
 | 851 | #define STACK_POINTER_OFFSET ((OFFSET_ppc32_GPR0 + OFFSET_ppc32_GPR2) / 2) | 
 | 852 | #elif defined(VGA_ppc64) | 
 | 853 | #define STACK_POINTER_OFFSET ((OFFSET_ppc64_GPR0 + OFFSET_ppc64_GPR2) / 2) | 
 | 854 | #else | 
 | 855 | #error Unknown architecture. | 
 | 856 | #endif | 
 | 857 |  | 
 | 858 |  | 
 | 859 | /** Return true if and only if addr_expr matches the pattern (SP) or | 
 | 860 |  *  <offset>(SP). | 
 | 861 |  */ | 
 | 862 | static Bool is_stack_access(IRSB* const bb, IRExpr* const addr_expr) | 
 | 863 | { | 
 | 864 |   Bool result = False; | 
 | 865 |  | 
 | 866 |   if (addr_expr->tag == Iex_RdTmp) | 
 | 867 |   { | 
 | 868 |     int i; | 
 | 869 |     for (i = 0; i < bb->stmts_size; i++) | 
 | 870 |     { | 
 | 871 |       if (bb->stmts[i] | 
 | 872 |           && bb->stmts[i]->tag == Ist_WrTmp | 
 | 873 |           && bb->stmts[i]->Ist.WrTmp.tmp == addr_expr->Iex.RdTmp.tmp) | 
 | 874 |       { | 
 | 875 |         IRExpr* e = bb->stmts[i]->Ist.WrTmp.data; | 
 | 876 |         if (e->tag == Iex_Get && e->Iex.Get.offset == STACK_POINTER_OFFSET) | 
 | 877 |         { | 
 | 878 |           result = True; | 
 | 879 |         } | 
 | 880 |  | 
 | 881 |         //ppIRExpr(e); | 
 | 882 |         //VG_(printf)(" (%s)\n", result ? "True" : "False"); | 
 | 883 |         break; | 
 | 884 |       } | 
 | 885 |     } | 
 | 886 |   } | 
 | 887 |   return result; | 
 | 888 | } | 
 | 889 |  | 
| bart | a79df6e | 2008-03-14 17:07:51 +0000 | [diff] [blame] | 890 | static void instrument_load(IRSB* const bb, | 
 | 891 |                             IRExpr* const addr_expr, | 
 | 892 |                             const HWord size) | 
 | 893 | { | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 894 |   IRExpr* size_expr; | 
 | 895 |   IRExpr** argv; | 
 | 896 |   IRDirty* di; | 
| bart | a79df6e | 2008-03-14 17:07:51 +0000 | [diff] [blame] | 897 |  | 
| bart | 29a0e2a | 2008-06-10 13:55:13 +0000 | [diff] [blame] | 898 |   if (UNLIKELY(drd_any_address_is_traced())) | 
 | 899 |   { | 
 | 900 |     addStmtToIRSB(bb, | 
 | 901 | 		  IRStmt_Dirty( | 
 | 902 | 		    unsafeIRDirty_0_N(/*regparms*/2, | 
 | 903 | 				      "drd_trace_load", | 
 | 904 | 				      VG_(fnptr_to_fnentry) | 
 | 905 | 				      (drd_trace_mem_load), | 
 | 906 | 				      mkIRExprVec_2(addr_expr, | 
 | 907 | 						    mkIRExpr_HWord(size))))); | 
 | 908 |   } | 
 | 909 |  | 
| bart | eacd916 | 2008-06-16 20:22:18 +0000 | [diff] [blame] | 910 |   if (! s_drd_check_stack_accesses && is_stack_access(bb, addr_expr)) | 
 | 911 |     return; | 
 | 912 |  | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 913 |   switch (size) | 
 | 914 |   { | 
 | 915 |   case 1: | 
 | 916 |     argv = mkIRExprVec_1(addr_expr); | 
 | 917 |     di = unsafeIRDirty_0_N(/*regparms*/1, | 
 | 918 |                            "drd_trace_load_1", | 
 | 919 |                            VG_(fnptr_to_fnentry)(drd_trace_load_1), | 
 | 920 |                            argv); | 
 | 921 |     break; | 
 | 922 |   case 2: | 
 | 923 |     argv = mkIRExprVec_1(addr_expr); | 
 | 924 |     di = unsafeIRDirty_0_N(/*regparms*/1, | 
 | 925 |                            "drd_trace_load_2", | 
 | 926 |                            VG_(fnptr_to_fnentry)(drd_trace_load_2), | 
 | 927 |                            argv); | 
 | 928 |     break; | 
 | 929 |   case 4: | 
 | 930 |     argv = mkIRExprVec_1(addr_expr); | 
 | 931 |     di = unsafeIRDirty_0_N(/*regparms*/1, | 
 | 932 |                            "drd_trace_load_4", | 
 | 933 |                            VG_(fnptr_to_fnentry)(drd_trace_load_4), | 
 | 934 |                            argv); | 
 | 935 |     break; | 
 | 936 |   case 8: | 
 | 937 |     argv = mkIRExprVec_1(addr_expr); | 
 | 938 |     di = unsafeIRDirty_0_N(/*regparms*/1, | 
 | 939 |                            "drd_trace_load_8", | 
 | 940 |                            VG_(fnptr_to_fnentry)(drd_trace_load_8), | 
 | 941 |                            argv); | 
 | 942 |     break; | 
 | 943 |   default: | 
 | 944 |     size_expr = mkIRExpr_HWord(size); | 
 | 945 |     argv = mkIRExprVec_2(addr_expr, size_expr); | 
 | 946 |     di = unsafeIRDirty_0_N(/*regparms*/2, | 
 | 947 |                            "drd_trace_load", | 
 | 948 |                            VG_(fnptr_to_fnentry)(drd_trace_load), | 
 | 949 |                            argv); | 
 | 950 |     break; | 
 | 951 |   } | 
 | 952 |   addStmtToIRSB(bb, IRStmt_Dirty(di)); | 
| bart | a79df6e | 2008-03-14 17:07:51 +0000 | [diff] [blame] | 953 | } | 
 | 954 |  | 
 | 955 | static void instrument_store(IRSB* const bb, | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 956 |                              IRExpr* const addr_expr, | 
 | 957 |                              const HWord size) | 
| bart | a79df6e | 2008-03-14 17:07:51 +0000 | [diff] [blame] | 958 | { | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 959 |   IRExpr* size_expr; | 
 | 960 |   IRExpr** argv; | 
 | 961 |   IRDirty* di; | 
| bart | a79df6e | 2008-03-14 17:07:51 +0000 | [diff] [blame] | 962 |  | 
| bart | 29a0e2a | 2008-06-10 13:55:13 +0000 | [diff] [blame] | 963 |   if (UNLIKELY(drd_any_address_is_traced())) | 
 | 964 |   { | 
 | 965 |     addStmtToIRSB(bb, | 
 | 966 | 		  IRStmt_Dirty( | 
 | 967 | 		    unsafeIRDirty_0_N(/*regparms*/2, | 
 | 968 | 				      "drd_trace_store", | 
 | 969 | 				      VG_(fnptr_to_fnentry) | 
 | 970 | 				      (drd_trace_mem_store), | 
 | 971 | 				      mkIRExprVec_2(addr_expr, | 
 | 972 | 						    mkIRExpr_HWord(size))))); | 
 | 973 |   } | 
 | 974 |  | 
| bart | eacd916 | 2008-06-16 20:22:18 +0000 | [diff] [blame] | 975 |   if (! s_drd_check_stack_accesses && is_stack_access(bb, addr_expr)) | 
 | 976 |     return; | 
 | 977 |  | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 978 |   switch (size) | 
 | 979 |   { | 
 | 980 |   case 1: | 
 | 981 |     argv = mkIRExprVec_1(addr_expr); | 
 | 982 |     di = unsafeIRDirty_0_N(/*regparms*/1, | 
 | 983 |                            "drd_trace_store_1", | 
 | 984 |                            VG_(fnptr_to_fnentry)(drd_trace_store_1), | 
 | 985 |                            argv); | 
 | 986 |     break; | 
 | 987 |   case 2: | 
 | 988 |     argv = mkIRExprVec_1(addr_expr); | 
 | 989 |     di = unsafeIRDirty_0_N(/*regparms*/1, | 
 | 990 |                            "drd_trace_store_2", | 
 | 991 |                            VG_(fnptr_to_fnentry)(drd_trace_store_2), | 
 | 992 |                            argv); | 
 | 993 |     break; | 
 | 994 |   case 4: | 
 | 995 |     argv = mkIRExprVec_1(addr_expr); | 
 | 996 |     di = unsafeIRDirty_0_N(/*regparms*/1, | 
 | 997 |                            "drd_trace_store_4", | 
 | 998 |                            VG_(fnptr_to_fnentry)(drd_trace_store_4), | 
 | 999 |                            argv); | 
 | 1000 |     break; | 
 | 1001 |   case 8: | 
 | 1002 |     argv = mkIRExprVec_1(addr_expr); | 
 | 1003 |     di = unsafeIRDirty_0_N(/*regparms*/1, | 
 | 1004 |                            "drd_trace_store_8", | 
 | 1005 |                            VG_(fnptr_to_fnentry)(drd_trace_store_8), | 
 | 1006 |                            argv); | 
 | 1007 |     break; | 
 | 1008 |   default: | 
 | 1009 |     size_expr = mkIRExpr_HWord(size); | 
 | 1010 |     argv = mkIRExprVec_2(addr_expr, size_expr); | 
 | 1011 |     di = unsafeIRDirty_0_N(/*regparms*/2, | 
 | 1012 |                            "drd_trace_store", | 
 | 1013 |                            VG_(fnptr_to_fnentry)(drd_trace_store), | 
 | 1014 |                            argv); | 
 | 1015 |     break; | 
 | 1016 |   } | 
 | 1017 |   addStmtToIRSB(bb, IRStmt_Dirty(di)); | 
| bart | a79df6e | 2008-03-14 17:07:51 +0000 | [diff] [blame] | 1018 | } | 
 | 1019 |  | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 1020 | static | 
 | 1021 | IRSB* drd_instrument(VgCallbackClosure* const closure, | 
| sewardj | 347eeba | 2008-01-21 14:19:07 +0000 | [diff] [blame] | 1022 |                      IRSB* const bb_in, | 
 | 1023 |                      VexGuestLayout* const layout, | 
 | 1024 |                      VexGuestExtents* const vge,  | 
 | 1025 |                      IRType const gWordTy, | 
 | 1026 |                      IRType const hWordTy) | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 1027 | { | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 1028 |   IRDirty* di; | 
 | 1029 |   Int      i; | 
 | 1030 |   IRSB*    bb; | 
 | 1031 |   IRExpr** argv; | 
 | 1032 |   Bool     instrument = True; | 
 | 1033 |   Bool     bus_locked = False; | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 1034 |  | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 1035 |   /* Set up BB */ | 
 | 1036 |   bb           = emptyIRSB(); | 
 | 1037 |   bb->tyenv    = deepCopyIRTypeEnv(bb_in->tyenv); | 
 | 1038 |   bb->next     = deepCopyIRExpr(bb_in->next); | 
 | 1039 |   bb->jumpkind = bb_in->jumpkind; | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 1040 |  | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 1041 |   for (i = 0; i < bb_in->stmts_used; i++) | 
 | 1042 |   { | 
 | 1043 |     IRStmt* const st = bb_in->stmts[i]; | 
 | 1044 |     tl_assert(st); | 
 | 1045 |     if (st->tag == Ist_NoOp) | 
 | 1046 |       continue; | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 1047 |  | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 1048 |     switch (st->tag) | 
 | 1049 |     { | 
| bart | 7c97218 | 2008-06-30 13:15:33 +0000 | [diff] [blame] | 1050 |     /* Note: the code for not instrumenting the code in .plt          */ | 
 | 1051 |     /* sections is only necessary on CentOS 3.0 x86 (kernel 2.4.21    */ | 
 | 1052 |     /* + glibc 2.3.2 + NPTL 0.60 + binutils 2.14.90.0.4).             */ | 
 | 1053 |     /* This is because on this platform dynamic library symbols are   */ | 
 | 1054 |     /* relocated in another way than by later binutils versions. The  */ | 
 | 1055 |     /* linker e.g. does not generate .got.plt sections on CentOS 3.0. */ | 
 | 1056 |     case Ist_IMark: | 
 | 1057 |       instrument = VG_(seginfo_sect_kind)(NULL, 0, st->Ist.IMark.addr) | 
 | 1058 |         != Vg_SectPLT; | 
 | 1059 |       addStmtToIRSB(bb, st); | 
 | 1060 |       break; | 
 | 1061 |  | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 1062 |     case Ist_MBE: | 
 | 1063 |       switch (st->Ist.MBE.event) | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 1064 |       { | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 1065 |       case Imbe_Fence: | 
 | 1066 |         break; /* not interesting */ | 
 | 1067 |       case Imbe_BusLock: | 
| sewardj | 9df35c2 | 2008-06-30 10:32:54 +0000 | [diff] [blame] | 1068 |       case Imbe_SnoopedStoreBegin: | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 1069 |         tl_assert(! bus_locked); | 
 | 1070 |         bus_locked = True; | 
 | 1071 |         break; | 
 | 1072 |       case Imbe_BusUnlock: | 
| sewardj | 9df35c2 | 2008-06-30 10:32:54 +0000 | [diff] [blame] | 1073 |       case Imbe_SnoopedStoreEnd: | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 1074 |         tl_assert(bus_locked); | 
 | 1075 |         bus_locked = False; | 
 | 1076 |         break; | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 1077 |       default: | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 1078 |         tl_assert(0); | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 1079 |       } | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 1080 |       addStmtToIRSB(bb, st); | 
 | 1081 |       break; | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 1082 |  | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 1083 |     case Ist_Store: | 
 | 1084 |       if (instrument && ! bus_locked) | 
 | 1085 |       { | 
 | 1086 |         instrument_store(bb, | 
 | 1087 |                          st->Ist.Store.addr, | 
 | 1088 |                          sizeofIRType(typeOfIRExpr(bb->tyenv, | 
 | 1089 |                                                    st->Ist.Store.data))); | 
 | 1090 |       } | 
 | 1091 |       addStmtToIRSB(bb, st); | 
 | 1092 |       break; | 
| bart | a47b351 | 2008-03-07 17:22:26 +0000 | [diff] [blame] | 1093 |  | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 1094 |     case Ist_WrTmp: | 
 | 1095 |       if (instrument) | 
 | 1096 |       { | 
 | 1097 |         const IRExpr* const data = st->Ist.WrTmp.data; | 
 | 1098 |         if (data->tag == Iex_Load) | 
 | 1099 |         { | 
 | 1100 |           instrument_load(bb, | 
 | 1101 |                           data->Iex.Load.addr, | 
 | 1102 |                           sizeofIRType(data->Iex.Load.ty)); | 
 | 1103 |         } | 
 | 1104 |       } | 
 | 1105 |       addStmtToIRSB(bb, st); | 
 | 1106 |       break; | 
 | 1107 |  | 
 | 1108 |     case Ist_Dirty: | 
 | 1109 |       if (instrument) | 
 | 1110 |       { | 
 | 1111 |         IRDirty* d = st->Ist.Dirty.details; | 
 | 1112 |         IREffect const mFx = d->mFx; | 
 | 1113 |         switch (mFx) { | 
 | 1114 |         case Ifx_None: | 
 | 1115 |           break; | 
 | 1116 |         case Ifx_Read: | 
 | 1117 |         case Ifx_Write: | 
 | 1118 |         case Ifx_Modify: | 
 | 1119 |           tl_assert(d->mAddr); | 
 | 1120 |           tl_assert(d->mSize > 0); | 
 | 1121 |           argv = mkIRExprVec_2(d->mAddr, mkIRExpr_HWord(d->mSize)); | 
 | 1122 |           if (mFx == Ifx_Read || mFx == Ifx_Modify) { | 
 | 1123 |             di = unsafeIRDirty_0_N( | 
 | 1124 |                                    /*regparms*/2, | 
 | 1125 |                                    "drd_trace_load", | 
 | 1126 |                                    VG_(fnptr_to_fnentry)(drd_trace_load), | 
 | 1127 |                                    argv); | 
 | 1128 |             addStmtToIRSB(bb, IRStmt_Dirty(di)); | 
 | 1129 |           } | 
 | 1130 |           if ((mFx == Ifx_Write || mFx == Ifx_Modify) | 
 | 1131 |               && ! bus_locked) | 
 | 1132 |           { | 
 | 1133 |             di = unsafeIRDirty_0_N( | 
 | 1134 |                                    /*regparms*/2, | 
 | 1135 |                                    "drd_trace_store", | 
 | 1136 |                                    VG_(fnptr_to_fnentry)(drd_trace_store), | 
 | 1137 |                                    argv); | 
 | 1138 |             addStmtToIRSB(bb, IRStmt_Dirty(di)); | 
 | 1139 |           } | 
 | 1140 |           break; | 
 | 1141 |         default: | 
 | 1142 |           tl_assert(0); | 
 | 1143 |         } | 
 | 1144 |       } | 
 | 1145 |       addStmtToIRSB(bb, st); | 
 | 1146 |       break; | 
 | 1147 |  | 
 | 1148 |     default: | 
 | 1149 |       addStmtToIRSB(bb, st); | 
 | 1150 |       break; | 
 | 1151 |     } | 
 | 1152 |   } | 
 | 1153 |  | 
 | 1154 |   tl_assert(! bus_locked); | 
 | 1155 |  | 
 | 1156 |   return bb; | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 1157 | } | 
 | 1158 |  | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 1159 | static void drd_start_client_code(const ThreadId tid, const ULong bbs_done) | 
 | 1160 | { | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 1161 |   tl_assert(tid == VG_(get_running_tid)()); | 
 | 1162 |   thread_set_vg_running_tid(tid); | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 1163 | } | 
 | 1164 |  | 
 | 1165 | static | 
 | 1166 | void drd_fini(Int exitcode) | 
 | 1167 | { | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 1168 |   // thread_print_all(); | 
| bart | bd7e56e | 2008-03-31 18:14:12 +0000 | [diff] [blame] | 1169 |   if (VG_(clo_verbosity) > 1 || s_drd_print_stats) | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 1170 |   { | 
| bart | e73b0aa | 2008-06-28 07:19:56 +0000 | [diff] [blame] | 1171 |     ULong update_conflict_set_count; | 
| bart | e4504dd | 2008-04-06 15:02:58 +0000 | [diff] [blame] | 1172 |     ULong dsnsc; | 
 | 1173 |     ULong dscvc; | 
 | 1174 |  | 
| bart | e73b0aa | 2008-06-28 07:19:56 +0000 | [diff] [blame] | 1175 |     update_conflict_set_count | 
 | 1176 |       = thread_get_update_conflict_set_count(&dsnsc, &dscvc); | 
| bart | e4504dd | 2008-04-06 15:02:58 +0000 | [diff] [blame] | 1177 |  | 
| bart | bd7e56e | 2008-03-31 18:14:12 +0000 | [diff] [blame] | 1178 |     VG_(message)(Vg_UserMsg, | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 1179 |                  "   thread: %lld context switches" | 
| bart | e73b0aa | 2008-06-28 07:19:56 +0000 | [diff] [blame] | 1180 |                  " / %lld updates of the conflict set", | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 1181 |                  thread_get_context_switch_count(), | 
| bart | e73b0aa | 2008-06-28 07:19:56 +0000 | [diff] [blame] | 1182 |                  update_conflict_set_count); | 
| bart | e4504dd | 2008-04-06 15:02:58 +0000 | [diff] [blame] | 1183 |     VG_(message)(Vg_UserMsg, | 
 | 1184 |                  "           (%lld new sg + %lld combine vc + %lld csw).", | 
 | 1185 |                  dsnsc, | 
 | 1186 |                  dscvc, | 
| bart | e73b0aa | 2008-06-28 07:19:56 +0000 | [diff] [blame] | 1187 |                  update_conflict_set_count - dsnsc - dscvc); | 
| bart | bd7e56e | 2008-03-31 18:14:12 +0000 | [diff] [blame] | 1188 |     VG_(message)(Vg_UserMsg, | 
 | 1189 |                  " segments: created %lld segments, max %lld alive," | 
 | 1190 |                  " %lld discard points.", | 
| bart | 7102f10 | 2008-03-17 17:37:53 +0000 | [diff] [blame] | 1191 |                  sg_get_created_segments_count(), | 
 | 1192 |                  sg_get_max_alive_segments_count(), | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 1193 |                  thread_get_discard_ordered_segments_count()); | 
| bart | bd7e56e | 2008-03-31 18:14:12 +0000 | [diff] [blame] | 1194 |     VG_(message)(Vg_UserMsg, | 
| bart | 6bbefaf | 2008-04-19 15:16:45 +0000 | [diff] [blame] | 1195 |                  "           (%lld m, %lld rw, %lld s, %lld b)", | 
 | 1196 |                  get_mutex_segment_creation_count(), | 
 | 1197 |                  get_rwlock_segment_creation_count(), | 
 | 1198 |                  get_semaphore_segment_creation_count(), | 
 | 1199 |                  get_barrier_segment_creation_count()); | 
 | 1200 |     VG_(message)(Vg_UserMsg, | 
| bart | 952e1a0 | 2008-04-06 13:06:36 +0000 | [diff] [blame] | 1201 |                  "  bitmaps: %lld level 1 / %lld level 2 bitmap refs", | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 1202 |                  bm_get_bitmap_creation_count(), | 
| bart | 952e1a0 | 2008-04-06 13:06:36 +0000 | [diff] [blame] | 1203 |                  bm_get_bitmap2_node_creation_count()); | 
 | 1204 |     VG_(message)(Vg_UserMsg, | 
 | 1205 |                  "           and %lld level 2 bitmaps were allocated.", | 
| bart | bd7e56e | 2008-03-31 18:14:12 +0000 | [diff] [blame] | 1206 |                  bm_get_bitmap2_creation_count()); | 
 | 1207 |     VG_(message)(Vg_UserMsg, | 
 | 1208 |                  "    mutex: %lld non-recursive lock/unlock events.", | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 1209 |                  get_mutex_lock_count()); | 
 | 1210 |     drd_print_malloc_stats(); | 
 | 1211 |   } | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 1212 | } | 
 | 1213 |  | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 1214 | static | 
 | 1215 | void drd_pre_clo_init(void) | 
 | 1216 | { | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 1217 |   // Basic tool stuff. | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 1218 |  | 
| bart | ef1b972 | 2008-07-04 15:34:23 +0000 | [diff] [blame^] | 1219 |   VG_(details_name)            ("drd"); | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 1220 |   VG_(details_version)         (NULL); | 
| bart | c821a94 | 2008-07-04 14:48:39 +0000 | [diff] [blame] | 1221 |   VG_(details_description)     ("a thread error detector"); | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 1222 |   VG_(details_copyright_author)("Copyright (C) 2006-2008, and GNU GPL'd," | 
 | 1223 |                                 " by Bart Van Assche."); | 
 | 1224 |   VG_(details_bug_reports_to)  (VG_BUGS_TO); | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 1225 |  | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 1226 |   VG_(basic_tool_funcs)        (drd_post_clo_init, | 
 | 1227 |                                 drd_instrument, | 
 | 1228 |                                 drd_fini); | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 1229 |  | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 1230 |   // Command line stuff. | 
 | 1231 |   VG_(needs_command_line_options)(drd_process_cmd_line_option, | 
 | 1232 |                                   drd_print_usage, | 
 | 1233 |                                   drd_print_debug_usage); | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 1234 |  | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 1235 |   // Error handling. | 
 | 1236 |   drd_register_error_handlers(); | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 1237 |  | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 1238 |   // Core event tracking. | 
 | 1239 |   VG_(track_pre_mem_read)         (drd_pre_mem_read); | 
 | 1240 |   VG_(track_pre_mem_read_asciiz)  (drd_pre_mem_read_asciiz); | 
 | 1241 |   VG_(track_post_mem_write)       (drd_post_mem_write); | 
| sewardj | 7cf4e6b | 2008-05-01 20:24:26 +0000 | [diff] [blame] | 1242 |   VG_(track_new_mem_brk)          (drd_start_using_mem_w_tid); | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 1243 |   VG_(track_new_mem_mmap)         (drd_start_using_mem_w_perms); | 
 | 1244 |   VG_(track_new_mem_stack)        (drd_start_using_mem_stack); | 
 | 1245 |   VG_(track_new_mem_stack_signal) (drd_start_using_mem_stack_signal); | 
 | 1246 |   VG_(track_new_mem_startup)      (drd_start_using_mem_w_perms); | 
| bart | 0ffa483 | 2008-04-05 12:57:01 +0000 | [diff] [blame] | 1247 |   VG_(track_die_mem_brk)          (drd_stop_using_nonstack_mem); | 
 | 1248 |   VG_(track_die_mem_munmap)       (drd_stop_using_nonstack_mem); | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 1249 |   VG_(track_die_mem_stack)        (drd_stop_using_mem_stack); | 
 | 1250 |   VG_(track_die_mem_stack_signal) (drd_stop_using_mem_stack_signal); | 
 | 1251 |   VG_(track_start_client_code)    (drd_start_client_code); | 
 | 1252 |   VG_(track_pre_thread_ll_create) (drd_pre_thread_create); | 
 | 1253 |   VG_(track_pre_thread_first_insn)(drd_post_thread_create); | 
 | 1254 |   VG_(track_pre_thread_ll_exit)   (drd_thread_finished); | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 1255 |  | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 1256 |   // Other stuff. | 
| sewardj | 7cf4e6b | 2008-05-01 20:24:26 +0000 | [diff] [blame] | 1257 |   drd_register_malloc_wrappers(drd_start_using_mem_w_ecu, | 
| bart | 0ffa483 | 2008-04-05 12:57:01 +0000 | [diff] [blame] | 1258 |                                drd_stop_using_nonstack_mem); | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 1259 |  | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 1260 |   drd_clientreq_init(); | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 1261 |  | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 1262 |   drd_suppression_init(); | 
| bart | 4bb53d8 | 2008-02-28 19:06:34 +0000 | [diff] [blame] | 1263 |  | 
| bart | 3772a98 | 2008-03-15 08:11:03 +0000 | [diff] [blame] | 1264 |   clientobj_init(); | 
| sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 1265 | } | 
 | 1266 |  | 
 | 1267 |  | 
 | 1268 | VG_DETERMINE_INTERFACE_VERSION(drd_pre_clo_init) |