Remove emacs modeline and/or local variables from DRD source files
[valgrind.git] / drd / drd_clientreq.c
blob3173282becc0a2db6003061151dbcd51fff1689c
1 /*
2 This file is part of drd, a thread error detector.
4 Copyright (C) 2006-2011 Bart Van Assche <bvanassche@acm.org>.
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License as
8 published by the Free Software Foundation; either version 2 of the
9 License, or (at your option) any later version.
11 This program is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307, USA.
21 The GNU General Public License is contained in the file COPYING.
25 #include "drd_barrier.h"
26 #include "drd_clientreq.h"
27 #include "drd_cond.h"
28 #include "drd_error.h"
29 #include "drd_hb.h"
30 #include "drd_load_store.h"
31 #include "drd_malloc_wrappers.h"
32 #include "drd_mutex.h"
33 #include "drd_rwlock.h"
34 #include "drd_semaphore.h"
35 #include "drd_suppression.h" // drd_start_suppression()
36 #include "drd_thread.h"
37 #include "pub_tool_basics.h" // Bool
38 #include "pub_tool_debuginfo.h" // VG_(describe_IP)()
39 #include "pub_tool_libcassert.h"
40 #include "pub_tool_libcassert.h" // tl_assert()
41 #include "pub_tool_libcprint.h" // VG_(message)()
42 #include "pub_tool_machine.h" // VG_(get_SP)()
43 #include "pub_tool_threadstate.h"
44 #include "pub_tool_tooliface.h" // VG_(needs_...)()
47 /* Global variables. */
49 Bool DRD_(g_free_is_write);
52 /* Local function declarations. */
54 static Bool handle_client_request(ThreadId vg_tid, UWord* arg, UWord* ret);
57 /* Function definitions. */
59 /**
60 * Tell the Valgrind core the address of the DRD function that processes
61 * client requests. Must be called before any client code is run.
63 void DRD_(clientreq_init)(void)
65 VG_(needs_client_requests)(handle_client_request);
68 /**
69 * DRD's handler for Valgrind client requests. The code below handles both
70 * DRD's public and tool-internal client requests.
72 static Bool handle_client_request(ThreadId vg_tid, UWord* arg, UWord* ret)
74 UWord result = 0;
75 const DrdThreadId drd_tid = DRD_(thread_get_running_tid)();
77 tl_assert(vg_tid == VG_(get_running_tid()));
78 tl_assert(DRD_(VgThreadIdToDrdThreadId)(vg_tid) == drd_tid);
80 switch (arg[0])
82 case VG_USERREQ__MALLOCLIKE_BLOCK:
83 if (DRD_(g_free_is_write)) {
84 GenericErrInfo GEI = {
85 .tid = DRD_(thread_get_running_tid)(),
86 .addr = 0,
88 VG_(maybe_record_error)(vg_tid,
89 GenericErr,
90 VG_(get_IP)(vg_tid),
91 "--free-is-write=yes is incompatible with"
92 " custom memory allocator client requests",
93 &GEI);
95 if (arg[1])
96 DRD_(malloclike_block)(vg_tid, arg[1]/*addr*/, arg[2]/*size*/);
97 break;
99 case VG_USERREQ__RESIZEINPLACE_BLOCK:
100 if (!DRD_(freelike_block)(vg_tid, arg[1]/*addr*/, False))
102 GenericErrInfo GEI = {
103 .tid = DRD_(thread_get_running_tid)(),
104 .addr = 0,
106 VG_(maybe_record_error)(vg_tid,
107 GenericErr,
108 VG_(get_IP)(vg_tid),
109 "Invalid VG_USERREQ__RESIZEINPLACE_BLOCK request",
110 &GEI);
112 DRD_(malloclike_block)(vg_tid, arg[1]/*addr*/, arg[3]/*newSize*/);
113 break;
115 case VG_USERREQ__FREELIKE_BLOCK:
116 if (arg[1] && ! DRD_(freelike_block)(vg_tid, arg[1]/*addr*/, False))
118 GenericErrInfo GEI = {
119 .tid = DRD_(thread_get_running_tid)(),
120 .addr = 0,
122 VG_(maybe_record_error)(vg_tid,
123 GenericErr,
124 VG_(get_IP)(vg_tid),
125 "Invalid VG_USERREQ__FREELIKE_BLOCK request",
126 &GEI);
128 break;
130 case VG_USERREQ__DRD_GET_VALGRIND_THREAD_ID:
131 result = vg_tid;
132 break;
134 case VG_USERREQ__DRD_GET_DRD_THREAD_ID:
135 result = drd_tid;
136 break;
138 case VG_USERREQ__DRD_SET_THREAD_NAME:
139 DRD_(thread_set_name)(drd_tid, (const char*)arg[1]);
140 break;
142 case VG_USERREQ__DRD_START_SUPPRESSION:
143 /*_VG_USERREQ__HG_ARANGE_MAKE_UNTRACKED*/
144 case VG_USERREQ_TOOL_BASE('H','G') + 256 + 39:
145 DRD_(start_suppression)(arg[1], arg[1] + arg[2], "client");
146 break;
148 case VG_USERREQ__DRD_FINISH_SUPPRESSION:
149 /*_VG_USERREQ__HG_ARANGE_MAKE_TRACKED*/
150 case VG_USERREQ_TOOL_BASE('H','G') + 256 + 40:
151 DRD_(finish_suppression)(arg[1], arg[1] + arg[2]);
152 break;
154 case VG_USERREQ__DRD_ANNOTATE_HAPPENS_BEFORE:
155 DRD_(hb_happens_before)(drd_tid, arg[1]);
156 break;
158 case VG_USERREQ__DRD_ANNOTATE_HAPPENS_AFTER:
159 DRD_(hb_happens_after)(drd_tid, arg[1]);
160 break;
162 case VG_USERREQ__DRD_ANNOTATE_RWLOCK_CREATE:
163 if (arg[1])
165 struct mutex_info* const mutex_p = DRD_(mutex_get)(arg[1]);
166 if (mutex_p && mutex_p->mutex_type == mutex_type_spinlock)
167 break;
169 DRD_(rwlock_pre_init)(arg[1], user_rwlock);
170 break;
172 case VG_USERREQ__DRD_ANNOTATE_RWLOCK_DESTROY:
173 if (arg[1])
175 struct mutex_info* const mutex_p = DRD_(mutex_get)(arg[1]);
176 if (mutex_p && mutex_p->mutex_type == mutex_type_spinlock)
177 break;
179 DRD_(rwlock_post_destroy)(arg[1], user_rwlock);
180 break;
182 case VG_USERREQ__DRD_ANNOTATE_RWLOCK_ACQUIRED:
183 if (arg[1])
185 struct mutex_info* const mutex_p = DRD_(mutex_get)(arg[1]);
186 if (mutex_p && mutex_p->mutex_type == mutex_type_spinlock)
187 break;
189 tl_assert(arg[2] == !! arg[2]);
190 if (arg[2])
192 DRD_(rwlock_pre_wrlock)(arg[1], user_rwlock);
193 DRD_(rwlock_post_wrlock)(arg[1], user_rwlock, True);
195 else
197 DRD_(rwlock_pre_rdlock)(arg[1], user_rwlock);
198 DRD_(rwlock_post_rdlock)(arg[1], user_rwlock, True);
200 break;
202 case VG_USERREQ__DRD_ANNOTATE_RWLOCK_RELEASED:
203 if (arg[1])
205 struct mutex_info* const mutex_p = DRD_(mutex_get)(arg[1]);
206 if (mutex_p && mutex_p->mutex_type == mutex_type_spinlock)
207 break;
209 tl_assert(arg[2] == !! arg[2]);
210 DRD_(rwlock_pre_unlock)(arg[1], user_rwlock);
211 break;
213 case VG_USERREQ__SET_PTHREAD_COND_INITIALIZER:
214 DRD_(pthread_cond_initializer) = (Addr)arg[1];
215 DRD_(pthread_cond_initializer_size) = arg[2];
216 break;
218 case VG_USERREQ__DRD_START_NEW_SEGMENT:
219 DRD_(thread_new_segment)(DRD_(PtThreadIdToDrdThreadId)(arg[1]));
220 break;
222 case VG_USERREQ__DRD_START_TRACE_ADDR:
223 DRD_(start_tracing_address_range)(arg[1], arg[1] + arg[2]);
224 break;
226 case VG_USERREQ__DRD_STOP_TRACE_ADDR:
227 DRD_(stop_tracing_address_range)(arg[1], arg[1] + arg[2]);
228 break;
230 case VG_USERREQ__DRD_RECORD_LOADS:
231 DRD_(thread_set_record_loads)(drd_tid, arg[1]);
232 break;
234 case VG_USERREQ__DRD_RECORD_STORES:
235 DRD_(thread_set_record_stores)(drd_tid, arg[1]);
236 break;
238 case VG_USERREQ__SET_PTHREADID:
239 // pthread_self() returns 0 for programs not linked with libpthread.so.
240 if (arg[1] != INVALID_POSIX_THREADID)
241 DRD_(thread_set_pthreadid)(drd_tid, arg[1]);
242 break;
244 case VG_USERREQ__SET_JOINABLE:
246 const DrdThreadId drd_joinable = DRD_(PtThreadIdToDrdThreadId)(arg[1]);
247 if (drd_joinable != DRD_INVALID_THREADID)
248 DRD_(thread_set_joinable)(drd_joinable, (Bool)arg[2]);
249 else {
250 InvalidThreadIdInfo ITI = { DRD_(thread_get_running_tid)(), arg[1] };
251 VG_(maybe_record_error)(vg_tid,
252 InvalidThreadId,
253 VG_(get_IP)(vg_tid),
254 "pthread_detach(): invalid thread ID",
255 &ITI);
257 break;
260 case VG_USERREQ__ENTERING_PTHREAD_CREATE:
261 DRD_(thread_entering_pthread_create)(drd_tid);
262 break;
264 case VG_USERREQ__LEFT_PTHREAD_CREATE:
265 DRD_(thread_left_pthread_create)(drd_tid);
266 break;
268 case VG_USERREQ__POST_THREAD_JOIN:
270 const DrdThreadId thread_to_join = DRD_(PtThreadIdToDrdThreadId)(arg[1]);
271 if (thread_to_join == DRD_INVALID_THREADID)
273 InvalidThreadIdInfo ITI = { DRD_(thread_get_running_tid)(), arg[1] };
274 VG_(maybe_record_error)(vg_tid,
275 InvalidThreadId,
276 VG_(get_IP)(vg_tid),
277 "pthread_join(): invalid thread ID",
278 &ITI);
280 else
282 DRD_(thread_post_join)(drd_tid, thread_to_join);
284 break;
287 case VG_USERREQ__PRE_THREAD_CANCEL:
289 const DrdThreadId thread_to_cancel =DRD_(PtThreadIdToDrdThreadId)(arg[1]);
290 if (thread_to_cancel == DRD_INVALID_THREADID)
292 InvalidThreadIdInfo ITI = { DRD_(thread_get_running_tid)(), arg[1] };
293 VG_(maybe_record_error)(vg_tid,
294 InvalidThreadId,
295 VG_(get_IP)(vg_tid),
296 "pthread_cancel(): invalid thread ID",
297 &ITI);
299 else
301 DRD_(thread_pre_cancel)(thread_to_cancel);
303 break;
306 case VG_USERREQ__POST_THREAD_CANCEL:
307 break;
309 case VG_USERREQ__PRE_MUTEX_INIT:
310 if (DRD_(thread_enter_synchr)(drd_tid) == 0)
311 DRD_(mutex_init)(arg[1], arg[2]);
312 break;
314 case VG_USERREQ__POST_MUTEX_INIT:
315 DRD_(thread_leave_synchr)(drd_tid);
316 break;
318 case VG_USERREQ__PRE_MUTEX_DESTROY:
319 DRD_(thread_enter_synchr)(drd_tid);
320 break;
322 case VG_USERREQ__POST_MUTEX_DESTROY:
323 if (DRD_(thread_leave_synchr)(drd_tid) == 0)
324 DRD_(mutex_post_destroy)(arg[1]);
325 break;
327 case VG_USERREQ__PRE_MUTEX_LOCK:
328 if (DRD_(thread_enter_synchr)(drd_tid) == 0)
329 DRD_(mutex_pre_lock)(arg[1], arg[2], arg[3]);
330 break;
332 case VG_USERREQ__POST_MUTEX_LOCK:
333 if (DRD_(thread_leave_synchr)(drd_tid) == 0)
334 DRD_(mutex_post_lock)(arg[1], arg[2], False/*post_cond_wait*/);
335 break;
337 case VG_USERREQ__PRE_MUTEX_UNLOCK:
338 if (DRD_(thread_enter_synchr)(drd_tid) == 0)
339 DRD_(mutex_unlock)(arg[1], arg[2]);
340 break;
342 case VG_USERREQ__POST_MUTEX_UNLOCK:
343 DRD_(thread_leave_synchr)(drd_tid);
344 break;
346 case VG_USERREQ__PRE_SPIN_INIT_OR_UNLOCK:
347 if (DRD_(thread_enter_synchr)(drd_tid) == 0)
348 DRD_(spinlock_init_or_unlock)(arg[1]);
349 break;
351 case VG_USERREQ__POST_SPIN_INIT_OR_UNLOCK:
352 DRD_(thread_leave_synchr)(drd_tid);
353 break;
355 case VG_USERREQ__PRE_COND_INIT:
356 if (DRD_(thread_enter_synchr)(drd_tid) == 0)
357 DRD_(cond_pre_init)(arg[1]);
358 break;
360 case VG_USERREQ__POST_COND_INIT:
361 DRD_(thread_leave_synchr)(drd_tid);
362 break;
364 case VG_USERREQ__PRE_COND_DESTROY:
365 DRD_(thread_enter_synchr)(drd_tid);
366 break;
368 case VG_USERREQ__POST_COND_DESTROY:
369 if (DRD_(thread_leave_synchr)(drd_tid) == 0)
370 DRD_(cond_post_destroy)(arg[1]);
371 break;
373 case VG_USERREQ__PRE_COND_WAIT:
374 if (DRD_(thread_enter_synchr)(drd_tid) == 0)
376 const Addr cond = arg[1];
377 const Addr mutex = arg[2];
378 const MutexT mutex_type = arg[3];
379 DRD_(mutex_unlock)(mutex, mutex_type);
380 DRD_(cond_pre_wait)(cond, mutex);
382 break;
384 case VG_USERREQ__POST_COND_WAIT:
385 if (DRD_(thread_leave_synchr)(drd_tid) == 0)
387 const Addr cond = arg[1];
388 const Addr mutex = arg[2];
389 const Bool took_lock = arg[3];
390 DRD_(cond_post_wait)(cond);
391 DRD_(mutex_post_lock)(mutex, took_lock, True);
393 break;
395 case VG_USERREQ__PRE_COND_SIGNAL:
396 if (DRD_(thread_enter_synchr)(drd_tid) == 0)
397 DRD_(cond_pre_signal)(arg[1]);
398 break;
400 case VG_USERREQ__POST_COND_SIGNAL:
401 DRD_(thread_leave_synchr)(drd_tid);
402 break;
404 case VG_USERREQ__PRE_COND_BROADCAST:
405 if (DRD_(thread_enter_synchr)(drd_tid) == 0)
406 DRD_(cond_pre_broadcast)(arg[1]);
407 break;
409 case VG_USERREQ__POST_COND_BROADCAST:
410 DRD_(thread_leave_synchr)(drd_tid);
411 break;
413 case VG_USERREQ__PRE_SEM_INIT:
414 if (DRD_(thread_enter_synchr)(drd_tid) == 0)
415 DRD_(semaphore_init)(arg[1], arg[2], arg[3]);
416 break;
418 case VG_USERREQ__POST_SEM_INIT:
419 DRD_(thread_leave_synchr)(drd_tid);
420 break;
422 case VG_USERREQ__PRE_SEM_DESTROY:
423 DRD_(thread_enter_synchr)(drd_tid);
424 break;
426 case VG_USERREQ__POST_SEM_DESTROY:
427 if (DRD_(thread_leave_synchr)(drd_tid) == 0)
428 DRD_(semaphore_destroy)(arg[1]);
429 break;
431 case VG_USERREQ__PRE_SEM_OPEN:
432 DRD_(thread_enter_synchr)(drd_tid);
433 break;
435 case VG_USERREQ__POST_SEM_OPEN:
436 if (DRD_(thread_leave_synchr)(drd_tid) == 0)
437 DRD_(semaphore_open)(arg[1], (Char*)arg[2], arg[3], arg[4], arg[5]);
438 break;
440 case VG_USERREQ__PRE_SEM_CLOSE:
441 if (DRD_(thread_enter_synchr)(drd_tid) == 0)
442 DRD_(semaphore_close)(arg[1]);
443 break;
445 case VG_USERREQ__POST_SEM_CLOSE:
446 DRD_(thread_leave_synchr)(drd_tid);
447 break;
449 case VG_USERREQ__PRE_SEM_WAIT:
450 if (DRD_(thread_enter_synchr)(drd_tid) == 0)
451 DRD_(semaphore_pre_wait)(arg[1]);
452 break;
454 case VG_USERREQ__POST_SEM_WAIT:
455 if (DRD_(thread_leave_synchr)(drd_tid) == 0)
456 DRD_(semaphore_post_wait)(drd_tid, arg[1], arg[2]);
457 break;
459 case VG_USERREQ__PRE_SEM_POST:
460 if (DRD_(thread_enter_synchr)(drd_tid) == 0)
461 DRD_(semaphore_pre_post)(drd_tid, arg[1]);
462 break;
464 case VG_USERREQ__POST_SEM_POST:
465 if (DRD_(thread_leave_synchr)(drd_tid) == 0)
466 DRD_(semaphore_post_post)(drd_tid, arg[1], arg[2]);
467 break;
469 case VG_USERREQ__PRE_BARRIER_INIT:
470 if (DRD_(thread_enter_synchr)(drd_tid) == 0)
471 DRD_(barrier_init)(arg[1], arg[2], arg[3], arg[4]);
472 break;
474 case VG_USERREQ__POST_BARRIER_INIT:
475 DRD_(thread_leave_synchr)(drd_tid);
476 break;
478 case VG_USERREQ__PRE_BARRIER_DESTROY:
479 DRD_(thread_enter_synchr)(drd_tid);
480 break;
482 case VG_USERREQ__POST_BARRIER_DESTROY:
483 if (DRD_(thread_leave_synchr)(drd_tid) == 0)
484 DRD_(barrier_destroy)(arg[1], arg[2]);
485 break;
487 case VG_USERREQ__PRE_BARRIER_WAIT:
488 if (DRD_(thread_enter_synchr)(drd_tid) == 0)
489 DRD_(barrier_pre_wait)(drd_tid, arg[1], arg[2]);
490 break;
492 case VG_USERREQ__POST_BARRIER_WAIT:
493 if (DRD_(thread_leave_synchr)(drd_tid) == 0)
494 DRD_(barrier_post_wait)(drd_tid, arg[1], arg[2], arg[3], arg[4]);
495 break;
497 case VG_USERREQ__PRE_RWLOCK_INIT:
498 DRD_(rwlock_pre_init)(arg[1], pthread_rwlock);
499 break;
501 case VG_USERREQ__POST_RWLOCK_DESTROY:
502 DRD_(rwlock_post_destroy)(arg[1], pthread_rwlock);
503 break;
505 case VG_USERREQ__PRE_RWLOCK_RDLOCK:
506 if (DRD_(thread_enter_synchr)(drd_tid) == 0)
507 DRD_(rwlock_pre_rdlock)(arg[1], pthread_rwlock);
508 break;
510 case VG_USERREQ__POST_RWLOCK_RDLOCK:
511 if (DRD_(thread_leave_synchr)(drd_tid) == 0)
512 DRD_(rwlock_post_rdlock)(arg[1], pthread_rwlock, arg[2]);
513 break;
515 case VG_USERREQ__PRE_RWLOCK_WRLOCK:
516 if (DRD_(thread_enter_synchr)(drd_tid) == 0)
517 DRD_(rwlock_pre_wrlock)(arg[1], pthread_rwlock);
518 break;
520 case VG_USERREQ__POST_RWLOCK_WRLOCK:
521 if (DRD_(thread_leave_synchr)(drd_tid) == 0)
522 DRD_(rwlock_post_wrlock)(arg[1], pthread_rwlock, arg[2]);
523 break;
525 case VG_USERREQ__PRE_RWLOCK_UNLOCK:
526 if (DRD_(thread_enter_synchr)(drd_tid) == 0)
527 DRD_(rwlock_pre_unlock)(arg[1], pthread_rwlock);
528 break;
530 case VG_USERREQ__POST_RWLOCK_UNLOCK:
531 DRD_(thread_leave_synchr)(drd_tid);
532 break;
534 case VG_USERREQ__DRD_CLEAN_MEMORY:
535 if (arg[2] > 0)
536 DRD_(clean_memory)(arg[1], arg[2]);
537 break;
539 case VG_USERREQ__HELGRIND_ANNOTATION_UNIMP:
541 /* Note: it is assumed below that the text arg[1] points to is never
542 * freed, e.g. because it points to static data.
544 UnimpClReqInfo UICR =
545 { DRD_(thread_get_running_tid)(), (Char*)arg[1] };
546 VG_(maybe_record_error)(vg_tid,
547 UnimpHgClReq,
548 VG_(get_IP)(vg_tid),
550 &UICR);
552 break;
554 case VG_USERREQ__DRD_ANNOTATION_UNIMP:
556 /* Note: it is assumed below that the text arg[1] points to is never
557 * freed, e.g. because it points to static data.
559 UnimpClReqInfo UICR =
560 { DRD_(thread_get_running_tid)(), (Char*)arg[1] };
561 VG_(maybe_record_error)(vg_tid,
562 UnimpDrdClReq,
563 VG_(get_IP)(vg_tid),
565 &UICR);
567 break;
569 default:
570 #if 0
571 VG_(message)(Vg_DebugMsg, "Unrecognized client request 0x%lx 0x%lx",
572 arg[0], arg[1]);
573 tl_assert(0);
574 #endif
575 return False;
578 *ret = result;
579 return True;