1 /* -*- mode: C; c-basic-offset: 3; -*- */ 2 3 /*--------------------------------------------------------------------*/ 4 /*--- Client-space code for DRD. drd_pthread_intercepts.c ---*/ 5 /*--------------------------------------------------------------------*/ 6 7 /* 8 This file is part of DRD, a thread error detector. 9 10 Copyright (C) 2006-2010 Bart Van Assche <bvanassche (at) acm.org>. 11 12 This program is free software; you can redistribute it and/or 13 modify it under the terms of the GNU General Public License as 14 published by the Free Software Foundation; either version 2 of the 15 License, or (at your option) any later version. 16 17 This program is distributed in the hope that it will be useful, but 18 WITHOUT ANY WARRANTY; without even the implied warranty of 19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 20 General Public License for more details. 21 22 You should have received a copy of the GNU General Public License 23 along with this program; if not, write to the Free Software 24 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 25 02111-1307, USA. 26 27 The GNU General Public License is contained in the file COPYING. 28 */ 29 30 /* --------------------------------------------------------------------- 31 ALL THE CODE IN THIS FILE RUNS ON THE SIMULATED CPU. 32 33 These functions are not called directly - they're the targets of code 34 redirection or load notifications (see pub_core_redir.h for info). 35 They're named weirdly so that the intercept code can find them when the 36 shared object is initially loaded. 37 38 Note that this filename has the "drd_" prefix because it can appear 39 in stack traces, and the "drd_" makes it a little clearer that it 40 originates from Valgrind. 41 ------------------------------------------------------------------ */ 42 43 /* 44 * Define _GNU_SOURCE to make sure that pthread_spinlock_t is available when 45 * compiling with older glibc versions (2.3 or before). 46 */ 47 #ifndef _GNU_SOURCE 48 #define _GNU_SOURCE 49 #endif 50 51 #include <assert.h> /* assert() */ 52 #include <pthread.h> /* pthread_mutex_t */ 53 #include <semaphore.h> /* sem_t */ 54 #include <stdint.h> /* uintptr_t */ 55 #include <stdio.h> /* fprintf() */ 56 #include <stdlib.h> /* malloc(), free() */ 57 #include <unistd.h> /* confstr() */ 58 #include "config.h" /* HAVE_PTHREAD_MUTEX_ADAPTIVE_NP etc. */ 59 #include "drd_basics.h" /* DRD_() */ 60 #include "drd_clientreq.h" 61 #include "pub_tool_redir.h" /* VG_WRAP_FUNCTION_ZZ() */ 62 63 64 /* Defines. */ 65 66 /* 67 * Do not undefine the two macro's below, or the following two subtle race 68 * conditions will be introduced in the data race detection algorithm: 69 * - sg_init() runs on the context of the created thread and copies the 70 * vector clock of the creator thread. This only works reliably if 71 * the creator thread waits until this copy has been performed. 72 * - Since DRD_(thread_compute_minimum_vc)() does not take the vector 73 * clocks into account that are involved in thread creation but 74 * for which the corresponding thread has not yet been created, by 75 * undefining the macro below it becomes possible that segments get 76 * discarded that should not yet be discarded. Or: some data races 77 * are not detected. 78 */ 79 #define WAIT_UNTIL_CREATED_THREAD_STARTED 80 #define ALLOCATE_THREAD_ARGS_ON_THE_STACK 81 82 /** 83 * Macro for generating a Valgrind interception function. 84 * @param[in] ret_ty Return type of the function to be generated. 85 * @param[in] zf Z-encoded name of the interception function. 86 * @param[in] implf Name of the function that implements the intercept. 87 * @param[in] arg_decl Argument declaration list enclosed in parentheses. 88 * @param[in] argl Argument list enclosed in parentheses. 89 */ 90 #define PTH_FUNC(ret_ty, zf, implf, argl_decl, argl) \ 91 ret_ty VG_WRAP_FUNCTION_ZZ(VG_Z_LIBPTHREAD_SONAME,zf) argl_decl; \ 92 ret_ty VG_WRAP_FUNCTION_ZZ(VG_Z_LIBPTHREAD_SONAME,zf) argl_decl \ 93 { return implf argl; } 94 95 /** 96 * Macro for generating three Valgrind interception functions: one with the 97 * Z-encoded name zf, one with ZAZa ("@*") appended to the name zf and one 98 * with ZDZa ("$*") appended to the name zf. The second generated interception 99 * function will intercept versioned symbols on Linux, and the third will 100 * intercept versioned symbols on Darwin. 101 */ 102 #define PTH_FUNCS(ret_ty, zf, implf, argl_decl, argl) \ 103 PTH_FUNC(ret_ty, zf, implf, argl_decl, argl); \ 104 PTH_FUNC(ret_ty, zf ## ZAZa, implf, argl_decl, argl); \ 105 PTH_FUNC(ret_ty, zf ## ZDZa, implf, argl_decl, argl); 106 107 /* 108 * Not inlining one of the intercept functions will cause the regression 109 * tests to fail because this would cause an additional stackfram to appear 110 * in the output. The __always_inline macro guarantees that inlining will 111 * happen, even when compiling with optimization disabled. 112 */ 113 #undef __always_inline /* since already defined in <cdefs.h> */ 114 #if __GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR__ >= 2 115 #define __always_inline __inline__ __attribute__((always_inline)) 116 #else 117 #define __always_inline __inline__ 118 #endif 119 120 /* Local data structures. */ 121 122 typedef struct 123 { 124 void* (*start)(void*); 125 void* arg; 126 int detachstate; 127 #if defined(WAIT_UNTIL_CREATED_THREAD_STARTED) 128 int wrapper_started; 129 #endif 130 } DrdPosixThreadArgs; 131 132 133 /* Local function declarations. */ 134 135 static void DRD_(init)(void) __attribute__((constructor)); 136 static void DRD_(check_threading_library)(void); 137 static void DRD_(set_main_thread_state)(void); 138 139 140 /* Function definitions. */ 141 142 /** 143 * Shared library initialization function. The function init() is called after 144 * dlopen() has loaded the shared library with DRD client intercepts because 145 * the constructor attribute was specified in the declaration of this function. 146 * Note: do specify the -nostdlib option to gcc when linking this code into a 147 * shared library because doing so would cancel the effect of the constructor 148 * attribute ! Using the gcc option -nodefaultlibs is fine because this last 149 * option preserves the shared library initialization code that calls 150 * constructor and destructor functions. 151 */ 152 static void DRD_(init)(void) 153 { 154 DRD_(check_threading_library)(); 155 DRD_(set_main_thread_state)(); 156 } 157 158 /** 159 * POSIX threads and DRD each have their own mutex type identification. 160 * Convert POSIX threads' mutex type to DRD's mutex type. In the code below 161 * if-statements are used to test the value of 'kind' instead of a switch 162 * statement because some of the PTHREAD_MUTEX_ macro's may have the same 163 * value. 164 */ 165 static MutexT DRD_(pthread_to_drd_mutex_type)(const int kind) 166 { 167 if (kind == PTHREAD_MUTEX_RECURSIVE) 168 return mutex_type_recursive_mutex; 169 else if (kind == PTHREAD_MUTEX_ERRORCHECK) 170 return mutex_type_errorcheck_mutex; 171 else if (kind == PTHREAD_MUTEX_NORMAL) 172 return mutex_type_default_mutex; 173 else if (kind == PTHREAD_MUTEX_DEFAULT) 174 return mutex_type_default_mutex; 175 #if defined(HAVE_PTHREAD_MUTEX_ADAPTIVE_NP) 176 else if (kind == PTHREAD_MUTEX_ADAPTIVE_NP) 177 return mutex_type_default_mutex; 178 #endif 179 else 180 { 181 return mutex_type_invalid_mutex; 182 } 183 } 184 185 #define IS_ALIGNED(p) (((uintptr_t)(p) & (sizeof(*(p)) - 1)) == 0) 186 187 /** 188 * Read the mutex type stored in the client memory used for the mutex 189 * implementation. 190 * 191 * @note This function depends on the implementation of the POSIX threads 192 * library -- the POSIX standard does not define the name of the member in 193 * which the mutex type is stored. 194 * @note The function mutex_type() has been declared inline in order 195 * to avoid that it shows up in call stacks (drd/tests/...exp* files). 196 * @note glibc stores the mutex type in the lowest two bits, and uses the 197 * higher bits for flags like PTHREAD_MUTEXATTR_FLAG_ROBUST and 198 * PTHREAD_MUTEXATTR_FLAG_PSHARED. 199 */ 200 static __always_inline MutexT DRD_(mutex_type)(pthread_mutex_t* mutex) 201 { 202 #if defined(HAVE_PTHREAD_MUTEX_T__M_KIND) 203 /* glibc + LinuxThreads. */ 204 if (IS_ALIGNED(&mutex->__m_kind)) 205 { 206 const int kind = mutex->__m_kind & 3; 207 return DRD_(pthread_to_drd_mutex_type)(kind); 208 } 209 #elif defined(HAVE_PTHREAD_MUTEX_T__DATA__KIND) 210 /* glibc + NPTL. */ 211 if (IS_ALIGNED(&mutex->__data.__kind)) 212 { 213 const int kind = mutex->__data.__kind & 3; 214 return DRD_(pthread_to_drd_mutex_type)(kind); 215 } 216 #else 217 /* 218 * Another POSIX threads implementation. The mutex type won't be printed 219 * when enabling --trace-mutex=yes. 220 */ 221 #endif 222 return mutex_type_unknown; 223 } 224 225 /** 226 * Tell DRD whether 'tid' is a joinable thread or a detached thread. 227 */ 228 static void DRD_(set_joinable)(const pthread_t tid, const int joinable) 229 { 230 int res; 231 assert(joinable == 0 || joinable == 1); 232 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__SET_JOINABLE, 233 tid, joinable, 0, 0, 0); 234 } 235 236 /** Tell DRD that the calling thread is about to enter pthread_create(). */ 237 static __always_inline void DRD_(entering_pthread_create)(void) 238 { 239 int res; 240 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__ENTERING_PTHREAD_CREATE, 241 0, 0, 0, 0, 0); 242 } 243 244 /** Tell DRD that the calling thread has left pthread_create(). */ 245 static __always_inline void DRD_(left_pthread_create)(void) 246 { 247 int res; 248 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__LEFT_PTHREAD_CREATE, 249 0, 0, 0, 0, 0); 250 } 251 252 /** 253 * Entry point for newly created threads. This function is called from the 254 * thread created by pthread_create(). 255 */ 256 static void* DRD_(thread_wrapper)(void* arg) 257 { 258 int res; 259 DrdPosixThreadArgs* arg_ptr; 260 DrdPosixThreadArgs arg_copy; 261 262 arg_ptr = (DrdPosixThreadArgs*)arg; 263 arg_copy = *arg_ptr; 264 #if defined(WAIT_UNTIL_CREATED_THREAD_STARTED) 265 arg_ptr->wrapper_started = 1; 266 #else 267 #if defined(ALLOCATE_THREAD_ARGS_ON_THE_STACK) 268 #error Defining ALLOCATE_THREAD_ARGS_ON_THE_STACK but not \ 269 WAIT_UNTIL_CREATED_THREAD_STARTED is not supported. 270 #else 271 free(arg_ptr); 272 #endif 273 #endif 274 275 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SET_PTHREADID, 276 pthread_self(), 0, 0, 0, 0); 277 278 DRD_(set_joinable)(pthread_self(), 279 arg_copy.detachstate == PTHREAD_CREATE_JOINABLE); 280 281 return (arg_copy.start)(arg_copy.arg); 282 } 283 284 /** 285 * Return 1 if the LinuxThreads implementation of POSIX Threads has been 286 * detected, and 0 otherwise. 287 * 288 * @see For more information about the confstr() function, see also 289 * http://www.opengroup.org/onlinepubs/009695399/functions/confstr.html 290 */ 291 static int DRD_(detected_linuxthreads)(void) 292 { 293 #if defined(linux) 294 #if defined(_CS_GNU_LIBPTHREAD_VERSION) 295 /* Linux with a recent glibc. */ 296 char buffer[256]; 297 unsigned len; 298 len = confstr(_CS_GNU_LIBPTHREAD_VERSION, buffer, sizeof(buffer)); 299 assert(len <= sizeof(buffer)); 300 return len > 0 && buffer[0] == 'l'; 301 #else 302 /* Linux without _CS_GNU_LIBPTHREAD_VERSION: most likely LinuxThreads. */ 303 return 1; 304 #endif 305 #else 306 /* Another OS than Linux, hence no LinuxThreads. */ 307 return 0; 308 #endif 309 } 310 311 /** 312 * Stop and print an error message in case a non-supported threading 313 * library implementation (LinuxThreads) has been detected. 314 */ 315 static void DRD_(check_threading_library)(void) 316 { 317 if (DRD_(detected_linuxthreads)()) 318 { 319 if (getenv("LD_ASSUME_KERNEL")) 320 { 321 fprintf(stderr, 322 "Detected the LinuxThreads threading library. Sorry, but DRD only supports\n" 323 "the newer NPTL (Native POSIX Threads Library). Please try to rerun DRD\n" 324 "after having unset the environment variable LD_ASSUME_KERNEL. Giving up.\n" 325 ); 326 } 327 else 328 { 329 fprintf(stderr, 330 "Detected the LinuxThreads threading library. Sorry, but DRD only supports\n" 331 "the newer NPTL (Native POSIX Threads Library). Please try to rerun DRD\n" 332 "after having upgraded to a newer version of your Linux distribution.\n" 333 "Giving up.\n" 334 ); 335 } 336 abort(); 337 } 338 } 339 340 /** 341 * The main thread is the only thread not created by pthread_create(). 342 * Update DRD's state information about the main thread. 343 */ 344 static void DRD_(set_main_thread_state)(void) 345 { 346 int res; 347 348 // Make sure that DRD knows about the main thread's POSIX thread ID. 349 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SET_PTHREADID, 350 pthread_self(), 0, 0, 0, 0); 351 } 352 353 /* 354 * Note: as of today there exist three different versions of pthread_create 355 * in Linux: 356 * - pthread_create (at) GLIBC_2.0 357 * - pthread_create@@GLIBC_2.1 358 * - pthread_create@@GLIBC_2.2.5 359 * As an example, in libpthread-2.3.4 both pthread_create (at) GLIBC_2.0 and 360 * pthread_create@@GLIBC_2.1 are defined, while in libpthread-2.9 all three 361 * versions have been implemented. In any glibc version where more than one 362 * pthread_create function has been implemented, older versions call the 363 * newer versions. Or: the pthread_create* wrapper defined below can be 364 * called recursively. Any code in this wrapper should take this in account. 365 * As an example, it is not safe to invoke the DRD_STOP_RECORDING 366 * / DRD_START_RECORDING client requests from the pthread_create wrapper. 367 * See also the implementation of pthread_create (at) GLIBC_2.0 in 368 * glibc-2.9/nptl/pthread_create.c. 369 */ 370 371 static __always_inline 372 int pthread_create_intercept(pthread_t* thread, const pthread_attr_t* attr, 373 void* (*start)(void*), void* arg) 374 { 375 int res; 376 int ret; 377 OrigFn fn; 378 #if defined(ALLOCATE_THREAD_ARGS_ON_THE_STACK) 379 DrdPosixThreadArgs thread_args; 380 #endif 381 DrdPosixThreadArgs* thread_args_p; 382 383 VALGRIND_GET_ORIG_FN(fn); 384 385 #if defined(ALLOCATE_THREAD_ARGS_ON_THE_STACK) 386 thread_args_p = &thread_args; 387 #else 388 thread_args_p = malloc(sizeof(*thread_args_p)); 389 #endif 390 assert(thread_args_p); 391 392 thread_args_p->start = start; 393 thread_args_p->arg = arg; 394 #if defined(WAIT_UNTIL_CREATED_THREAD_STARTED) 395 DRD_IGNORE_VAR(thread_args_p->wrapper_started); 396 thread_args_p->wrapper_started = 0; 397 #endif 398 /* 399 * Find out whether the thread will be started as a joinable thread 400 * or as a detached thread. If no thread attributes have been specified, 401 * this means that the new thread will be started as a joinable thread. 402 */ 403 thread_args_p->detachstate = PTHREAD_CREATE_JOINABLE; 404 if (attr) 405 { 406 if (pthread_attr_getdetachstate(attr, &thread_args_p->detachstate) != 0) 407 { 408 assert(0); 409 } 410 } 411 assert(thread_args_p->detachstate == PTHREAD_CREATE_JOINABLE 412 || thread_args_p->detachstate == PTHREAD_CREATE_DETACHED); 413 414 415 DRD_(entering_pthread_create)(); 416 CALL_FN_W_WWWW(ret, fn, thread, attr, DRD_(thread_wrapper), thread_args_p); 417 DRD_(left_pthread_create)(); 418 419 #if defined(WAIT_UNTIL_CREATED_THREAD_STARTED) 420 if (ret == 0) 421 { 422 /* 423 * Wait until the thread wrapper started. 424 * @todo Find out why some regression tests fail if thread arguments are 425 * passed via dynamically allocated memory and if the loop below is 426 * removed. 427 */ 428 while (! thread_args_p->wrapper_started) 429 { 430 sched_yield(); 431 } 432 } 433 434 #if defined(ALLOCATE_THREAD_ARGS_DYNAMICALLY) 435 free(thread_args_p); 436 #endif 437 438 #endif 439 440 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__DRD_START_NEW_SEGMENT, 441 pthread_self(), 0, 0, 0, 0); 442 443 return ret; 444 } 445 446 PTH_FUNCS(int, pthreadZucreate, pthread_create_intercept, 447 (pthread_t *thread, const pthread_attr_t *attr, 448 void *(*start) (void *), void *arg), 449 (thread, attr, start, arg)); 450 451 static __always_inline 452 int pthread_join_intercept(pthread_t pt_joinee, void **thread_return) 453 { 454 int ret; 455 int res; 456 OrigFn fn; 457 458 VALGRIND_GET_ORIG_FN(fn); 459 CALL_FN_W_WW(ret, fn, pt_joinee, thread_return); 460 if (ret == 0) 461 { 462 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_THREAD_JOIN, 463 pt_joinee, 0, 0, 0, 0); 464 } 465 return ret; 466 } 467 468 PTH_FUNCS(int, pthreadZujoin, pthread_join_intercept, 469 (pthread_t pt_joinee, void **thread_return), 470 (pt_joinee, thread_return)); 471 472 static __always_inline 473 int pthread_detach_intercept(pthread_t pt_thread) 474 { 475 int ret; 476 OrigFn fn; 477 VALGRIND_GET_ORIG_FN(fn); 478 { 479 CALL_FN_W_W(ret, fn, pt_thread); 480 if (ret == 0) 481 { 482 DRD_(set_joinable)(pt_thread, 0); 483 } 484 } 485 return ret; 486 } 487 488 PTH_FUNCS(int, pthreadZudetach, pthread_detach_intercept, 489 (pthread_t thread), (thread)); 490 491 // NOTE: be careful to intercept only pthread_cancel() and not 492 // pthread_cancel_init() on Linux. 493 494 static __always_inline 495 int pthread_cancel_intercept(pthread_t pt_thread) 496 { 497 int res; 498 int ret; 499 OrigFn fn; 500 VALGRIND_GET_ORIG_FN(fn); 501 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_THREAD_CANCEL, 502 pt_thread, 0, 0, 0, 0); 503 CALL_FN_W_W(ret, fn, pt_thread); 504 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_THREAD_CANCEL, 505 pt_thread, ret==0, 0, 0, 0); 506 return ret; 507 } 508 509 PTH_FUNCS(int, pthreadZucancel, pthread_cancel_intercept, 510 (pthread_t thread), (thread)) 511 512 static __always_inline 513 int pthread_once_intercept(pthread_once_t *once_control, 514 void (*init_routine)(void)) 515 { 516 int ret; 517 OrigFn fn; 518 VALGRIND_GET_ORIG_FN(fn); 519 /* 520 * Ignore any data races triggered by the implementation of pthread_once(). 521 * Necessary for Darwin. This is not necessary for Linux but doesn't have 522 * any known adverse effects. 523 */ 524 DRD_IGNORE_VAR(*once_control); 525 CALL_FN_W_WW(ret, fn, once_control, init_routine); 526 DRD_STOP_IGNORING_VAR(*once_control); 527 return ret; 528 } 529 530 PTH_FUNCS(int, pthreadZuonce, pthread_once_intercept, 531 (pthread_once_t *once_control, void (*init_routine)(void)), 532 (once_control, init_routine)); 533 534 static __always_inline 535 int pthread_mutex_init_intercept(pthread_mutex_t *mutex, 536 const pthread_mutexattr_t* attr) 537 { 538 int ret; 539 int res; 540 OrigFn fn; 541 int mt; 542 VALGRIND_GET_ORIG_FN(fn); 543 mt = PTHREAD_MUTEX_DEFAULT; 544 if (attr) 545 pthread_mutexattr_gettype(attr, &mt); 546 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_MUTEX_INIT, 547 mutex, DRD_(pthread_to_drd_mutex_type)(mt), 548 0, 0, 0); 549 CALL_FN_W_WW(ret, fn, mutex, attr); 550 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_INIT, 551 mutex, 0, 0, 0, 0); 552 return ret; 553 } 554 555 PTH_FUNCS(int, pthreadZumutexZuinit, pthread_mutex_init_intercept, 556 (pthread_mutex_t *mutex, const pthread_mutexattr_t* attr), 557 (mutex, attr)); 558 559 static __always_inline 560 int pthread_mutex_destroy_intercept(pthread_mutex_t* mutex) 561 { 562 int ret; 563 int res; 564 OrigFn fn; 565 VALGRIND_GET_ORIG_FN(fn); 566 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_MUTEX_DESTROY, 567 mutex, 0, 0, 0, 0); 568 CALL_FN_W_W(ret, fn, mutex); 569 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_DESTROY, 570 mutex, DRD_(mutex_type)(mutex), 0, 0, 0); 571 return ret; 572 } 573 574 PTH_FUNCS(int, pthreadZumutexZudestroy, pthread_mutex_destroy_intercept, 575 (pthread_mutex_t *mutex), (mutex)); 576 577 static __always_inline 578 int pthread_mutex_lock_intercept(pthread_mutex_t* mutex) 579 { 580 int ret; 581 int res; 582 OrigFn fn; 583 VALGRIND_GET_ORIG_FN(fn); 584 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_MUTEX_LOCK, 585 mutex, DRD_(mutex_type)(mutex), 0, 0, 0); 586 CALL_FN_W_W(ret, fn, mutex); 587 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__POST_MUTEX_LOCK, 588 mutex, ret == 0, 0, 0, 0); 589 return ret; 590 } 591 592 PTH_FUNCS(int, pthreadZumutexZulock, pthread_mutex_lock_intercept, 593 (pthread_mutex_t *mutex), (mutex)); 594 595 static __always_inline 596 int pthread_mutex_trylock_intercept(pthread_mutex_t* mutex) 597 { 598 int ret; 599 int res; 600 OrigFn fn; 601 VALGRIND_GET_ORIG_FN(fn); 602 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_MUTEX_LOCK, 603 mutex, DRD_(mutex_type)(mutex), 1, 0, 0); 604 CALL_FN_W_W(ret, fn, mutex); 605 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_LOCK, 606 mutex, ret == 0, 0, 0, 0); 607 return ret; 608 } 609 610 PTH_FUNCS(int, pthreadZumutexZutrylock, pthread_mutex_trylock_intercept, 611 (pthread_mutex_t *mutex), (mutex)); 612 613 static __always_inline 614 int pthread_mutex_timedlock_intercept(pthread_mutex_t *mutex, 615 const struct timespec *abs_timeout) 616 { 617 int ret; 618 int res; 619 OrigFn fn; 620 VALGRIND_GET_ORIG_FN(fn); 621 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_MUTEX_LOCK, 622 mutex, DRD_(mutex_type)(mutex), 0, 0, 0); 623 CALL_FN_W_WW(ret, fn, mutex, abs_timeout); 624 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_LOCK, 625 mutex, ret == 0, 0, 0, 0); 626 return ret; 627 } 628 629 PTH_FUNCS(int, pthreadZumutexZutimedlock, pthread_mutex_timedlock_intercept, 630 (pthread_mutex_t *mutex, const struct timespec *abs_timeout), 631 (mutex, abs_timeout)); 632 633 static __always_inline 634 int pthread_mutex_unlock_intercept(pthread_mutex_t *mutex) 635 { 636 int ret; 637 int res; 638 OrigFn fn; 639 VALGRIND_GET_ORIG_FN(fn); 640 VALGRIND_DO_CLIENT_REQUEST(res, -1, 641 VG_USERREQ__PRE_MUTEX_UNLOCK, 642 mutex, DRD_(mutex_type)(mutex), 0, 0, 0); 643 CALL_FN_W_W(ret, fn, mutex); 644 VALGRIND_DO_CLIENT_REQUEST(res, -1, 645 VG_USERREQ__POST_MUTEX_UNLOCK, 646 mutex, 0, 0, 0, 0); 647 return ret; 648 } 649 650 PTH_FUNCS(int, pthreadZumutexZuunlock, pthread_mutex_unlock_intercept, 651 (pthread_mutex_t *mutex), (mutex)); 652 653 static __always_inline 654 int pthread_cond_init_intercept(pthread_cond_t* cond, 655 const pthread_condattr_t* attr) 656 { 657 int ret; 658 int res; 659 OrigFn fn; 660 VALGRIND_GET_ORIG_FN(fn); 661 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_COND_INIT, 662 cond, 0, 0, 0, 0); 663 CALL_FN_W_WW(ret, fn, cond, attr); 664 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_COND_INIT, 665 cond, 0, 0, 0, 0); 666 return ret; 667 } 668 669 PTH_FUNCS(int, pthreadZucondZuinit, pthread_cond_init_intercept, 670 (pthread_cond_t* cond, const pthread_condattr_t* attr), 671 (cond, attr)); 672 673 static __always_inline 674 int pthread_cond_destroy_intercept(pthread_cond_t* cond) 675 { 676 int ret; 677 int res; 678 OrigFn fn; 679 VALGRIND_GET_ORIG_FN(fn); 680 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_COND_DESTROY, 681 cond, 0, 0, 0, 0); 682 CALL_FN_W_W(ret, fn, cond); 683 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_COND_DESTROY, 684 cond, 0, 0, 0, 0); 685 return ret; 686 } 687 688 PTH_FUNCS(int, pthreadZucondZudestroy, pthread_cond_destroy_intercept, 689 (pthread_cond_t* cond), (cond)); 690 691 static __always_inline 692 int pthread_cond_wait_intercept(pthread_cond_t *cond, pthread_mutex_t *mutex) 693 { 694 int ret; 695 int res; 696 OrigFn fn; 697 VALGRIND_GET_ORIG_FN(fn); 698 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_COND_WAIT, 699 cond, mutex, DRD_(mutex_type)(mutex), 0, 0); 700 CALL_FN_W_WW(ret, fn, cond, mutex); 701 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_COND_WAIT, 702 cond, mutex, 1, 0, 0); 703 return ret; 704 } 705 706 PTH_FUNCS(int, pthreadZucondZuwait, pthread_cond_wait_intercept, 707 (pthread_cond_t *cond, pthread_mutex_t *mutex), 708 (cond, mutex)); 709 710 static __always_inline 711 int pthread_cond_timedwait_intercept(pthread_cond_t *cond, 712 pthread_mutex_t *mutex, 713 const struct timespec* abstime) 714 { 715 int ret; 716 int res; 717 OrigFn fn; 718 VALGRIND_GET_ORIG_FN(fn); 719 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_COND_WAIT, 720 cond, mutex, DRD_(mutex_type)(mutex), 0, 0); 721 CALL_FN_W_WWW(ret, fn, cond, mutex, abstime); 722 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_COND_WAIT, 723 cond, mutex, 1, 0, 0); 724 return ret; 725 } 726 727 PTH_FUNCS(int, pthreadZucondZutimedwait, pthread_cond_timedwait_intercept, 728 (pthread_cond_t *cond, pthread_mutex_t *mutex, 729 const struct timespec* abstime), 730 (cond, mutex, abstime)); 731 732 // NOTE: be careful to intercept only pthread_cond_signal() and not Darwin's 733 // pthread_cond_signal_thread_np(). The former accepts one argument; the latter 734 // two. Intercepting all pthread_cond_signal* functions will cause only one 735 // argument to be passed to pthread_cond_signal_np() and hence will cause this 736 // last function to crash. 737 738 static __always_inline 739 int pthread_cond_signal_intercept(pthread_cond_t* cond) 740 { 741 int ret; 742 int res; 743 OrigFn fn; 744 VALGRIND_GET_ORIG_FN(fn); 745 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_COND_SIGNAL, 746 cond, 0, 0, 0, 0); 747 CALL_FN_W_W(ret, fn, cond); 748 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_COND_SIGNAL, 749 cond, 0, 0, 0, 0); 750 return ret; 751 } 752 753 PTH_FUNCS(int, pthreadZucondZusignal, pthread_cond_signal_intercept, 754 (pthread_cond_t* cond), (cond)); 755 756 static __always_inline 757 int pthread_cond_broadcast_intercept(pthread_cond_t* cond) 758 { 759 int ret; 760 int res; 761 OrigFn fn; 762 VALGRIND_GET_ORIG_FN(fn); 763 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_COND_BROADCAST, 764 cond, 0, 0, 0, 0); 765 CALL_FN_W_W(ret, fn, cond); 766 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_COND_BROADCAST, 767 cond, 0, 0, 0, 0); 768 return ret; 769 } 770 771 PTH_FUNCS(int, pthreadZucondZubroadcast, pthread_cond_broadcast_intercept, 772 (pthread_cond_t* cond), (cond)); 773 774 #if defined(HAVE_PTHREAD_SPIN_LOCK) 775 static __always_inline 776 int pthread_spin_init_intercept(pthread_spinlock_t *spinlock, int pshared) 777 { 778 int ret; 779 int res; 780 OrigFn fn; 781 VALGRIND_GET_ORIG_FN(fn); 782 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SPIN_INIT_OR_UNLOCK, 783 spinlock, 0, 0, 0, 0); 784 CALL_FN_W_WW(ret, fn, spinlock, pshared); 785 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SPIN_INIT_OR_UNLOCK, 786 spinlock, 0, 0, 0, 0); 787 return ret; 788 } 789 790 PTH_FUNCS(int, pthreadZuspinZuinit, pthread_spin_init_intercept, 791 (pthread_spinlock_t *spinlock, int pshared), (spinlock, pshared)); 792 793 static __always_inline 794 int pthread_spin_destroy_intercept(pthread_spinlock_t *spinlock) 795 { 796 int ret; 797 int res; 798 OrigFn fn; 799 VALGRIND_GET_ORIG_FN(fn); 800 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_MUTEX_DESTROY, 801 spinlock, 0, 0, 0, 0); 802 CALL_FN_W_W(ret, fn, spinlock); 803 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_DESTROY, 804 spinlock, mutex_type_spinlock, 0, 0, 0); 805 return ret; 806 } 807 808 PTH_FUNCS(int, pthreadZuspinZudestroy, pthread_spin_destroy_intercept, 809 (pthread_spinlock_t *spinlock), (spinlock)); 810 811 static __always_inline 812 int pthread_spin_lock_intercept(pthread_spinlock_t *spinlock) 813 { 814 int ret; 815 int res; 816 OrigFn fn; 817 VALGRIND_GET_ORIG_FN(fn); 818 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_MUTEX_LOCK, 819 spinlock, mutex_type_spinlock, 0, 0, 0); 820 CALL_FN_W_W(ret, fn, spinlock); 821 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_LOCK, 822 spinlock, ret == 0, 0, 0, 0); 823 return ret; 824 } 825 826 PTH_FUNCS(int, pthreadZuspinZulock, pthread_spin_lock_intercept, 827 (pthread_spinlock_t *spinlock), (spinlock)); 828 829 static __always_inline 830 int pthread_spin_trylock_intercept(pthread_spinlock_t *spinlock) 831 { 832 int ret; 833 int res; 834 OrigFn fn; 835 VALGRIND_GET_ORIG_FN(fn); 836 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_MUTEX_LOCK, 837 spinlock, mutex_type_spinlock, 0, 0, 0); 838 CALL_FN_W_W(ret, fn, spinlock); 839 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_LOCK, 840 spinlock, ret == 0, 0, 0, 0); 841 return ret; 842 } 843 844 PTH_FUNCS(int, pthreadZuspinZutrylock, pthread_spin_trylock_intercept, 845 (pthread_spinlock_t *spinlock), (spinlock)); 846 847 static __always_inline 848 int pthread_spin_unlock_intercept(pthread_spinlock_t *spinlock) 849 { 850 int ret; 851 int res; 852 OrigFn fn; 853 VALGRIND_GET_ORIG_FN(fn); 854 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SPIN_INIT_OR_UNLOCK, 855 spinlock, mutex_type_spinlock, 0, 0, 0); 856 CALL_FN_W_W(ret, fn, spinlock); 857 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SPIN_INIT_OR_UNLOCK, 858 spinlock, 0, 0, 0, 0); 859 return ret; 860 } 861 862 PTH_FUNCS(int, pthreadZuspinZuunlock, pthread_spin_unlock_intercept, 863 (pthread_spinlock_t *spinlock), (spinlock)); 864 #endif // HAVE_PTHREAD_SPIN_LOCK 865 866 867 #if defined(HAVE_PTHREAD_BARRIER_INIT) 868 static __always_inline 869 int pthread_barrier_init_intercept(pthread_barrier_t* barrier, 870 const pthread_barrierattr_t* attr, 871 unsigned count) 872 { 873 int ret; 874 int res; 875 OrigFn fn; 876 VALGRIND_GET_ORIG_FN(fn); 877 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_BARRIER_INIT, 878 barrier, pthread_barrier, count, 0, 0); 879 CALL_FN_W_WWW(ret, fn, barrier, attr, count); 880 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_BARRIER_INIT, 881 barrier, pthread_barrier, 0, 0, 0); 882 return ret; 883 } 884 885 PTH_FUNCS(int, pthreadZubarrierZuinit, pthread_barrier_init_intercept, 886 (pthread_barrier_t* barrier, const pthread_barrierattr_t* attr, 887 unsigned count), (barrier, attr, count)); 888 889 static __always_inline 890 int pthread_barrier_destroy_intercept(pthread_barrier_t* barrier) 891 { 892 int ret; 893 int res; 894 OrigFn fn; 895 VALGRIND_GET_ORIG_FN(fn); 896 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_BARRIER_DESTROY, 897 barrier, pthread_barrier, 0, 0, 0); 898 CALL_FN_W_W(ret, fn, barrier); 899 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_BARRIER_DESTROY, 900 barrier, pthread_barrier, 0, 0, 0); 901 return ret; 902 } 903 904 PTH_FUNCS(int, pthreadZubarrierZudestroy, pthread_barrier_destroy_intercept, 905 (pthread_barrier_t* barrier), (barrier)); 906 907 static __always_inline 908 int pthread_barrier_wait_intercept(pthread_barrier_t* barrier) 909 { 910 int ret; 911 int res; 912 OrigFn fn; 913 VALGRIND_GET_ORIG_FN(fn); 914 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_BARRIER_WAIT, 915 barrier, pthread_barrier, 0, 0, 0); 916 CALL_FN_W_W(ret, fn, barrier); 917 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_BARRIER_WAIT, 918 barrier, pthread_barrier, 919 ret == 0 || ret == PTHREAD_BARRIER_SERIAL_THREAD, 920 ret == PTHREAD_BARRIER_SERIAL_THREAD, 0); 921 return ret; 922 } 923 924 PTH_FUNCS(int, pthreadZubarrierZuwait, pthread_barrier_wait_intercept, 925 (pthread_barrier_t* barrier), (barrier)); 926 #endif // HAVE_PTHREAD_BARRIER_INIT 927 928 929 static __always_inline 930 int sem_init_intercept(sem_t *sem, int pshared, unsigned int value) 931 { 932 int ret; 933 int res; 934 OrigFn fn; 935 VALGRIND_GET_ORIG_FN(fn); 936 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_INIT, 937 sem, pshared, value, 0, 0); 938 CALL_FN_W_WWW(ret, fn, sem, pshared, value); 939 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_INIT, 940 sem, 0, 0, 0, 0); 941 return ret; 942 } 943 944 PTH_FUNCS(int, semZuinit, sem_init_intercept, 945 (sem_t *sem, int pshared, unsigned int value), (sem, pshared, value)); 946 947 static __always_inline 948 int sem_destroy_intercept(sem_t *sem) 949 { 950 int ret; 951 int res; 952 OrigFn fn; 953 VALGRIND_GET_ORIG_FN(fn); 954 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_DESTROY, 955 sem, 0, 0, 0, 0); 956 CALL_FN_W_W(ret, fn, sem); 957 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_DESTROY, 958 sem, 0, 0, 0, 0); 959 return ret; 960 } 961 962 PTH_FUNCS(int, semZudestroy, sem_destroy_intercept, (sem_t *sem), (sem)); 963 964 static __always_inline 965 sem_t* sem_open_intercept(const char *name, int oflag, mode_t mode, 966 unsigned int value) 967 { 968 sem_t *ret; 969 int res; 970 OrigFn fn; 971 VALGRIND_GET_ORIG_FN(fn); 972 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_OPEN, 973 name, oflag, mode, value, 0); 974 CALL_FN_W_WWWW(ret, fn, name, oflag, mode, value); 975 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_OPEN, 976 ret != SEM_FAILED ? ret : 0, 977 name, oflag, mode, value); 978 return ret; 979 } 980 981 PTH_FUNCS(sem_t *, semZuopen, sem_open_intercept, 982 (const char *name, int oflag, mode_t mode, unsigned int value), 983 (name, oflag, mode, value)); 984 985 static __always_inline int sem_close_intercept(sem_t *sem) 986 { 987 int ret; 988 int res; 989 OrigFn fn; 990 VALGRIND_GET_ORIG_FN(fn); 991 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_CLOSE, 992 sem, 0, 0, 0, 0); 993 CALL_FN_W_W(ret, fn, sem); 994 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_CLOSE, 995 sem, 0, 0, 0, 0); 996 return ret; 997 } 998 999 PTH_FUNCS(int, semZuclose, sem_close_intercept, (sem_t *sem), (sem)); 1000 1001 static __always_inline int sem_wait_intercept(sem_t *sem) 1002 { 1003 int ret; 1004 int res; 1005 OrigFn fn; 1006 VALGRIND_GET_ORIG_FN(fn); 1007 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_WAIT, 1008 sem, 0, 0, 0, 0); 1009 CALL_FN_W_W(ret, fn, sem); 1010 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT, 1011 sem, ret == 0, 0, 0, 0); 1012 return ret; 1013 } 1014 1015 PTH_FUNCS(int, semZuwait, sem_wait_intercept, (sem_t *sem), (sem)); 1016 1017 static __always_inline int sem_trywait_intercept(sem_t *sem) 1018 { 1019 int ret; 1020 int res; 1021 OrigFn fn; 1022 VALGRIND_GET_ORIG_FN(fn); 1023 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_WAIT, 1024 sem, 0, 0, 0, 0); 1025 CALL_FN_W_W(ret, fn, sem); 1026 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT, 1027 sem, ret == 0, 0, 0, 0); 1028 return ret; 1029 } 1030 1031 PTH_FUNCS(int, semZutrywait, sem_trywait_intercept, (sem_t *sem), (sem)); 1032 1033 static __always_inline 1034 int sem_timedwait_intercept(sem_t *sem, const struct timespec *abs_timeout) 1035 { 1036 int ret; 1037 int res; 1038 OrigFn fn; 1039 VALGRIND_GET_ORIG_FN(fn); 1040 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_WAIT, 1041 sem, 0, 0, 0, 0); 1042 CALL_FN_W_WW(ret, fn, sem, abs_timeout); 1043 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT, 1044 sem, ret == 0, 0, 0, 0); 1045 return ret; 1046 } 1047 1048 PTH_FUNCS(int, semZutimedwait, sem_timedwait_intercept, 1049 (sem_t *sem, const struct timespec *abs_timeout), 1050 (sem, abs_timeout)); 1051 1052 static __always_inline int sem_post_intercept(sem_t *sem) 1053 { 1054 int ret; 1055 int res; 1056 OrigFn fn; 1057 VALGRIND_GET_ORIG_FN(fn); 1058 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_POST, 1059 sem, 0, 0, 0, 0); 1060 CALL_FN_W_W(ret, fn, sem); 1061 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_POST, 1062 sem, ret == 0, 0, 0, 0); 1063 return ret; 1064 } 1065 1066 PTH_FUNCS(int, semZupost, sem_post_intercept, (sem_t *sem), (sem)); 1067 1068 static __always_inline 1069 int pthread_rwlock_init_intercept(pthread_rwlock_t* rwlock, 1070 const pthread_rwlockattr_t* attr) 1071 { 1072 int ret; 1073 int res; 1074 OrigFn fn; 1075 VALGRIND_GET_ORIG_FN(fn); 1076 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_INIT, 1077 rwlock, 0, 0, 0, 0); 1078 CALL_FN_W_WW(ret, fn, rwlock, attr); 1079 return ret; 1080 } 1081 1082 PTH_FUNCS(int, 1083 pthreadZurwlockZuinit, pthread_rwlock_init_intercept, 1084 (pthread_rwlock_t* rwlock, const pthread_rwlockattr_t* attr), 1085 (rwlock, attr)); 1086 1087 static __always_inline 1088 int pthread_rwlock_destroy_intercept(pthread_rwlock_t* rwlock) 1089 { 1090 int ret; 1091 int res; 1092 OrigFn fn; 1093 VALGRIND_GET_ORIG_FN(fn); 1094 CALL_FN_W_W(ret, fn, rwlock); 1095 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_DESTROY, 1096 rwlock, 0, 0, 0, 0); 1097 return ret; 1098 } 1099 1100 PTH_FUNCS(int, 1101 pthreadZurwlockZudestroy, pthread_rwlock_destroy_intercept, 1102 (pthread_rwlock_t* rwlock), (rwlock)); 1103 1104 static __always_inline 1105 int pthread_rwlock_rdlock_intercept(pthread_rwlock_t* rwlock) 1106 { 1107 int ret; 1108 int res; 1109 OrigFn fn; 1110 VALGRIND_GET_ORIG_FN(fn); 1111 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_RDLOCK, 1112 rwlock, 0, 0, 0, 0); 1113 CALL_FN_W_W(ret, fn, rwlock); 1114 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_RDLOCK, 1115 rwlock, ret == 0, 0, 0, 0); 1116 return ret; 1117 } 1118 1119 PTH_FUNCS(int, 1120 pthreadZurwlockZurdlock, pthread_rwlock_rdlock_intercept, 1121 (pthread_rwlock_t* rwlock), (rwlock)); 1122 1123 static __always_inline 1124 int pthread_rwlock_wrlock_intercept(pthread_rwlock_t* rwlock) 1125 { 1126 int ret; 1127 int res; 1128 OrigFn fn; 1129 VALGRIND_GET_ORIG_FN(fn); 1130 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_WRLOCK, 1131 rwlock, 0, 0, 0, 0); 1132 CALL_FN_W_W(ret, fn, rwlock); 1133 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_WRLOCK, 1134 rwlock, ret == 0, 0, 0, 0); 1135 return ret; 1136 } 1137 1138 PTH_FUNCS(int, 1139 pthreadZurwlockZuwrlock, pthread_rwlock_wrlock_intercept, 1140 (pthread_rwlock_t* rwlock), (rwlock)); 1141 1142 static __always_inline 1143 int pthread_rwlock_timedrdlock_intercept(pthread_rwlock_t* rwlock) 1144 { 1145 int ret; 1146 int res; 1147 OrigFn fn; 1148 VALGRIND_GET_ORIG_FN(fn); 1149 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_RDLOCK, 1150 rwlock, 0, 0, 0, 0); 1151 CALL_FN_W_W(ret, fn, rwlock); 1152 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_RDLOCK, 1153 rwlock, ret == 0, 0, 0, 0); 1154 return ret; 1155 } 1156 1157 PTH_FUNCS(int, 1158 pthreadZurwlockZutimedrdlock, pthread_rwlock_timedrdlock_intercept, 1159 (pthread_rwlock_t* rwlock), (rwlock)); 1160 1161 static __always_inline 1162 int pthread_rwlock_timedwrlock_intercept(pthread_rwlock_t* rwlock) 1163 { 1164 int ret; 1165 int res; 1166 OrigFn fn; 1167 VALGRIND_GET_ORIG_FN(fn); 1168 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_WRLOCK, 1169 rwlock, 0, 0, 0, 0); 1170 CALL_FN_W_W(ret, fn, rwlock); 1171 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_WRLOCK, 1172 rwlock, ret == 0, 0, 0, 0); 1173 return ret; 1174 } 1175 1176 PTH_FUNCS(int, 1177 pthreadZurwlockZutimedwrlock, pthread_rwlock_timedwrlock_intercept, 1178 (pthread_rwlock_t* rwlock), (rwlock)); 1179 1180 static __always_inline 1181 int pthread_rwlock_tryrdlock_intercept(pthread_rwlock_t* rwlock) 1182 { 1183 int ret; 1184 int res; 1185 OrigFn fn; 1186 VALGRIND_GET_ORIG_FN(fn); 1187 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_RDLOCK, 1188 rwlock, 0, 0, 0, 0); 1189 CALL_FN_W_W(ret, fn, rwlock); 1190 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_RDLOCK, 1191 rwlock, ret == 0, 0, 0, 0); 1192 return ret; 1193 } 1194 1195 PTH_FUNCS(int, 1196 pthreadZurwlockZutryrdlock, pthread_rwlock_tryrdlock_intercept, 1197 (pthread_rwlock_t* rwlock), (rwlock)); 1198 1199 static __always_inline 1200 int pthread_rwlock_trywrlock_intercept(pthread_rwlock_t* rwlock) 1201 { 1202 int ret; 1203 int res; 1204 OrigFn fn; 1205 VALGRIND_GET_ORIG_FN(fn); 1206 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_WRLOCK, 1207 rwlock, 0, 0, 0, 0); 1208 CALL_FN_W_W(ret, fn, rwlock); 1209 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_WRLOCK, 1210 rwlock, ret == 0, 0, 0, 0); 1211 return ret; 1212 } 1213 1214 PTH_FUNCS(int, 1215 pthreadZurwlockZutrywrlock, pthread_rwlock_trywrlock_intercept, 1216 (pthread_rwlock_t* rwlock), (rwlock)); 1217 1218 static __always_inline 1219 int pthread_rwlock_unlock_intercept(pthread_rwlock_t* rwlock) 1220 { 1221 int ret; 1222 int res; 1223 OrigFn fn; 1224 VALGRIND_GET_ORIG_FN(fn); 1225 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_UNLOCK, 1226 rwlock, 0, 0, 0, 0); 1227 CALL_FN_W_W(ret, fn, rwlock); 1228 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_UNLOCK, 1229 rwlock, ret == 0, 0, 0, 0); 1230 return ret; 1231 } 1232 1233 PTH_FUNCS(int, 1234 pthreadZurwlockZuunlock, pthread_rwlock_unlock_intercept, 1235 (pthread_rwlock_t* rwlock), (rwlock)); 1236