memcheck/tests/sh-mem-random.c: Set huge_addr to 240GB
[valgrind.git] / drd / drd_clientreq.c
blob914d9a3482416a1ad0790cebb0675b1118c56599
1 /*
2 This file is part of drd, a thread error detector.
4 Copyright (C) 2006-2024 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, see <http://www.gnu.org/licenses/>.
19 The GNU General Public License is contained in the file COPYING.
23 #include "drd_barrier.h"
24 #include "drd_clientreq.h"
25 #include "drd_cond.h"
26 #include "drd_error.h"
27 #include "drd_hb.h"
28 #include "drd_load_store.h"
29 #include "drd_malloc_wrappers.h"
30 #include "drd_mutex.h"
31 #include "drd_rwlock.h"
32 #include "drd_semaphore.h"
33 #include "drd_suppression.h" // drd_start_suppression()
34 #include "drd_thread.h"
35 #include "pub_tool_basics.h" // Bool
36 #include "pub_tool_libcassert.h"
37 #include "pub_tool_libcassert.h" // tl_assert()
38 #include "pub_tool_libcprint.h" // VG_(message)()
39 #include "pub_tool_machine.h" // VG_(get_SP)()
40 #include "pub_tool_threadstate.h"
41 #include "pub_tool_tooliface.h" // VG_(needs_...)()
44 /* Global variables. */
46 Bool DRD_(g_free_is_write);
49 /* Function definitions. */
51 static Bool handle_core_client_request(ThreadId vg_tid, UWord* arg, UWord* ret)
53 tl_assert(vg_tid == VG_(get_running_tid)());
55 switch (arg[0])
57 case VG_USERREQ__MALLOCLIKE_BLOCK:
58 if (DRD_(g_free_is_write)) {
59 GenericErrInfo GEI = {
60 .tid = DRD_(thread_get_running_tid)(),
61 .addr = 0,
63 VG_(maybe_record_error)(vg_tid,
64 GenericErr,
65 VG_(get_IP)(vg_tid),
66 "--free-is-write=yes is incompatible with"
67 " custom memory allocator client requests",
68 &GEI);
70 if (arg[1])
71 DRD_(malloclike_block)(vg_tid, arg[1]/*addr*/, arg[2]/*size*/);
72 break;
74 case VG_USERREQ__RESIZEINPLACE_BLOCK:
75 if (!DRD_(freelike_block)(vg_tid, arg[1]/*addr*/, False))
77 GenericErrInfo GEI = {
78 .tid = DRD_(thread_get_running_tid)(),
79 .addr = 0,
81 VG_(maybe_record_error)(vg_tid,
82 GenericErr,
83 VG_(get_IP)(vg_tid),
84 "Invalid VG_USERREQ__RESIZEINPLACE_BLOCK request",
85 &GEI);
87 DRD_(malloclike_block)(vg_tid, arg[1]/*addr*/, arg[3]/*newSize*/);
88 break;
90 case VG_USERREQ__FREELIKE_BLOCK:
91 if (arg[1] && ! DRD_(freelike_block)(vg_tid, arg[1]/*addr*/, False))
93 GenericErrInfo GEI = {
94 .tid = DRD_(thread_get_running_tid)(),
95 .addr = 0,
97 VG_(maybe_record_error)(vg_tid,
98 GenericErr,
99 VG_(get_IP)(vg_tid),
100 "Invalid VG_USERREQ__FREELIKE_BLOCK request",
101 &GEI);
103 break;
106 *ret = 0;
107 return True;
110 #if defined(VGP_mips32_linux) || defined(VGP_mips64_linux)
111 /* There is a cse related issue in gcc for MIPS. Optimization level
112 has to be lowered, so cse related optimizations are not
113 included. */
114 __attribute__((optimize("O1")))
115 #endif
116 static Bool handle_thr_client_request(ThreadId vg_tid, UWord* arg, UWord* ret)
118 const DrdThreadId drd_tid = DRD_(thread_get_running_tid)();
119 UWord result = 0;
121 tl_assert(vg_tid == VG_(get_running_tid)());
122 tl_assert(DRD_(VgThreadIdToDrdThreadId)(vg_tid) == drd_tid);
124 switch (arg[0])
126 case VG_USERREQ__DRD_GET_VALGRIND_THREAD_ID:
127 result = vg_tid;
128 break;
130 case VG_USERREQ__DRD_GET_DRD_THREAD_ID:
131 result = drd_tid;
132 break;
134 case VG_USERREQ__DRD_SET_THREAD_NAME:
135 DRD_(thread_set_name)(drd_tid, (const HChar*)arg[1]);
136 break;
138 case VG_USERREQ__DRD_START_SUPPRESSION:
139 /*_VG_USERREQ__HG_ARANGE_MAKE_UNTRACKED*/
140 case VG_USERREQ_TOOL_BASE('H','G') + 256 + 39:
141 DRD_(start_suppression)(arg[1], arg[1] + arg[2], "client");
142 break;
144 case VG_USERREQ__DRD_FINISH_SUPPRESSION:
145 /*_VG_USERREQ__HG_ARANGE_MAKE_TRACKED*/
146 case VG_USERREQ_TOOL_BASE('H','G') + 256 + 40:
147 DRD_(finish_suppression)(arg[1], arg[1] + arg[2]);
148 break;
150 case VG_USERREQ__DRD_ANNOTATE_HAPPENS_BEFORE:
151 DRD_(hb_happens_before)(drd_tid, arg[1]);
152 break;
154 case VG_USERREQ__DRD_ANNOTATE_HAPPENS_AFTER:
155 DRD_(hb_happens_after)(drd_tid, arg[1]);
156 break;
158 case VG_USERREQ__DRD_ANNOTATE_RWLOCK_CREATE:
159 if (arg[1])
161 struct mutex_info* const mutex_p = DRD_(mutex_get)(arg[1]);
162 if (mutex_p && mutex_p->mutex_type == mutex_type_spinlock)
163 break;
165 DRD_(rwlock_pre_init)(arg[1], user_rwlock);
166 break;
168 case VG_USERREQ__DRD_ANNOTATE_RWLOCK_DESTROY:
169 if (arg[1])
171 struct mutex_info* const mutex_p = DRD_(mutex_get)(arg[1]);
172 if (mutex_p && mutex_p->mutex_type == mutex_type_spinlock)
173 break;
175 DRD_(rwlock_post_destroy)(arg[1], user_rwlock);
176 break;
178 case VG_USERREQ__DRD_ANNOTATE_RWLOCK_ACQUIRED:
179 if (arg[1])
181 struct mutex_info* const mutex_p = DRD_(mutex_get)(arg[1]);
182 if (mutex_p && mutex_p->mutex_type == mutex_type_spinlock)
183 break;
185 tl_assert(arg[2] == !! arg[2]);
186 if (arg[2])
188 DRD_(rwlock_pre_wrlock)(arg[1], user_rwlock);
189 DRD_(rwlock_post_wrlock)(arg[1], user_rwlock, True);
191 else
193 DRD_(rwlock_pre_rdlock)(arg[1], user_rwlock);
194 DRD_(rwlock_post_rdlock)(arg[1], user_rwlock, True);
196 break;
198 case VG_USERREQ__DRD_ANNOTATE_RWLOCK_RELEASED:
199 if (arg[1])
201 struct mutex_info* const mutex_p = DRD_(mutex_get)(arg[1]);
202 if (mutex_p && mutex_p->mutex_type == mutex_type_spinlock)
203 break;
205 tl_assert(arg[2] == !! arg[2]);
206 DRD_(rwlock_pre_unlock)(arg[1], user_rwlock);
207 break;
209 case VG_USERREQ__DRD_ANNOTATE_SEM_INIT_PRE:
210 DRD_(semaphore_init)(arg[1], 0, arg[2]);
211 break;
213 case VG_USERREQ__DRD_ANNOTATE_SEM_DESTROY_POST:
214 DRD_(semaphore_destroy)(arg[1]);
215 break;
217 case VG_USERREQ__DRD_ANNOTATE_SEM_WAIT_PRE:
218 DRD_(semaphore_pre_wait)(arg[1]);
219 break;
221 case VG_USERREQ__DRD_ANNOTATE_SEM_WAIT_POST:
222 DRD_(semaphore_post_wait)(drd_tid, arg[1], True /* waited */);
223 break;
225 case VG_USERREQ__DRD_ANNOTATE_SEM_POST_PRE:
226 DRD_(semaphore_pre_post)(drd_tid, arg[1]);
227 break;
229 case VG_USERREQ_DRD_SET_PTHREAD_COND_INITIALIZER:
230 DRD_(pthread_cond_initializer) = (Addr)arg[1];
231 DRD_(pthread_cond_initializer_size) = arg[2];
232 break;
234 case VG_USERREQ_DRD_START_NEW_SEGMENT:
235 DRD_(thread_new_segment)(DRD_(PtThreadIdToDrdThreadId)(arg[1]));
236 break;
238 case VG_USERREQ__DRD_START_TRACE_ADDR:
239 DRD_(start_tracing_address_range)(arg[1], arg[1] + arg[2], False);
240 break;
242 case VG_USERREQ__DRD_STOP_TRACE_ADDR:
243 DRD_(stop_tracing_address_range)(arg[1], arg[1] + arg[2]);
244 break;
246 case VG_USERREQ__DRD_RECORD_LOADS:
247 DRD_(thread_set_record_loads)(drd_tid, arg[1]);
248 break;
250 case VG_USERREQ__DRD_RECORD_STORES:
251 DRD_(thread_set_record_stores)(drd_tid, arg[1]);
252 break;
254 case VG_USERREQ_DRD_SET_PTHREADID:
255 // pthread_self() returns 0 for programs not linked with libpthread.so.
256 if (arg[1] != INVALID_POSIX_THREADID)
257 DRD_(thread_set_pthreadid)(drd_tid, arg[1]);
258 break;
260 case VG_USERREQ_DRD_SET_JOINABLE:
262 const DrdThreadId drd_joinable = DRD_(PtThreadIdToDrdThreadId)(arg[1]);
263 if (drd_joinable != DRD_INVALID_THREADID)
264 DRD_(thread_set_joinable)(drd_joinable, (Bool)arg[2]);
265 else {
266 InvalidThreadIdInfo ITI = { DRD_(thread_get_running_tid)(), arg[1] };
267 VG_(maybe_record_error)(vg_tid,
268 InvalidThreadId,
269 VG_(get_IP)(vg_tid),
270 "pthread_detach(): invalid thread ID",
271 &ITI);
273 break;
276 case VG_USERREQ_DRD_ENTERING_PTHREAD_CREATE:
277 DRD_(thread_entering_pthread_create)(drd_tid);
278 break;
280 case VG_USERREQ_DRD_LEFT_PTHREAD_CREATE:
281 DRD_(thread_left_pthread_create)(drd_tid);
282 break;
284 case VG_USERREQ_DRD_POST_THREAD_JOIN:
286 const DrdThreadId thread_to_join = DRD_(PtThreadIdToDrdThreadId)(arg[1]);
287 if (thread_to_join == DRD_INVALID_THREADID)
289 InvalidThreadIdInfo ITI = { DRD_(thread_get_running_tid)(), arg[1] };
290 VG_(maybe_record_error)(vg_tid,
291 InvalidThreadId,
292 VG_(get_IP)(vg_tid),
293 "pthread_join(): invalid thread ID",
294 &ITI);
296 else
298 DRD_(thread_post_join)(drd_tid, thread_to_join);
300 break;
303 case VG_USERREQ_DRD_PRE_THREAD_CANCEL:
305 const DrdThreadId thread_to_cancel =DRD_(PtThreadIdToDrdThreadId)(arg[1]);
306 if (thread_to_cancel == DRD_INVALID_THREADID)
308 InvalidThreadIdInfo ITI = { DRD_(thread_get_running_tid)(), arg[1] };
309 VG_(maybe_record_error)(vg_tid,
310 InvalidThreadId,
311 VG_(get_IP)(vg_tid),
312 "pthread_cancel(): invalid thread ID",
313 &ITI);
315 else
317 DRD_(thread_pre_cancel)(thread_to_cancel);
319 break;
322 case VG_USERREQ_DRD_POST_THREAD_CANCEL:
323 break;
325 case VG_USERREQ_DRD_PRE_MUTEX_INIT:
326 if (DRD_(thread_enter_synchr)(drd_tid) == 0)
327 DRD_(mutex_init)(arg[1], arg[2]);
328 break;
330 case VG_USERREQ_DRD_POST_MUTEX_INIT:
331 DRD_(thread_leave_synchr)(drd_tid);
332 break;
334 case VG_USERREQ_DRD_PRE_MUTEX_DESTROY:
335 DRD_(thread_enter_synchr)(drd_tid);
336 break;
338 case VG_USERREQ_DRD_POST_MUTEX_DESTROY:
339 if (DRD_(thread_leave_synchr)(drd_tid) == 0)
340 DRD_(mutex_post_destroy)(arg[1]);
341 break;
343 case VG_USERREQ_DRD_PRE_MUTEX_LOCK:
344 if (DRD_(thread_enter_synchr)(drd_tid) == 0)
345 DRD_(mutex_pre_lock)(arg[1], arg[2], arg[3]);
346 break;
348 case VG_USERREQ_DRD_POST_MUTEX_LOCK:
349 if (DRD_(thread_leave_synchr)(drd_tid) == 0)
350 DRD_(mutex_post_lock)(arg[1], arg[2], False/*post_cond_wait*/);
351 break;
353 case VG_USERREQ_DRD_PRE_MUTEX_UNLOCK:
354 if (DRD_(thread_enter_synchr)(drd_tid) == 0)
355 DRD_(mutex_unlock)(arg[1], arg[2]);
356 break;
358 case VG_USERREQ_DRD_POST_MUTEX_UNLOCK:
359 DRD_(thread_leave_synchr)(drd_tid);
360 break;
362 case VG_USERREQ__DRD_IGNORE_MUTEX_ORDERING:
363 DRD_(mutex_ignore_ordering)(arg[1]);
364 break;
366 case VG_USERREQ_DRD_PRE_SPIN_INIT_OR_UNLOCK:
367 if (DRD_(thread_enter_synchr)(drd_tid) == 0)
368 DRD_(spinlock_init_or_unlock)(arg[1]);
369 break;
371 case VG_USERREQ_DRD_POST_SPIN_INIT_OR_UNLOCK:
372 DRD_(thread_leave_synchr)(drd_tid);
373 break;
375 case VG_USERREQ_DRD_PRE_COND_INIT:
376 if (DRD_(thread_enter_synchr)(drd_tid) == 0)
377 DRD_(cond_pre_init)(arg[1]);
378 break;
380 case VG_USERREQ_DRD_POST_COND_INIT:
381 DRD_(thread_leave_synchr)(drd_tid);
382 break;
384 case VG_USERREQ_DRD_PRE_COND_DESTROY:
385 DRD_(thread_enter_synchr)(drd_tid);
386 break;
388 case VG_USERREQ_DRD_POST_COND_DESTROY:
389 if (DRD_(thread_leave_synchr)(drd_tid) == 0)
390 DRD_(cond_post_destroy)(arg[1], arg[2]);
391 break;
393 case VG_USERREQ_DRD_PRE_COND_WAIT:
394 if (DRD_(thread_enter_synchr)(drd_tid) == 0)
396 const Addr cond = arg[1];
397 const Addr mutex = arg[2];
398 const MutexT mutex_type = arg[3];
399 DRD_(mutex_unlock)(mutex, mutex_type);
400 DRD_(cond_pre_wait)(cond, mutex);
402 break;
404 case VG_USERREQ_DRD_POST_COND_WAIT:
405 if (DRD_(thread_leave_synchr)(drd_tid) == 0)
407 const Addr cond = arg[1];
408 const Addr mutex = arg[2];
409 const Bool took_lock = arg[3];
410 DRD_(cond_post_wait)(cond);
411 DRD_(mutex_post_lock)(mutex, took_lock, True);
413 break;
415 case VG_USERREQ_DRD_PRE_COND_SIGNAL:
416 if (DRD_(thread_enter_synchr)(drd_tid) == 0)
417 DRD_(cond_pre_signal)(arg[1]);
418 break;
420 case VG_USERREQ_DRD_POST_COND_SIGNAL:
421 DRD_(thread_leave_synchr)(drd_tid);
422 break;
424 case VG_USERREQ_DRD_PRE_COND_BROADCAST:
425 if (DRD_(thread_enter_synchr)(drd_tid) == 0)
426 DRD_(cond_pre_broadcast)(arg[1]);
427 break;
429 case VG_USERREQ_DRD_POST_COND_BROADCAST:
430 DRD_(thread_leave_synchr)(drd_tid);
431 break;
433 case VG_USERREQ_DRD_PRE_SEM_INIT:
434 if (DRD_(thread_enter_synchr)(drd_tid) == 0)
435 DRD_(semaphore_init)(arg[1], arg[2], arg[3]);
436 break;
438 case VG_USERREQ_DRD_POST_SEM_INIT:
439 DRD_(thread_leave_synchr)(drd_tid);
440 break;
442 case VG_USERREQ_DRD_PRE_SEM_DESTROY:
443 DRD_(thread_enter_synchr)(drd_tid);
444 break;
446 case VG_USERREQ_DRD_POST_SEM_DESTROY:
447 if (DRD_(thread_leave_synchr)(drd_tid) == 0)
448 DRD_(semaphore_destroy)(arg[1]);
449 break;
451 case VG_USERREQ_DRD_PRE_SEM_OPEN:
452 DRD_(thread_enter_synchr)(drd_tid);
453 break;
455 case VG_USERREQ_DRD_POST_SEM_OPEN:
456 if (DRD_(thread_leave_synchr)(drd_tid) == 0)
457 DRD_(semaphore_open)(arg[1], (HChar*)arg[2], arg[3], arg[4], arg[5]);
458 break;
460 case VG_USERREQ_DRD_PRE_SEM_CLOSE:
461 if (DRD_(thread_enter_synchr)(drd_tid) == 0)
462 DRD_(semaphore_close)(arg[1]);
463 break;
465 case VG_USERREQ_DRD_POST_SEM_CLOSE:
466 DRD_(thread_leave_synchr)(drd_tid);
467 break;
469 case VG_USERREQ_DRD_PRE_SEM_WAIT:
470 if (DRD_(thread_enter_synchr)(drd_tid) == 0)
471 DRD_(semaphore_pre_wait)(arg[1]);
472 break;
474 case VG_USERREQ_DRD_POST_SEM_WAIT:
475 if (DRD_(thread_leave_synchr)(drd_tid) == 0)
476 DRD_(semaphore_post_wait)(drd_tid, arg[1], arg[2]);
477 break;
479 case VG_USERREQ_DRD_PRE_SEM_POST:
480 if (DRD_(thread_enter_synchr)(drd_tid) == 0)
481 DRD_(semaphore_pre_post)(drd_tid, arg[1]);
482 break;
484 case VG_USERREQ_DRD_POST_SEM_POST:
485 if (DRD_(thread_leave_synchr)(drd_tid) == 0)
486 DRD_(semaphore_post_post)(drd_tid, arg[1], arg[2]);
487 break;
489 case VG_USERREQ_DRD_PRE_BARRIER_INIT:
490 if (DRD_(thread_enter_synchr)(drd_tid) == 0)
491 DRD_(barrier_init)(arg[1], arg[2], arg[3], arg[4]);
492 break;
494 case VG_USERREQ_DRD_POST_BARRIER_INIT:
495 DRD_(thread_leave_synchr)(drd_tid);
496 break;
498 case VG_USERREQ_DRD_PRE_BARRIER_DESTROY:
499 DRD_(thread_enter_synchr)(drd_tid);
500 break;
502 case VG_USERREQ_DRD_POST_BARRIER_DESTROY:
503 if (DRD_(thread_leave_synchr)(drd_tid) == 0)
504 DRD_(barrier_destroy)(arg[1], arg[2]);
505 break;
507 case VG_USERREQ_DRD_PRE_BARRIER_WAIT:
508 if (DRD_(thread_enter_synchr)(drd_tid) == 0)
509 DRD_(barrier_pre_wait)(drd_tid, arg[1], arg[2]);
510 break;
512 case VG_USERREQ_DRD_POST_BARRIER_WAIT:
513 if (DRD_(thread_leave_synchr)(drd_tid) == 0)
514 DRD_(barrier_post_wait)(drd_tid, arg[1], arg[2], arg[3], arg[4]);
515 break;
517 case VG_USERREQ_DRD_PRE_RWLOCK_INIT:
518 if (DRD_(thread_enter_synchr)(drd_tid) == 0)
519 DRD_(rwlock_pre_init)(arg[1], pthread_rwlock);
520 break;
522 case VG_USERREQ_DRD_POST_RWLOCK_INIT:
523 DRD_(thread_leave_synchr)(drd_tid);
524 break;
526 case VG_USERREQ_DRD_PRE_RWLOCK_DESTROY:
527 DRD_(thread_enter_synchr)(drd_tid);
528 break;
530 case VG_USERREQ_DRD_POST_RWLOCK_DESTROY:
531 if (DRD_(thread_leave_synchr)(drd_tid) == 0)
532 DRD_(rwlock_post_destroy)(arg[1], pthread_rwlock);
533 break;
535 case VG_USERREQ_DRD_PRE_RWLOCK_RDLOCK:
536 if (DRD_(thread_enter_synchr)(drd_tid) == 0)
537 DRD_(rwlock_pre_rdlock)(arg[1], pthread_rwlock);
538 break;
540 case VG_USERREQ_DRD_POST_RWLOCK_RDLOCK:
541 if (DRD_(thread_leave_synchr)(drd_tid) == 0)
542 DRD_(rwlock_post_rdlock)(arg[1], pthread_rwlock, arg[2]);
543 break;
545 case VG_USERREQ_DRD_PRE_RWLOCK_WRLOCK:
546 if (DRD_(thread_enter_synchr)(drd_tid) == 0)
547 DRD_(rwlock_pre_wrlock)(arg[1], pthread_rwlock);
548 break;
550 case VG_USERREQ_DRD_POST_RWLOCK_WRLOCK:
551 if (DRD_(thread_leave_synchr)(drd_tid) == 0)
552 DRD_(rwlock_post_wrlock)(arg[1], pthread_rwlock, arg[2]);
553 break;
555 case VG_USERREQ_DRD_PRE_RWLOCK_UNLOCK:
556 if (DRD_(thread_enter_synchr)(drd_tid) == 0)
557 DRD_(rwlock_pre_unlock)(arg[1], pthread_rwlock);
558 break;
560 case VG_USERREQ_DRD_POST_RWLOCK_UNLOCK:
561 DRD_(thread_leave_synchr)(drd_tid);
562 break;
564 case VG_USERREQ__DRD_CLEAN_MEMORY:
565 if (arg[2] > 0)
566 DRD_(clean_memory)(arg[1], arg[2]);
567 break;
569 case VG_USERREQ__HELGRIND_ANNOTATION_UNIMP:
571 /* Note: it is assumed below that the text arg[1] points to is never
572 * freed, e.g. because it points to static data.
574 UnimpClReqInfo UICR =
575 { DRD_(thread_get_running_tid)(), (HChar*)arg[1] };
576 VG_(maybe_record_error)(vg_tid,
577 UnimpHgClReq,
578 VG_(get_IP)(vg_tid),
580 &UICR);
582 break;
584 case VG_USERREQ__DRD_ANNOTATION_UNIMP:
586 /* Note: it is assumed below that the text arg[1] points to is never
587 * freed, e.g. because it points to static data.
589 UnimpClReqInfo UICR =
590 { DRD_(thread_get_running_tid)(), (HChar*)arg[1] };
591 VG_(maybe_record_error)(vg_tid,
592 UnimpDrdClReq,
593 VG_(get_IP)(vg_tid),
595 &UICR);
597 break;
599 #if defined(VGO_solaris)
600 case VG_USERREQ_DRD_RTLD_BIND_GUARD:
601 DRD_(thread_entering_rtld_bind_guard)(drd_tid, arg[1]);
602 break;
604 case VG_USERREQ_DRD_RTLD_BIND_CLEAR:
605 DRD_(thread_leaving_rtld_bind_clear)(drd_tid, arg[1]);
606 break;
607 #endif /* VGO_solaris */
609 default:
610 if (VG_IS_TOOL_USERREQ('D','R',arg[0]) ||
611 VG_IS_TOOL_USERREQ('D','r',arg[0])) {
612 /* don't warn about any unhandled HG client reqs */
613 VG_(message)(Vg_UserMsg,
614 "Warning: unknown DRD client request code %llx\n",
615 (ULong)arg[0]);
617 return False;
620 *ret = result;
621 return True;
625 * DRD's handler for Valgrind client requests. The code below handles both
626 * DRD's public and tool-internal client requests.
628 static Bool handle_client_request(ThreadId vg_tid, UWord* arg, UWord* ret)
630 if (VG_IS_TOOL_USERREQ(0, 0, arg[0]))
631 return handle_core_client_request(vg_tid, arg, ret);
633 if (VG_IS_TOOL_USERREQ('D', 'R', arg[0]) ||
634 VG_IS_TOOL_USERREQ('D', 'r', arg[0]) ||
635 VG_IS_TOOL_USERREQ('H', 'G', arg[0]))
636 return handle_thr_client_request(vg_tid, arg, ret);
638 return False;
642 * Tell the Valgrind core the address of the DRD function that processes
643 * client requests. Must be called before any client code is run.
645 void DRD_(clientreq_init)(void)
647 VG_(needs_client_requests)(handle_client_request);