drd_pthread_intercepts.c revision 5f5ef2ae9e7c2ce5ebc36c1e2fc98e5f81650be3
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-2009 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#define PTH_FUNC(ret_ty, f, args...) \ 82 ret_ty VG_WRAP_FUNCTION_ZZ(VG_Z_LIBPTHREAD_SONAME,f)(args); \ 83 ret_ty VG_WRAP_FUNCTION_ZZ(VG_Z_LIBPTHREAD_SONAME,f)(args) 84 85 86/* Local data structures. */ 87 88typedef struct 89{ 90 void* (*start)(void*); 91 void* arg; 92 int detachstate; 93#if defined(WAIT_UNTIL_CREATED_THREAD_STARTED) 94 int wrapper_started; 95#endif 96} DrdPosixThreadArgs; 97 98 99/* Local function declarations. */ 100 101static void DRD_(init)(void) __attribute__((constructor)); 102static void DRD_(check_threading_library)(void); 103static void DRD_(set_main_thread_state)(void); 104 105 106/* Function definitions. */ 107 108/** 109 * Shared library initialization function. The function init() is called after 110 * dlopen() has loaded the shared library with DRD client intercepts because 111 * the constructor attribute was specified in the declaration of this function. 112 * Note: do specify the -nostdlib option to gcc when linking this code into a 113 * shared library because doing so would cancel the effect of the constructor 114 * attribute ! Using the gcc option -nodefaultlibs is fine because this last 115 * option preserves the shared library initialization code that calls 116 * constructor and destructor functions. 117 */ 118static void DRD_(init)(void) 119{ 120 DRD_(check_threading_library)(); 121 DRD_(set_main_thread_state)(); 122} 123 124/** 125 * POSIX threads and DRD each have their own mutex type identification. 126 * Convert POSIX threads' mutex type to DRD's mutex type. In the code below 127 * if-statements are used to test the value of 'kind' instead of a switch 128 * statement because some of the PTHREAD_MUTEX_ macro's may have the same 129 * value. 130 */ 131static MutexT DRD_(pthread_to_drd_mutex_type)(const int kind) 132{ 133 if (kind == PTHREAD_MUTEX_RECURSIVE) 134 return mutex_type_recursive_mutex; 135 else if (kind == PTHREAD_MUTEX_ERRORCHECK) 136 return mutex_type_errorcheck_mutex; 137 else if (kind == PTHREAD_MUTEX_NORMAL) 138 return mutex_type_default_mutex; 139 else if (kind == PTHREAD_MUTEX_DEFAULT) 140 return mutex_type_default_mutex; 141#if defined(HAVE_PTHREAD_MUTEX_ADAPTIVE_NP) 142 else if (kind == PTHREAD_MUTEX_ADAPTIVE_NP) 143 return mutex_type_default_mutex; 144#endif 145 else 146 { 147 return mutex_type_invalid_mutex; 148 } 149} 150 151/** 152 * Read the mutex type stored in the client memory used for the mutex 153 * implementation. 154 * 155 * @note This function depends on the implementation of the POSIX threads 156 * library -- the POSIX standard does not define the name of the member in 157 * which the mutex type is stored. 158 * @note The function mutex_type() has been declared inline in order 159 * to avoid that it shows up in call stacks (drd/tests/...exp* files). 160 * @note glibc stores the mutex type in the lowest two bits, and uses the 161 * higher bits for flags like PTHREAD_MUTEXATTR_FLAG_ROBUST and 162 * PTHREAD_MUTEXATTR_FLAG_PSHARED. 163 */ 164static __inline__ MutexT DRD_(mutex_type)(pthread_mutex_t* mutex) 165{ 166#if defined(HAVE_PTHREAD_MUTEX_T__M_KIND) 167 /* glibc + LinuxThreads. */ 168 const int kind = mutex->__m_kind & 3; 169#elif defined(HAVE_PTHREAD_MUTEX_T__DATA__KIND) 170 /* glibc + NPTL. */ 171 const int kind = mutex->__data.__kind & 3; 172#else 173 /* Another POSIX threads implementation. Regression tests will fail. */ 174 const int kind = PTHREAD_MUTEX_DEFAULT; 175 fprintf(stderr, 176 "Did not recognize your POSIX threads implementation. Giving up.\n"); 177 assert(0); 178#endif 179 return DRD_(pthread_to_drd_mutex_type)(kind); 180} 181 182/** 183 * Tell DRD whether 'tid' is a joinable thread or a detached thread. 184 */ 185static void DRD_(set_joinable)(const pthread_t tid, const int joinable) 186{ 187 int res; 188 assert(joinable == 0 || joinable == 1); 189 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__SET_JOINABLE, 190 tid, joinable, 0, 0, 0); 191} 192 193/** 194 * The function called from the thread created by pthread_create(). 195 */ 196static void* DRD_(thread_wrapper)(void* arg) 197{ 198 int res; 199 DrdPosixThreadArgs* arg_ptr; 200 DrdPosixThreadArgs arg_copy; 201 202 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__DRD_SUPPRESS_CURRENT_STACK, 203 0, 0, 0, 0, 0); 204 205 arg_ptr = (DrdPosixThreadArgs*)arg; 206 arg_copy = *arg_ptr; 207#if defined(WAIT_UNTIL_CREATED_THREAD_STARTED) 208 arg_ptr->wrapper_started = 1; 209#else 210#if defined(ALLOCATE_THREAD_ARGS_ON_THE_STACK) 211#error Defining ALLOCATE_THREAD_ARGS_ON_THE_STACK but not \ 212 WAIT_UNTIL_CREATED_THREAD_STARTED is not supported. 213#else 214 free(arg_ptr); 215#endif 216#endif 217 218 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SET_PTHREADID, 219 pthread_self(), 0, 0, 0, 0); 220 221 DRD_(set_joinable)(pthread_self(), 222 arg_copy.detachstate == PTHREAD_CREATE_JOINABLE); 223 224 return (arg_copy.start)(arg_copy.arg); 225} 226 227/** 228 * Return 1 if the LinuxThreads implementation of POSIX Threads has been 229 * detected, and 0 otherwise. 230 * 231 * @see For more information about the confstr() function, see also 232 * http://www.opengroup.org/onlinepubs/009695399/functions/confstr.html 233 */ 234static int DRD_(detected_linuxthreads)(void) 235{ 236#if defined(linux) 237#if defined(_CS_GNU_LIBPTHREAD_VERSION) 238 /* Linux with a recent glibc. */ 239 char buffer[256]; 240 unsigned len; 241 len = confstr(_CS_GNU_LIBPTHREAD_VERSION, buffer, sizeof(buffer)); 242 assert(len <= sizeof(buffer)); 243 return len > 0 && buffer[0] == 'l'; 244#else 245 /* Linux without _CS_GNU_LIBPTHREAD_VERSION: most likely LinuxThreads. */ 246 return 1; 247#endif 248#else 249 /* Another OS than Linux, hence no LinuxThreads. */ 250 return 0; 251#endif 252} 253 254/** 255 * Stop and print an error message in case a non-supported threading 256 * library implementation (LinuxThreads) has been detected. 257 */ 258static void DRD_(check_threading_library)(void) 259{ 260 if (DRD_(detected_linuxthreads)()) 261 { 262 if (getenv("LD_ASSUME_KERNEL")) 263 { 264 fprintf(stderr, 265"Detected the LinuxThreads threading library. Sorry, but DRD only supports\n" 266"the newer NPTL (Native POSIX Threads Library). Please try to rerun DRD\n" 267"after having unset the environment variable LD_ASSUME_KERNEL. Giving up.\n" 268); 269 } 270 else 271 { 272 fprintf(stderr, 273"Detected the LinuxThreads threading library. Sorry, but DRD only supports\n" 274"the newer NPTL (Native POSIX Threads Library). Please try to rerun DRD\n" 275"after having upgraded to a newer version of your Linux distribution.\n" 276"Giving up.\n" 277); 278 } 279 abort(); 280 } 281} 282 283/** 284 * The main thread is the only thread not created by pthread_create(). 285 * Update DRD's state information about the main thread. 286 */ 287static void DRD_(set_main_thread_state)(void) 288{ 289 int res; 290 291 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__DRD_SUPPRESS_CURRENT_STACK, 292 0, 0, 0, 0, 0); 293 294 // Make sure that DRD knows about the main thread's POSIX thread ID. 295 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SET_PTHREADID, 296 pthread_self(), 0, 0, 0, 0); 297 298} 299 300 301/* 302 * Note: as of today there exist three different versions of pthread_create: 303 * - pthread_create@GLIBC_2.0 304 * - pthread_create@@GLIBC_2.1 305 * - pthread_create@@GLIBC_2.2.5 306 * As an example, in libpthread-2.3.4 both pthread_create@GLIBC_2.0 and 307 * pthread_create@@GLIBC_2.1 are defined, while in libpthread-2.9 all three 308 * versions have been implemented. In any glibc version where more than one 309 * pthread_create function has been implemented, older versions call the 310 * newer versions. Or: the pthread_create* wrapper defined below can be 311 * called recursively. Any code in this wrapper should take this in account. 312 * As an example, it is not safe to invoke the DRD_STOP_RECORDING 313 * / DRD_START_RECORDING client requests from the pthread_create wrapper. 314 * See also the implementation of pthread_create@GLIBC_2.0 in 315 * glibc-2.9/nptl/pthread_create.c. 316 */ 317 318// pthread_create 319PTH_FUNC(int, pthreadZucreateZa, // pthread_create* 320 pthread_t *thread, const pthread_attr_t *attr, 321 void *(*start) (void *), void *arg) 322{ 323 int res; 324 int ret; 325 OrigFn fn; 326#if defined(ALLOCATE_THREAD_ARGS_ON_THE_STACK) 327 DrdPosixThreadArgs thread_args; 328#endif 329 DrdPosixThreadArgs* thread_args_p; 330 331 VALGRIND_GET_ORIG_FN(fn); 332 333#if defined(ALLOCATE_THREAD_ARGS_ON_THE_STACK) 334 thread_args_p = &thread_args; 335#else 336 thread_args_p = malloc(sizeof(*thread_args_p)); 337#endif 338 assert(thread_args_p); 339 340 thread_args_p->start = start; 341 thread_args_p->arg = arg; 342#if defined(WAIT_UNTIL_CREATED_THREAD_STARTED) 343 DRD_IGNORE_VAR(thread_args_p->wrapper_started); 344 thread_args_p->wrapper_started = 0; 345#endif 346 /* 347 * Find out whether the thread will be started as a joinable thread 348 * or as a detached thread. If no thread attributes have been specified, 349 * this means that the new thread will be started as a joinable thread. 350 */ 351 thread_args_p->detachstate = PTHREAD_CREATE_JOINABLE; 352 if (attr) 353 { 354 if (pthread_attr_getdetachstate(attr, &thread_args_p->detachstate) != 0) 355 { 356 assert(0); 357 } 358 } 359 assert(thread_args_p->detachstate == PTHREAD_CREATE_JOINABLE 360 || thread_args_p->detachstate == PTHREAD_CREATE_DETACHED); 361 362 CALL_FN_W_WWWW(ret, fn, thread, attr, DRD_(thread_wrapper), thread_args_p); 363 364#if defined(WAIT_UNTIL_CREATED_THREAD_STARTED) 365 if (ret == 0) 366 { 367 /* 368 * Wait until the thread wrapper started. 369 * @todo Find out why some regression tests fail if thread arguments are 370 * passed via dynamically allocated memory and if the loop below is 371 * removed. 372 */ 373 while (! thread_args_p->wrapper_started) 374 { 375 sched_yield(); 376 } 377 } 378 379#if defined(ALLOCATE_THREAD_ARGS_DYNAMICALLY) 380 free(thread_args_p); 381#endif 382 383#endif 384 385 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__DRD_START_NEW_SEGMENT, 386 pthread_self(), 0, 0, 0, 0); 387 388 return ret; 389} 390 391// pthread_join 392PTH_FUNC(int, pthreadZujoin, // pthread_join 393 pthread_t pt_joinee, void **thread_return) 394{ 395 int ret; 396 int res; 397 OrigFn fn; 398 399 VALGRIND_GET_ORIG_FN(fn); 400 CALL_FN_W_WW(ret, fn, pt_joinee, thread_return); 401 if (ret == 0) 402 { 403 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_THREAD_JOIN, 404 pt_joinee, 0, 0, 0, 0); 405 } 406 return ret; 407} 408 409// pthread_detach 410PTH_FUNC(int, pthreadZudetach, pthread_t pt_thread) 411{ 412 int ret; 413 OrigFn fn; 414 VALGRIND_GET_ORIG_FN(fn); 415 { 416 CALL_FN_W_W(ret, fn, pt_thread); 417 if (ret == 0) 418 { 419 DRD_(set_joinable)(pt_thread, 0); 420 } 421 } 422 return ret; 423} 424 425// pthread_cancel 426PTH_FUNC(int, pthreadZucancel, pthread_t pt_thread) 427{ 428 int res; 429 int ret; 430 OrigFn fn; 431 VALGRIND_GET_ORIG_FN(fn); 432 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_THREAD_CANCEL, 433 pt_thread, 0, 0, 0, 0); 434 CALL_FN_W_W(ret, fn, pt_thread); 435 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_THREAD_CANCEL, 436 pt_thread, ret==0, 0, 0, 0); 437 return ret; 438} 439 440// pthread_mutex_init 441PTH_FUNC(int, pthreadZumutexZuinit, 442 pthread_mutex_t *mutex, 443 const pthread_mutexattr_t* attr) 444{ 445 int ret; 446 int res; 447 OrigFn fn; 448 int mt; 449 VALGRIND_GET_ORIG_FN(fn); 450 mt = PTHREAD_MUTEX_DEFAULT; 451 if (attr) 452 pthread_mutexattr_gettype(attr, &mt); 453 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_MUTEX_INIT, 454 mutex, DRD_(pthread_to_drd_mutex_type)(mt), 455 0, 0, 0); 456 CALL_FN_W_WW(ret, fn, mutex, attr); 457 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_INIT, 458 mutex, 0, 0, 0, 0); 459 return ret; 460} 461 462// pthread_mutex_destroy 463PTH_FUNC(int, pthreadZumutexZudestroy, 464 pthread_mutex_t *mutex) 465{ 466 int ret; 467 int res; 468 OrigFn fn; 469 VALGRIND_GET_ORIG_FN(fn); 470 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_MUTEX_DESTROY, 471 mutex, 0, 0, 0, 0); 472 CALL_FN_W_W(ret, fn, mutex); 473 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_DESTROY, 474 mutex, DRD_(mutex_type)(mutex), 0, 0, 0); 475 return ret; 476} 477 478// pthread_mutex_lock 479PTH_FUNC(int, pthreadZumutexZulock, // pthread_mutex_lock 480 pthread_mutex_t *mutex) 481{ 482 int ret; 483 int res; 484 OrigFn fn; 485 VALGRIND_GET_ORIG_FN(fn); 486 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_MUTEX_LOCK, 487 mutex, DRD_(mutex_type)(mutex), 0, 0, 0); 488 CALL_FN_W_W(ret, fn, mutex); 489 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__POST_MUTEX_LOCK, 490 mutex, ret == 0, 0, 0, 0); 491 return ret; 492} 493 494// pthread_mutex_trylock 495PTH_FUNC(int, pthreadZumutexZutrylock, // pthread_mutex_trylock 496 pthread_mutex_t *mutex) 497{ 498 int ret; 499 int res; 500 OrigFn fn; 501 VALGRIND_GET_ORIG_FN(fn); 502 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_MUTEX_LOCK, 503 mutex, DRD_(mutex_type)(mutex), 1, 0, 0); 504 CALL_FN_W_W(ret, fn, mutex); 505 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_LOCK, 506 mutex, ret == 0, 0, 0, 0); 507 return ret; 508} 509 510// pthread_mutex_timedlock 511PTH_FUNC(int, pthreadZumutexZutimedlock, // pthread_mutex_timedlock 512 pthread_mutex_t *mutex, 513 const struct timespec *abs_timeout) 514{ 515 int ret; 516 int res; 517 OrigFn fn; 518 VALGRIND_GET_ORIG_FN(fn); 519 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_MUTEX_LOCK, 520 mutex, DRD_(mutex_type)(mutex), 0, 0, 0); 521 CALL_FN_W_WW(ret, fn, mutex, abs_timeout); 522 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_LOCK, 523 mutex, ret == 0, 0, 0, 0); 524 return ret; 525} 526 527// pthread_mutex_unlock 528PTH_FUNC(int, pthreadZumutexZuunlock, // pthread_mutex_unlock 529 pthread_mutex_t *mutex) 530{ 531 int ret; 532 int res; 533 OrigFn fn; 534 VALGRIND_GET_ORIG_FN(fn); 535 VALGRIND_DO_CLIENT_REQUEST(res, -1, 536 VG_USERREQ__PRE_MUTEX_UNLOCK, 537 mutex, DRD_(mutex_type)(mutex), 0, 0, 0); 538 CALL_FN_W_W(ret, fn, mutex); 539 VALGRIND_DO_CLIENT_REQUEST(res, -1, 540 VG_USERREQ__POST_MUTEX_UNLOCK, 541 mutex, 0, 0, 0, 0); 542 return ret; 543} 544 545// pthread_cond_init 546PTH_FUNC(int, pthreadZucondZuinitZa, // pthread_cond_init* 547 pthread_cond_t* cond, 548 const pthread_condattr_t* attr) 549{ 550 int ret; 551 int res; 552 OrigFn fn; 553 VALGRIND_GET_ORIG_FN(fn); 554 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_COND_INIT, 555 cond, 0, 0, 0, 0); 556 CALL_FN_W_WW(ret, fn, cond, attr); 557 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_COND_INIT, 558 cond, 0, 0, 0, 0); 559 return ret; 560} 561 562// pthread_cond_destroy 563PTH_FUNC(int, pthreadZucondZudestroyZa, // pthread_cond_destroy* 564 pthread_cond_t* cond) 565{ 566 int ret; 567 int res; 568 OrigFn fn; 569 VALGRIND_GET_ORIG_FN(fn); 570 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_COND_DESTROY, 571 cond, 0, 0, 0, 0); 572 CALL_FN_W_W(ret, fn, cond); 573 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_COND_DESTROY, 574 cond, 0, 0, 0, 0); 575 return ret; 576} 577 578// pthread_cond_wait 579PTH_FUNC(int, pthreadZucondZuwaitZa, // pthread_cond_wait* 580 pthread_cond_t *cond, 581 pthread_mutex_t *mutex) 582{ 583 int ret; 584 int res; 585 OrigFn fn; 586 VALGRIND_GET_ORIG_FN(fn); 587 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_COND_WAIT, 588 cond, mutex, DRD_(mutex_type)(mutex), 0, 0); 589 CALL_FN_W_WW(ret, fn, cond, mutex); 590 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_COND_WAIT, 591 cond, mutex, 1, 0, 0); 592 return ret; 593} 594 595// pthread_cond_timedwait 596PTH_FUNC(int, pthreadZucondZutimedwaitZa, // pthread_cond_timedwait* 597 pthread_cond_t *cond, 598 pthread_mutex_t *mutex, 599 const struct timespec* abstime) 600{ 601 int ret; 602 int res; 603 OrigFn fn; 604 VALGRIND_GET_ORIG_FN(fn); 605 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_COND_WAIT, 606 cond, mutex, DRD_(mutex_type)(mutex), 0, 0); 607 CALL_FN_W_WWW(ret, fn, cond, mutex, abstime); 608 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_COND_WAIT, 609 cond, mutex, 1, 0, 0); 610 return ret; 611} 612 613// pthread_cond_signal 614PTH_FUNC(int, pthreadZucondZusignalZa, // pthread_cond_signal* 615 pthread_cond_t* cond) 616{ 617 int ret; 618 int res; 619 OrigFn fn; 620 VALGRIND_GET_ORIG_FN(fn); 621 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_COND_SIGNAL, 622 cond, 0, 0, 0, 0); 623 CALL_FN_W_W(ret, fn, cond); 624 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_COND_SIGNAL, 625 cond, 0, 0, 0, 0); 626 return ret; 627} 628 629// pthread_cond_broadcast 630PTH_FUNC(int, pthreadZucondZubroadcastZa, // pthread_cond_broadcast* 631 pthread_cond_t* cond) 632{ 633 int ret; 634 int res; 635 OrigFn fn; 636 VALGRIND_GET_ORIG_FN(fn); 637 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_COND_BROADCAST, 638 cond, 0, 0, 0, 0); 639 CALL_FN_W_W(ret, fn, cond); 640 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_COND_BROADCAST, 641 cond, 0, 0, 0, 0); 642 return ret; 643} 644 645 646// pthread_spin_init 647PTH_FUNC(int, pthreadZuspinZuinit, // pthread_spin_init 648 pthread_spinlock_t *spinlock, 649 int pshared) 650{ 651 int ret; 652 int res; 653 OrigFn fn; 654 VALGRIND_GET_ORIG_FN(fn); 655 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SPIN_INIT_OR_UNLOCK, 656 spinlock, 0, 0, 0, 0); 657 CALL_FN_W_WW(ret, fn, spinlock, pshared); 658 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SPIN_INIT_OR_UNLOCK, 659 spinlock, 0, 0, 0, 0); 660 return ret; 661} 662 663// pthread_spin_destroy 664PTH_FUNC(int, pthreadZuspinZudestroy, // pthread_spin_destroy 665 pthread_spinlock_t *spinlock) 666{ 667 int ret; 668 int res; 669 OrigFn fn; 670 VALGRIND_GET_ORIG_FN(fn); 671 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_MUTEX_DESTROY, 672 spinlock, 0, 0, 0, 0); 673 CALL_FN_W_W(ret, fn, spinlock); 674 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_DESTROY, 675 spinlock, mutex_type_spinlock, 0, 0, 0); 676 return ret; 677} 678 679// pthread_spin_lock 680PTH_FUNC(int, pthreadZuspinZulock, // pthread_spin_lock 681 pthread_spinlock_t *spinlock) 682{ 683 int ret; 684 int res; 685 OrigFn fn; 686 VALGRIND_GET_ORIG_FN(fn); 687 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_MUTEX_LOCK, 688 spinlock, mutex_type_spinlock, 0, 0, 0); 689 CALL_FN_W_W(ret, fn, spinlock); 690 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_LOCK, 691 spinlock, ret == 0, 0, 0, 0); 692 return ret; 693} 694 695// pthread_spin_trylock 696PTH_FUNC(int, pthreadZuspinZutrylock, // pthread_spin_trylock 697 pthread_spinlock_t *spinlock) 698{ 699 int ret; 700 int res; 701 OrigFn fn; 702 VALGRIND_GET_ORIG_FN(fn); 703 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__PRE_MUTEX_LOCK, 704 spinlock, mutex_type_spinlock, 0, 0, 0); 705 CALL_FN_W_W(ret, fn, spinlock); 706 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_LOCK, 707 spinlock, ret == 0, 0, 0, 0); 708 return ret; 709} 710 711// pthread_spin_unlock 712PTH_FUNC(int, pthreadZuspinZuunlock, // pthread_spin_unlock 713 pthread_spinlock_t *spinlock) 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_SPIN_INIT_OR_UNLOCK, 720 spinlock, mutex_type_spinlock, 0, 0, 0); 721 CALL_FN_W_W(ret, fn, spinlock); 722 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SPIN_INIT_OR_UNLOCK, 723 spinlock, 0, 0, 0, 0); 724 return ret; 725} 726 727// pthread_barrier_init 728PTH_FUNC(int, pthreadZubarrierZuinit, // pthread_barrier_init 729 pthread_barrier_t* barrier, 730 const pthread_barrierattr_t* attr, 731 unsigned count) 732{ 733 int ret; 734 int res; 735 OrigFn fn; 736 VALGRIND_GET_ORIG_FN(fn); 737 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_BARRIER_INIT, 738 barrier, pthread_barrier, count, 0, 0); 739 CALL_FN_W_WWW(ret, fn, barrier, attr, count); 740 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_BARRIER_INIT, 741 barrier, pthread_barrier, 0, 0, 0); 742 return ret; 743} 744 745// pthread_barrier_destroy 746PTH_FUNC(int, pthreadZubarrierZudestroy, // pthread_barrier_destroy 747 pthread_barrier_t* barrier) 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_BARRIER_DESTROY, 754 barrier, pthread_barrier, 0, 0, 0); 755 CALL_FN_W_W(ret, fn, barrier); 756 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_BARRIER_DESTROY, 757 barrier, pthread_barrier, 0, 0, 0); 758 return ret; 759} 760 761// pthread_barrier_wait 762PTH_FUNC(int, pthreadZubarrierZuwait, // pthread_barrier_wait 763 pthread_barrier_t* barrier) 764{ 765 int ret; 766 int res; 767 OrigFn fn; 768 VALGRIND_GET_ORIG_FN(fn); 769 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_BARRIER_WAIT, 770 barrier, pthread_barrier, 0, 0, 0); 771 CALL_FN_W_W(ret, fn, barrier); 772 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_BARRIER_WAIT, 773 barrier, pthread_barrier, 774 ret == 0 || ret == PTHREAD_BARRIER_SERIAL_THREAD, 775 ret == PTHREAD_BARRIER_SERIAL_THREAD, 0); 776 return ret; 777} 778 779 780// sem_init 781PTH_FUNC(int, semZuinitZa, // sem_init* 782 sem_t *sem, 783 int pshared, 784 unsigned int value) 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_SEM_INIT, 791 sem, pshared, value, 0, 0); 792 CALL_FN_W_WWW(ret, fn, sem, pshared, value); 793 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_INIT, 794 sem, 0, 0, 0, 0); 795 return ret; 796} 797 798// sem_destroy 799PTH_FUNC(int, semZudestroyZa, // sem_destroy* 800 sem_t *sem) 801{ 802 int ret; 803 int res; 804 OrigFn fn; 805 VALGRIND_GET_ORIG_FN(fn); 806 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_DESTROY, 807 sem, 0, 0, 0, 0); 808 CALL_FN_W_W(ret, fn, sem); 809 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_DESTROY, 810 sem, 0, 0, 0, 0); 811 return ret; 812} 813 814// sem_wait 815PTH_FUNC(int, semZuwaitZa, // sem_wait* 816 sem_t *sem) 817{ 818 int ret; 819 int res; 820 OrigFn fn; 821 VALGRIND_GET_ORIG_FN(fn); 822 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_WAIT, 823 sem, 0, 0, 0, 0); 824 CALL_FN_W_W(ret, fn, sem); 825 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT, 826 sem, ret == 0, 0, 0, 0); 827 return ret; 828} 829 830// sem_trywait 831PTH_FUNC(int, semZutrywaitZa, // sem_trywait* 832 sem_t *sem) 833{ 834 int ret; 835 int res; 836 OrigFn fn; 837 VALGRIND_GET_ORIG_FN(fn); 838 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_WAIT, 839 sem, 0, 0, 0, 0); 840 CALL_FN_W_W(ret, fn, sem); 841 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT, 842 sem, ret == 0, 0, 0, 0); 843 return ret; 844} 845 846// sem_timedwait 847PTH_FUNC(int, semZutimedwait, // sem_timedwait 848 sem_t *sem, const struct timespec *abs_timeout) 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_SEM_WAIT, 855 sem, 0, 0, 0, 0); 856 CALL_FN_W_WW(ret, fn, sem, abs_timeout); 857 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_WAIT, 858 sem, ret == 0, 0, 0, 0); 859 return ret; 860} 861 862// sem_post 863PTH_FUNC(int, semZupostZa, // sem_post* 864 sem_t *sem) 865{ 866 int ret; 867 int res; 868 OrigFn fn; 869 VALGRIND_GET_ORIG_FN(fn); 870 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_SEM_POST, 871 sem, 0, 0, 0, 0); 872 CALL_FN_W_W(ret, fn, sem); 873 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_SEM_POST, 874 sem, ret == 0, 0, 0, 0); 875 return ret; 876} 877 878// pthread_rwlock_init 879PTH_FUNC(int, 880 pthreadZurwlockZuinitZa, // pthread_rwlock_init* 881 pthread_rwlock_t* rwlock, 882 const pthread_rwlockattr_t* attr) 883{ 884 int ret; 885 int res; 886 OrigFn fn; 887 VALGRIND_GET_ORIG_FN(fn); 888 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_INIT, 889 rwlock, 0, 0, 0, 0); 890 CALL_FN_W_WW(ret, fn, rwlock, attr); 891 return ret; 892} 893 894// pthread_rwlock_destroy 895PTH_FUNC(int, 896 pthreadZurwlockZudestroyZa, // pthread_rwlock_destroy* 897 pthread_rwlock_t* rwlock) 898{ 899 int ret; 900 int res; 901 OrigFn fn; 902 VALGRIND_GET_ORIG_FN(fn); 903 CALL_FN_W_W(ret, fn, rwlock); 904 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_DESTROY, 905 rwlock, 0, 0, 0, 0); 906 return ret; 907} 908 909// pthread_rwlock_rdlock 910PTH_FUNC(int, 911 pthreadZurwlockZurdlockZa, // pthread_rwlock_rdlock* 912 pthread_rwlock_t* rwlock) 913{ 914 int ret; 915 int res; 916 OrigFn fn; 917 VALGRIND_GET_ORIG_FN(fn); 918 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_RDLOCK, 919 rwlock, 0, 0, 0, 0); 920 CALL_FN_W_W(ret, fn, rwlock); 921 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_RDLOCK, 922 rwlock, ret == 0, 0, 0, 0); 923 return ret; 924} 925 926// pthread_rwlock_wrlock 927PTH_FUNC(int, 928 pthreadZurwlockZuwrlockZa, // pthread_rwlock_wrlock* 929 pthread_rwlock_t* rwlock) 930{ 931 int ret; 932 int res; 933 OrigFn fn; 934 VALGRIND_GET_ORIG_FN(fn); 935 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_WRLOCK, 936 rwlock, 0, 0, 0, 0); 937 CALL_FN_W_W(ret, fn, rwlock); 938 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_WRLOCK, 939 rwlock, ret == 0, 0, 0, 0); 940 return ret; 941} 942 943// pthread_rwlock_timedrdlock 944PTH_FUNC(int, 945 pthreadZurwlockZutimedrdlockZa, // pthread_rwlock_timedrdlock* 946 pthread_rwlock_t* rwlock) 947{ 948 int ret; 949 int res; 950 OrigFn fn; 951 VALGRIND_GET_ORIG_FN(fn); 952 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_RDLOCK, 953 rwlock, 0, 0, 0, 0); 954 CALL_FN_W_W(ret, fn, rwlock); 955 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_RDLOCK, 956 rwlock, ret == 0, 0, 0, 0); 957 return ret; 958} 959 960// pthread_rwlock_timedwrlock 961PTH_FUNC(int, 962 pthreadZurwlockZutimedwrlockZa, // pthread_rwlock_timedwrlock* 963 pthread_rwlock_t* rwlock) 964{ 965 int ret; 966 int res; 967 OrigFn fn; 968 VALGRIND_GET_ORIG_FN(fn); 969 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_WRLOCK, 970 rwlock, 0, 0, 0, 0); 971 CALL_FN_W_W(ret, fn, rwlock); 972 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_WRLOCK, 973 rwlock, ret == 0, 0, 0, 0); 974 return ret; 975} 976 977// pthread_rwlock_tryrdlock 978PTH_FUNC(int, 979 pthreadZurwlockZutryrdlockZa, // pthread_rwlock_tryrdlock* 980 pthread_rwlock_t* rwlock) 981{ 982 int ret; 983 int res; 984 OrigFn fn; 985 VALGRIND_GET_ORIG_FN(fn); 986 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_RDLOCK, 987 rwlock, 0, 0, 0, 0); 988 CALL_FN_W_W(ret, fn, rwlock); 989 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_RDLOCK, 990 rwlock, ret == 0, 0, 0, 0); 991 return ret; 992} 993 994// pthread_rwlock_trywrlock 995PTH_FUNC(int, 996 pthreadZurwlockZutrywrlockZa, // pthread_rwlock_trywrlock* 997 pthread_rwlock_t* rwlock) 998{ 999 int ret; 1000 int res; 1001 OrigFn fn; 1002 VALGRIND_GET_ORIG_FN(fn); 1003 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_WRLOCK, 1004 rwlock, 0, 0, 0, 0); 1005 CALL_FN_W_W(ret, fn, rwlock); 1006 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_WRLOCK, 1007 rwlock, ret == 0, 0, 0, 0); 1008 return ret; 1009} 1010 1011// pthread_rwlock_unlock 1012PTH_FUNC(int, 1013 pthreadZurwlockZuunlockZa, // pthread_rwlock_unlock* 1014 pthread_rwlock_t* rwlock) 1015{ 1016 int ret; 1017 int res; 1018 OrigFn fn; 1019 VALGRIND_GET_ORIG_FN(fn); 1020 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_RWLOCK_UNLOCK, 1021 rwlock, 0, 0, 0, 0); 1022 CALL_FN_W_W(ret, fn, rwlock); 1023 VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_RWLOCK_UNLOCK, 1024 rwlock, ret == 0, 0, 0, 0); 1025 return ret; 1026} 1027