bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 1 | /* -*- mode: C; c-basic-offset: 3; -*- */ |
sewardj | 8564292 | 2008-01-14 11:54:56 +0000 | [diff] [blame] | 2 | /* |
bart | 86562bd | 2009-02-16 19:43:56 +0000 | [diff] [blame] | 3 | This file is part of drd, a thread error detector. |
sewardj | 8564292 | 2008-01-14 11:54:56 +0000 | [diff] [blame] | 4 | |
bart | 09dc13f | 2009-02-14 15:13:31 +0000 | [diff] [blame] | 5 | Copyright (C) 2006-2009 Bart Van Assche <bart.vanassche@gmail.com>. |
sewardj | 8564292 | 2008-01-14 11:54:56 +0000 | [diff] [blame] | 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 | |
bart | 09dc13f | 2009-02-14 15:13:31 +0000 | [diff] [blame] | 26 | #include "drd_barrier.h" |
sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 27 | #include "drd_clientreq.h" |
| 28 | #include "drd_cond.h" |
bart | 83c1780 | 2009-03-10 09:26:07 +0000 | [diff] [blame] | 29 | #include "drd_load_store.h" |
sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 30 | #include "drd_mutex.h" |
bart | 09dc13f | 2009-02-14 15:13:31 +0000 | [diff] [blame] | 31 | #include "drd_rwlock.h" |
sewardj | 8564292 | 2008-01-14 11:54:56 +0000 | [diff] [blame] | 32 | #include "drd_semaphore.h" |
sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 33 | #include "drd_suppression.h" // drd_start_suppression() |
| 34 | #include "drd_thread.h" |
sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 35 | #include "pub_tool_basics.h" // Bool |
bart | b93846e | 2008-04-16 18:17:12 +0000 | [diff] [blame] | 36 | #include "pub_tool_debuginfo.h" // VG_(describe_IP)() |
sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 37 | #include "pub_tool_libcassert.h" |
| 38 | #include "pub_tool_libcassert.h" // tl_assert() |
| 39 | #include "pub_tool_libcprint.h" // VG_(message)() |
| 40 | #include "pub_tool_machine.h" // VG_(get_SP)() |
| 41 | #include "pub_tool_threadstate.h" |
| 42 | #include "pub_tool_tooliface.h" // VG_(needs_...)() |
| 43 | |
| 44 | |
bart | 09dc13f | 2009-02-14 15:13:31 +0000 | [diff] [blame] | 45 | /* Local function declarations. */ |
sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 46 | |
bart | 09dc13f | 2009-02-14 15:13:31 +0000 | [diff] [blame] | 47 | static |
| 48 | Bool DRD_(handle_client_request)(ThreadId vg_tid, UWord* arg, UWord* ret); |
| 49 | static Addr DRD_(highest_used_stack_address)(const ThreadId vg_tid); |
sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 50 | |
sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 51 | |
bart | 03ffb2e | 2009-02-15 10:36:32 +0000 | [diff] [blame] | 52 | /* Function definitions. */ |
| 53 | |
bart | 09dc13f | 2009-02-14 15:13:31 +0000 | [diff] [blame] | 54 | /** |
bart | 03ffb2e | 2009-02-15 10:36:32 +0000 | [diff] [blame] | 55 | * Tell the Valgrind core the address of the DRD function that processes |
| 56 | * client requests. Must be called before any client code is run. |
bart | f1ac71a | 2008-04-04 16:54:37 +0000 | [diff] [blame] | 57 | */ |
bart | 03ffb2e | 2009-02-15 10:36:32 +0000 | [diff] [blame] | 58 | void DRD_(clientreq_init)(void) |
bart | f1ac71a | 2008-04-04 16:54:37 +0000 | [diff] [blame] | 59 | { |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 60 | VG_(needs_client_requests)(DRD_(handle_client_request)); |
bart | f1ac71a | 2008-04-04 16:54:37 +0000 | [diff] [blame] | 61 | } |
| 62 | |
bart | 09dc13f | 2009-02-14 15:13:31 +0000 | [diff] [blame] | 63 | /** |
| 64 | * DRD's handler for Valgrind client requests. The code below handles both |
| 65 | * DRD's public and tool-internal client requests. |
| 66 | */ |
| 67 | static |
| 68 | Bool DRD_(handle_client_request)(ThreadId vg_tid, UWord* arg, UWord* ret) |
sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 69 | { |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 70 | UWord result = 0; |
| 71 | const DrdThreadId drd_tid = DRD_(thread_get_running_tid)(); |
bart | 0268dfa | 2008-03-11 20:10:21 +0000 | [diff] [blame] | 72 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 73 | tl_assert(vg_tid == VG_(get_running_tid())); |
| 74 | tl_assert(DRD_(VgThreadIdToDrdThreadId)(vg_tid) == drd_tid); |
sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 75 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 76 | switch (arg[0]) |
| 77 | { |
| 78 | case VG_USERREQ__DRD_GET_VALGRIND_THREAD_ID: |
| 79 | result = vg_tid; |
| 80 | break; |
sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 81 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 82 | case VG_USERREQ__DRD_GET_DRD_THREAD_ID: |
| 83 | result = drd_tid; |
| 84 | break; |
bart | 5f57be9 | 2008-07-01 08:48:56 +0000 | [diff] [blame] | 85 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 86 | case VG_USERREQ__DRD_START_SUPPRESSION: |
| 87 | DRD_(start_suppression)(arg[1], arg[1] + arg[2], "client"); |
| 88 | break; |
sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 89 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 90 | case VG_USERREQ__DRD_FINISH_SUPPRESSION: |
| 91 | DRD_(finish_suppression)(arg[1], arg[1] + arg[2]); |
| 92 | break; |
sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 93 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 94 | case VG_USERREQ__DRD_SUPPRESS_CURRENT_STACK: |
| 95 | { |
| 96 | const Addr topmost_sp = DRD_(highest_used_stack_address)(vg_tid); |
bart | 0ff483d | 2008-04-06 13:08:32 +0000 | [diff] [blame] | 97 | #if 0 |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 98 | UInt nframes; |
| 99 | const UInt n_ips = 20; |
| 100 | Addr ips[n_ips], sps[n_ips], fps[n_ips]; |
| 101 | Char desc[128]; |
| 102 | unsigned i; |
bart | 0ff483d | 2008-04-06 13:08:32 +0000 | [diff] [blame] | 103 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 104 | nframes = VG_(get_StackTrace)(vg_tid, ips, n_ips, sps, fps, 0); |
bart | 0ff483d | 2008-04-06 13:08:32 +0000 | [diff] [blame] | 105 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 106 | VG_(message)(Vg_DebugMsg, "thread %d/%d", vg_tid, drd_tid); |
| 107 | for (i = 0; i < nframes; i++) |
| 108 | { |
| 109 | VG_(describe_IP)(ips[i], desc, sizeof(desc)); |
| 110 | VG_(message)(Vg_DebugMsg, "[%2d] sp 0x%09lx fp 0x%09lx ip %s", |
| 111 | i, sps[i], fps[i], desc); |
| 112 | } |
bart | 0ff483d | 2008-04-06 13:08:32 +0000 | [diff] [blame] | 113 | #endif |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 114 | DRD_(thread_set_stack_startup)(drd_tid, VG_(get_SP)(vg_tid)); |
| 115 | DRD_(start_suppression)(topmost_sp, VG_(thread_get_stack_max)(vg_tid), |
| 116 | "stack top"); |
| 117 | break; |
| 118 | } |
sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 119 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 120 | case VG_USERREQ__DRD_START_NEW_SEGMENT: |
| 121 | DRD_(thread_new_segment)(DRD_(PtThreadIdToDrdThreadId)(arg[1])); |
| 122 | break; |
sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 123 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 124 | case VG_USERREQ__DRD_START_TRACE_ADDR: |
| 125 | DRD_(start_tracing_address_range)(arg[1], arg[1] + arg[2]); |
| 126 | break; |
bart | 005dc97 | 2008-03-29 14:42:59 +0000 | [diff] [blame] | 127 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 128 | case VG_USERREQ__DRD_STOP_TRACE_ADDR: |
| 129 | DRD_(stop_tracing_address_range)(arg[1], arg[1] + arg[2]); |
| 130 | break; |
bart | 5bd9f2d | 2008-03-03 20:31:58 +0000 | [diff] [blame] | 131 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 132 | case VG_USERREQ__DRD_STOP_RECORDING: |
| 133 | DRD_(thread_stop_recording)(drd_tid); |
| 134 | break; |
bart | bf3a60c | 2008-04-04 19:10:21 +0000 | [diff] [blame] | 135 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 136 | case VG_USERREQ__DRD_START_RECORDING: |
| 137 | DRD_(thread_start_recording)(drd_tid); |
| 138 | break; |
bart | bf3a60c | 2008-04-04 19:10:21 +0000 | [diff] [blame] | 139 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 140 | case VG_USERREQ__SET_PTHREADID: |
| 141 | // pthread_self() returns 0 for programs not linked with libpthread.so. |
| 142 | if (arg[1] != INVALID_POSIX_THREADID) |
| 143 | DRD_(thread_set_pthreadid)(drd_tid, arg[1]); |
| 144 | break; |
sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 145 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 146 | case VG_USERREQ__SET_JOINABLE: |
| 147 | DRD_(thread_set_joinable)(DRD_(PtThreadIdToDrdThreadId)(arg[1]), |
| 148 | (Bool)arg[2]); |
| 149 | break; |
sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 150 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 151 | case VG_USERREQ__POST_THREAD_JOIN: |
| 152 | tl_assert(arg[1]); |
| 153 | DRD_(thread_post_join)(drd_tid, DRD_(PtThreadIdToDrdThreadId)(arg[1])); |
| 154 | break; |
sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 155 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 156 | case VG_USERREQ__PRE_THREAD_CANCEL: |
| 157 | tl_assert(arg[1]); |
| 158 | DRD_(thread_pre_cancel)(drd_tid); |
| 159 | break; |
bart | 0f099cd | 2008-09-27 12:36:48 +0000 | [diff] [blame] | 160 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 161 | case VG_USERREQ__POST_THREAD_CANCEL: |
| 162 | tl_assert(arg[1]); |
| 163 | break; |
bart | 0f099cd | 2008-09-27 12:36:48 +0000 | [diff] [blame] | 164 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 165 | case VG_USERREQ__PRE_MUTEX_INIT: |
| 166 | if (DRD_(thread_enter_synchr)(drd_tid) == 0) |
| 167 | DRD_(mutex_init)(arg[1], arg[2]); |
| 168 | break; |
bart | 0268dfa | 2008-03-11 20:10:21 +0000 | [diff] [blame] | 169 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 170 | case VG_USERREQ__POST_MUTEX_INIT: |
| 171 | DRD_(thread_leave_synchr)(drd_tid); |
| 172 | break; |
bart | 0268dfa | 2008-03-11 20:10:21 +0000 | [diff] [blame] | 173 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 174 | case VG_USERREQ__PRE_MUTEX_DESTROY: |
| 175 | DRD_(thread_enter_synchr)(drd_tid); |
| 176 | break; |
sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 177 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 178 | case VG_USERREQ__POST_MUTEX_DESTROY: |
| 179 | if (DRD_(thread_leave_synchr)(drd_tid) == 0) |
| 180 | DRD_(mutex_post_destroy)(arg[1]); |
| 181 | break; |
sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 182 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 183 | case VG_USERREQ__PRE_MUTEX_LOCK: |
| 184 | if (DRD_(thread_enter_synchr)(drd_tid) == 0) |
| 185 | DRD_(mutex_pre_lock)(arg[1], arg[2], arg[3]); |
| 186 | break; |
sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 187 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 188 | case VG_USERREQ__POST_MUTEX_LOCK: |
| 189 | if (DRD_(thread_leave_synchr)(drd_tid) == 0) |
| 190 | DRD_(mutex_post_lock)(arg[1], arg[2], False/*post_cond_wait*/); |
| 191 | break; |
sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 192 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 193 | case VG_USERREQ__PRE_MUTEX_UNLOCK: |
| 194 | if (DRD_(thread_enter_synchr)(drd_tid) == 0) |
| 195 | DRD_(mutex_unlock)(arg[1], arg[2]); |
| 196 | break; |
bart | 0268dfa | 2008-03-11 20:10:21 +0000 | [diff] [blame] | 197 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 198 | case VG_USERREQ__POST_MUTEX_UNLOCK: |
| 199 | DRD_(thread_leave_synchr)(drd_tid); |
| 200 | break; |
sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 201 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 202 | case VG_USERREQ__PRE_SPIN_INIT_OR_UNLOCK: |
| 203 | if (DRD_(thread_enter_synchr)(drd_tid) == 0) |
| 204 | DRD_(spinlock_init_or_unlock)(arg[1]); |
| 205 | break; |
bart | f4f0581 | 2008-07-07 08:10:56 +0000 | [diff] [blame] | 206 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 207 | case VG_USERREQ__POST_SPIN_INIT_OR_UNLOCK: |
| 208 | DRD_(thread_leave_synchr)(drd_tid); |
| 209 | break; |
sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 210 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 211 | case VG_USERREQ__PRE_COND_INIT: |
| 212 | if (DRD_(thread_enter_synchr)(drd_tid) == 0) |
| 213 | DRD_(cond_pre_init)(arg[1]); |
| 214 | break; |
bart | 3f4623e | 2008-07-07 16:53:07 +0000 | [diff] [blame] | 215 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 216 | case VG_USERREQ__POST_COND_INIT: |
| 217 | DRD_(thread_leave_synchr)(drd_tid); |
| 218 | break; |
bart | 3f4623e | 2008-07-07 16:53:07 +0000 | [diff] [blame] | 219 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 220 | case VG_USERREQ__PRE_COND_DESTROY: |
| 221 | DRD_(thread_enter_synchr)(drd_tid); |
| 222 | break; |
sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 223 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 224 | case VG_USERREQ__POST_COND_DESTROY: |
| 225 | if (DRD_(thread_leave_synchr)(drd_tid) == 0) |
| 226 | DRD_(cond_post_destroy)(arg[1]); |
| 227 | break; |
sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 228 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 229 | case VG_USERREQ__PRE_COND_WAIT: |
| 230 | if (DRD_(thread_enter_synchr)(drd_tid) == 0) |
| 231 | { |
| 232 | const Addr cond = arg[1]; |
| 233 | const Addr mutex = arg[2]; |
| 234 | const MutexT mutex_type = arg[3]; |
| 235 | DRD_(mutex_unlock)(mutex, mutex_type); |
| 236 | DRD_(cond_pre_wait)(cond, mutex); |
| 237 | } |
| 238 | break; |
sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 239 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 240 | case VG_USERREQ__POST_COND_WAIT: |
| 241 | if (DRD_(thread_leave_synchr)(drd_tid) == 0) |
| 242 | { |
| 243 | const Addr cond = arg[1]; |
| 244 | const Addr mutex = arg[2]; |
| 245 | const Bool took_lock = arg[3]; |
| 246 | DRD_(cond_post_wait)(cond); |
| 247 | DRD_(mutex_post_lock)(mutex, took_lock, True); |
| 248 | } |
| 249 | break; |
sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 250 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 251 | case VG_USERREQ__PRE_COND_SIGNAL: |
| 252 | if (DRD_(thread_enter_synchr)(drd_tid) == 0) |
| 253 | DRD_(cond_pre_signal)(arg[1]); |
| 254 | break; |
bart | 3f4623e | 2008-07-07 16:53:07 +0000 | [diff] [blame] | 255 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 256 | case VG_USERREQ__POST_COND_SIGNAL: |
| 257 | DRD_(thread_leave_synchr)(drd_tid); |
| 258 | break; |
sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 259 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 260 | case VG_USERREQ__PRE_COND_BROADCAST: |
| 261 | if (DRD_(thread_enter_synchr)(drd_tid) == 0) |
| 262 | DRD_(cond_pre_broadcast)(arg[1]); |
| 263 | break; |
bart | 3f4623e | 2008-07-07 16:53:07 +0000 | [diff] [blame] | 264 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 265 | case VG_USERREQ__POST_COND_BROADCAST: |
| 266 | DRD_(thread_leave_synchr)(drd_tid); |
| 267 | break; |
sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 268 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 269 | case VG_USERREQ__PRE_SEM_INIT: |
| 270 | if (DRD_(thread_enter_synchr)(drd_tid) == 0) |
| 271 | DRD_(semaphore_init)(arg[1], arg[2], arg[3]); |
| 272 | break; |
sewardj | 8564292 | 2008-01-14 11:54:56 +0000 | [diff] [blame] | 273 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 274 | case VG_USERREQ__POST_SEM_INIT: |
| 275 | DRD_(thread_leave_synchr)(drd_tid); |
| 276 | break; |
bart | 0268dfa | 2008-03-11 20:10:21 +0000 | [diff] [blame] | 277 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 278 | case VG_USERREQ__PRE_SEM_DESTROY: |
| 279 | DRD_(thread_enter_synchr)(drd_tid); |
| 280 | break; |
bart | 0268dfa | 2008-03-11 20:10:21 +0000 | [diff] [blame] | 281 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 282 | case VG_USERREQ__POST_SEM_DESTROY: |
| 283 | if (DRD_(thread_leave_synchr)(drd_tid) == 0) |
| 284 | DRD_(semaphore_destroy)(arg[1]); |
| 285 | break; |
sewardj | 8564292 | 2008-01-14 11:54:56 +0000 | [diff] [blame] | 286 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 287 | case VG_USERREQ__PRE_SEM_WAIT: |
| 288 | if (DRD_(thread_enter_synchr)(drd_tid) == 0) |
| 289 | DRD_(semaphore_pre_wait)(arg[1]); |
| 290 | break; |
bart | 28230a3 | 2008-02-29 17:27:03 +0000 | [diff] [blame] | 291 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 292 | case VG_USERREQ__POST_SEM_WAIT: |
| 293 | if (DRD_(thread_leave_synchr)(drd_tid) == 0) |
| 294 | DRD_(semaphore_post_wait)(drd_tid, arg[1], arg[2]); |
| 295 | break; |
sewardj | 8564292 | 2008-01-14 11:54:56 +0000 | [diff] [blame] | 296 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 297 | case VG_USERREQ__PRE_SEM_POST: |
| 298 | if (DRD_(thread_enter_synchr)(drd_tid) == 0) |
| 299 | DRD_(semaphore_pre_post)(drd_tid, arg[1]); |
| 300 | break; |
sewardj | 8564292 | 2008-01-14 11:54:56 +0000 | [diff] [blame] | 301 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 302 | case VG_USERREQ__POST_SEM_POST: |
| 303 | if (DRD_(thread_leave_synchr)(drd_tid) == 0) |
| 304 | DRD_(semaphore_post_post)(drd_tid, arg[1], arg[2]); |
| 305 | break; |
sewardj | 8564292 | 2008-01-14 11:54:56 +0000 | [diff] [blame] | 306 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 307 | case VG_USERREQ__PRE_BARRIER_INIT: |
| 308 | if (DRD_(thread_enter_synchr)(drd_tid) == 0) |
| 309 | DRD_(barrier_init)(arg[1], arg[2], arg[3], arg[4]); |
| 310 | break; |
sewardj | 8564292 | 2008-01-14 11:54:56 +0000 | [diff] [blame] | 311 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 312 | case VG_USERREQ__POST_BARRIER_INIT: |
| 313 | DRD_(thread_leave_synchr)(drd_tid); |
| 314 | break; |
bart | 0268dfa | 2008-03-11 20:10:21 +0000 | [diff] [blame] | 315 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 316 | case VG_USERREQ__PRE_BARRIER_DESTROY: |
| 317 | DRD_(thread_enter_synchr)(drd_tid); |
| 318 | break; |
bart | 0268dfa | 2008-03-11 20:10:21 +0000 | [diff] [blame] | 319 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 320 | case VG_USERREQ__POST_BARRIER_DESTROY: |
| 321 | if (DRD_(thread_leave_synchr)(drd_tid) == 0) |
| 322 | DRD_(barrier_destroy)(arg[1], arg[2]); |
| 323 | break; |
sewardj | 8564292 | 2008-01-14 11:54:56 +0000 | [diff] [blame] | 324 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 325 | case VG_USERREQ__PRE_BARRIER_WAIT: |
| 326 | if (DRD_(thread_enter_synchr)(drd_tid) == 0) |
| 327 | DRD_(barrier_pre_wait)(drd_tid, arg[1], arg[2]); |
| 328 | break; |
sewardj | 8564292 | 2008-01-14 11:54:56 +0000 | [diff] [blame] | 329 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 330 | case VG_USERREQ__POST_BARRIER_WAIT: |
| 331 | if (DRD_(thread_leave_synchr)(drd_tid) == 0) |
| 332 | DRD_(barrier_post_wait)(drd_tid, arg[1], arg[2], arg[3], arg[4]); |
| 333 | break; |
sewardj | 8564292 | 2008-01-14 11:54:56 +0000 | [diff] [blame] | 334 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 335 | case VG_USERREQ__PRE_RWLOCK_INIT: |
| 336 | DRD_(rwlock_pre_init)(arg[1]); |
| 337 | break; |
bart | 0034464 | 2008-03-01 15:27:41 +0000 | [diff] [blame] | 338 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 339 | case VG_USERREQ__POST_RWLOCK_DESTROY: |
| 340 | DRD_(rwlock_post_destroy)(arg[1]); |
| 341 | break; |
bart | 0034464 | 2008-03-01 15:27:41 +0000 | [diff] [blame] | 342 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 343 | case VG_USERREQ__PRE_RWLOCK_RDLOCK: |
| 344 | if (DRD_(thread_enter_synchr)(drd_tid) == 0) |
| 345 | DRD_(rwlock_pre_rdlock)(arg[1]); |
| 346 | break; |
bart | 0034464 | 2008-03-01 15:27:41 +0000 | [diff] [blame] | 347 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 348 | case VG_USERREQ__POST_RWLOCK_RDLOCK: |
| 349 | if (DRD_(thread_leave_synchr)(drd_tid) == 0) |
| 350 | DRD_(rwlock_post_rdlock)(arg[1], arg[2]); |
| 351 | break; |
bart | 0034464 | 2008-03-01 15:27:41 +0000 | [diff] [blame] | 352 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 353 | case VG_USERREQ__PRE_RWLOCK_WRLOCK: |
| 354 | if (DRD_(thread_enter_synchr)(drd_tid) == 0) |
| 355 | DRD_(rwlock_pre_wrlock)(arg[1]); |
| 356 | break; |
bart | 0034464 | 2008-03-01 15:27:41 +0000 | [diff] [blame] | 357 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 358 | case VG_USERREQ__POST_RWLOCK_WRLOCK: |
| 359 | if (DRD_(thread_leave_synchr)(drd_tid) == 0) |
| 360 | DRD_(rwlock_post_wrlock)(arg[1], arg[2]); |
| 361 | break; |
bart | 0034464 | 2008-03-01 15:27:41 +0000 | [diff] [blame] | 362 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 363 | case VG_USERREQ__PRE_RWLOCK_UNLOCK: |
| 364 | if (DRD_(thread_enter_synchr)(drd_tid) == 0) |
| 365 | DRD_(rwlock_pre_unlock)(arg[1]); |
| 366 | break; |
bart | 0268dfa | 2008-03-11 20:10:21 +0000 | [diff] [blame] | 367 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 368 | case VG_USERREQ__POST_RWLOCK_UNLOCK: |
| 369 | DRD_(thread_leave_synchr)(drd_tid); |
| 370 | break; |
bart | 0034464 | 2008-03-01 15:27:41 +0000 | [diff] [blame] | 371 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 372 | case VG_USERREQ__DRD_CLEAN_MEMORY: |
| 373 | if (arg[2] > 0) |
| 374 | DRD_(clean_memory)(arg[1], arg[2]); |
| 375 | break; |
bart | 83c1780 | 2009-03-10 09:26:07 +0000 | [diff] [blame] | 376 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 377 | default: |
| 378 | VG_(message)(Vg_DebugMsg, "Unrecognized client request 0x%lx 0x%lx", |
| 379 | arg[0], arg[1]); |
| 380 | tl_assert(0); |
| 381 | return False; |
| 382 | } |
sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 383 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 384 | *ret = result; |
| 385 | return True; |
sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 386 | } |
| 387 | |
bart | 09dc13f | 2009-02-14 15:13:31 +0000 | [diff] [blame] | 388 | /** |
bart | 03ffb2e | 2009-02-15 10:36:32 +0000 | [diff] [blame] | 389 | * Walk the stack up to the highest stack frame, and return the stack pointer |
| 390 | * of the highest stack frame. It is assumed that there are no more than |
| 391 | * ten stack frames above the current frame. This should be no problem |
| 392 | * since this function is either called indirectly from the _init() function |
| 393 | * in vgpreload_exp-drd-*.so or from the thread wrapper for a newly created |
| 394 | * thread. See also drd_pthread_intercepts.c. |
bart | 09dc13f | 2009-02-14 15:13:31 +0000 | [diff] [blame] | 395 | */ |
bart | 03ffb2e | 2009-02-15 10:36:32 +0000 | [diff] [blame] | 396 | static Addr DRD_(highest_used_stack_address)(const ThreadId vg_tid) |
sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 397 | { |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 398 | UInt nframes; |
| 399 | const UInt n_ips = 10; |
| 400 | UInt i; |
| 401 | Addr ips[n_ips], sps[n_ips]; |
| 402 | Addr husa; |
bart | 03ffb2e | 2009-02-15 10:36:32 +0000 | [diff] [blame] | 403 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 404 | nframes = VG_(get_StackTrace)(vg_tid, ips, n_ips, sps, 0, 0); |
| 405 | tl_assert(1 <= nframes && nframes <= n_ips); |
bart | 03ffb2e | 2009-02-15 10:36:32 +0000 | [diff] [blame] | 406 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 407 | /* A hack to work around VG_(get_StackTrace)()'s behavior that sometimes */ |
| 408 | /* the topmost stackframes it returns are bogus (this occurs sometimes */ |
| 409 | /* at least on amd64, ppc32 and ppc64). */ |
bart | 03ffb2e | 2009-02-15 10:36:32 +0000 | [diff] [blame] | 410 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 411 | husa = sps[0]; |
bart | 03ffb2e | 2009-02-15 10:36:32 +0000 | [diff] [blame] | 412 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 413 | tl_assert(VG_(thread_get_stack_max)(vg_tid) |
| 414 | - VG_(thread_get_stack_size)(vg_tid) <= husa |
| 415 | && husa < VG_(thread_get_stack_max)(vg_tid)); |
bart | 03ffb2e | 2009-02-15 10:36:32 +0000 | [diff] [blame] | 416 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 417 | for (i = 1; i < nframes; i++) |
| 418 | { |
bart | 03ffb2e | 2009-02-15 10:36:32 +0000 | [diff] [blame] | 419 | if (sps[i] == 0) |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 420 | break; |
bart | 03ffb2e | 2009-02-15 10:36:32 +0000 | [diff] [blame] | 421 | if (husa < sps[i] && sps[i] < VG_(thread_get_stack_max)(vg_tid)) |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 422 | husa = sps[i]; |
| 423 | } |
bart | 03ffb2e | 2009-02-15 10:36:32 +0000 | [diff] [blame] | 424 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 425 | tl_assert(VG_(thread_get_stack_max)(vg_tid) |
| 426 | - VG_(thread_get_stack_size)(vg_tid) <= husa |
| 427 | && husa < VG_(thread_get_stack_max)(vg_tid)); |
bart | 03ffb2e | 2009-02-15 10:36:32 +0000 | [diff] [blame] | 428 | |
bart | bedfd23 | 2009-03-26 19:07:15 +0000 | [diff] [blame] | 429 | return husa; |
sewardj | af44c82 | 2007-11-25 14:01:38 +0000 | [diff] [blame] | 430 | } |