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