Index: helgrind/hg_main.c =================================================================== --- helgrind/hg_main.c (revision 6012) +++ helgrind/hg_main.c (working copy) @@ -2857,17 +2857,17 @@ /* Do nothing */ } -static void hg_pre_mutex_lock(ThreadId tid, void* void_mutex) +static void hg_pre_mutex_lock(ThreadId tid, Addr client_mutex) { - Mutex *mutex = get_mutex((Addr)void_mutex); + Mutex *mutex = get_mutex(client_mutex); test_mutex_state(mutex, MxLocked, tid); } -static void hg_post_mutex_lock(ThreadId tid, void* void_mutex) +static void hg_post_mutex_lock(ThreadId tid, Addr client_mutex) { static const Bool debug = False; - Mutex *mutex = get_mutex((Addr)void_mutex); + Mutex *mutex = get_mutex(client_mutex); const LockSet* ls; set_mutex_state(mutex, MxLocked, tid); @@ -2898,11 +2898,11 @@ } -static void hg_post_mutex_unlock(ThreadId tid, void* void_mutex) +static void hg_post_mutex_unlock(ThreadId tid, Addr client_mutex) { static const Bool debug = False; Int i = 0; - Mutex *mutex = get_mutex((Addr)void_mutex); + Mutex *mutex = get_mutex(client_mutex); const LockSet *ls; test_mutex_state(mutex, MxUnlocked, tid); @@ -3259,14 +3259,14 @@ static void bus_lock(void) { ThreadId tid = VG_(get_running_tid)(); - hg_pre_mutex_lock(tid, &__BUS_HARDWARE_LOCK__); - hg_post_mutex_lock(tid, &__BUS_HARDWARE_LOCK__); + hg_pre_mutex_lock(tid, (Addr)&__BUS_HARDWARE_LOCK__); + hg_post_mutex_lock(tid, (Addr)&__BUS_HARDWARE_LOCK__); } static void bus_unlock(void) { ThreadId tid = VG_(get_running_tid)(); - hg_post_mutex_unlock(tid, &__BUS_HARDWARE_LOCK__); + hg_post_mutex_unlock(tid, (Addr)&__BUS_HARDWARE_LOCK__); } /*--------------------------------------------------------------------*/ Index: include/pub_tool_tooliface.h =================================================================== --- include/pub_tool_tooliface.h (revision 6012) +++ include/pub_tool_tooliface.h (working copy) @@ -411,20 +411,32 @@ void VG_(track_post_thread_join) (void(*f)(ThreadId joiner, ThreadId joinee)); /* Mutex events (not exhaustive) - "void *mutex" is really a pthread_mutex * + "Addr mutex" is really a pthread_mutex_t * +*/ - Called before a thread can block while waiting for a mutex (called +void VG_(track_post_mutex_init)(void(*f)(ThreadId tid, Addr mutex, SizeT size)); +void VG_(track_pre_mutex_destroy)(void(*f)(ThreadId tid, Addr mutex, SizeT size)); + +/* Called before a thread can block while waiting for a mutex (called regardless of whether the thread will block or not). */ -void VG_(track_pre_mutex_lock)(void(*f)(ThreadId tid, void* mutex)); +void VG_(track_pre_mutex_lock)(void(*f)(ThreadId tid, Addr mutex)); /* Called once the thread actually holds the mutex (always paired with pre_mutex_lock). */ -void VG_(track_post_mutex_lock)(void(*f)(ThreadId tid, void* mutex)); +void VG_(track_post_mutex_lock)(void(*f)(ThreadId tid, Addr mutex)); -/* Called after a thread has released a mutex (no need for a corresponding - pre_mutex_unlock, because unlocking can't block). */ -void VG_(track_post_mutex_unlock)(void(*f)(ThreadId tid, void* mutex)); +/* Called before a thread releases a mutex. */ +void VG_(track_pre_mutex_unlock)(void(*f)(ThreadId tid, Addr mutex)); +/* Called after a thread has released a mutex. */ +void VG_(track_post_mutex_unlock)(void(*f)(ThreadId tid, Addr mutex)); + +void VG_(track_post_cond_init)(void(*f)(ThreadId tid, Addr cond, SizeT size)); +void VG_(track_pre_cond_destroy)(void(*f)(ThreadId tid, Addr cond, SizeT size)); +void VG_(track_pre_cond_wait)(void(*f)(ThreadId tid, Addr cond, Addr mutex)); +void VG_(track_post_cond_wait)(void(*f)(ThreadId tid, Addr cond, Addr mutex)); + + /* Signal events (not exhaustive) ... pre_send_signal, post_send_signal ... @@ -437,6 +449,7 @@ handler longjmps, this won't be called. */ void VG_(track_post_deliver_signal)(void(*f)(ThreadId tid, Int sigNo)); + /* Others... condition variables... ... */ Index: include/pub_tool_threadstate.h =================================================================== --- include/pub_tool_threadstate.h (revision 6012) +++ include/pub_tool_threadstate.h (working copy) @@ -46,6 +46,10 @@ /* Get the TID of the thread which currently has the CPU. */ extern ThreadId VG_(get_running_tid) ( void ); +Int VG_(get_tid_lwp)(ThreadId const tid); +ThreadId VG_(get_thread_id)(PosixThreadId const posixthreadid); +PosixThreadId VG_(get_pthread_id)(ThreadId const tid); + #endif // __PUB_TOOL_THREADSTATE_H /*--------------------------------------------------------------------*/ Index: include/pub_tool_libcprint.h =================================================================== --- include/pub_tool_libcprint.h (revision 6012) +++ include/pub_tool_libcprint.h (working copy) @@ -39,15 +39,27 @@ * --log-fd/--log-file/--log-socket argument, which defaults to 2 (stderr). * Hence no need for VG_(fprintf)(). */ -extern UInt VG_(printf) ( const HChar *format, ... ); +extern UInt VG_(printf) ( const HChar *format, ... ) +#if defined(__GNUC__) && defined(CHECK_FORMAT_STRINGS) + __attribute__((format(printf, 1, 2))) +#endif + ; extern UInt VG_(vprintf) ( const HChar *format, va_list vargs ); /* too noisy ... __attribute__ ((format (printf, 1, 2))) ; */ -extern UInt VG_(sprintf) ( Char* buf, const HChar* format, ... ); +extern UInt VG_(sprintf) ( Char* buf, const HChar* format, ... ) +#if defined(__GNUC__) && defined(CHECK_FORMAT_STRINGS) + __attribute__((format(printf, 2, 3))) +#endif + ; extern UInt VG_(vsprintf) ( Char* buf, const HChar* format, va_list vargs ); extern UInt VG_(snprintf) ( Char* buf, Int size, - const HChar *format, ... ); + const HChar *format, ... ) +#if defined(__GNUC__) && defined(CHECK_FORMAT_STRINGS) + __attribute__((format(printf, 3, 4))) +#endif + ; extern UInt VG_(vsnprintf)( Char* buf, Int size, const HChar *format, va_list vargs ); @@ -74,7 +86,11 @@ VgMsgKind; /* Send a single-part message. Appends a newline. */ -extern UInt VG_(message) ( VgMsgKind kind, const HChar* format, ... ); +extern UInt VG_(message) ( VgMsgKind kind, const HChar* format, ... ) +#if defined(__GNUC__) && defined(CHECK_FORMAT_STRINGS) + __attribute__((format(printf, 2, 3))) +#endif + ; extern UInt VG_(vmessage) ( VgMsgKind kind, const HChar* format, va_list vargs ); #endif // __PUB_TOOL_LIBCPRINT_H Index: include/pub_tool_debuginfo.h =================================================================== --- include/pub_tool_debuginfo.h (revision 6012) +++ include/pub_tool_debuginfo.h (working copy) @@ -135,6 +135,9 @@ extern VgSectKind VG_(seginfo_sect_kind)(Addr); +extern Char* VG_(seginfo_sect_kind_name)(Addr a, Char* buf, UInt n_buf); + + #endif // __PUB_TOOL_DEBUGINFO_H /*--------------------------------------------------------------------*/ Index: include/valgrind.h =================================================================== --- include/valgrind.h (revision 6012) +++ include/valgrind.h (working copy) @@ -2298,6 +2298,48 @@ VG_USERREQ__STACK_REGISTER = 0x1501, VG_USERREQ__STACK_DEREGISTER = 0x1502, VG_USERREQ__STACK_CHANGE = 0x1503, + + + /* To tell the core the POSIX thread ID */ + VG_USERREQ__SET_PTHREAD_SELF = 0x3000, + /* args: pthread_t (thread ID of running thread) */ + + /* To notify the core of pthread_thread_join calls */ + VG_USERREQ__POST_PTHREAD_JOIN = 0x3010, + /* args: pthread_t (joinee) */ + + /* To notify the core of a pthread_mutex_init call */ + VG_USERREQ__POST_MUTEX_INIT = 0x3020, + /* args: Addr, SizeT */ + /* To notify the core of a pthread_mutex_destroy call */ + VG_USERREQ__PRE_MUTEX_DESTROY = 0x3021, + /* args: Addr, SizeT */ + /* To notify the core of pthread_mutex_lock calls */ + VG_USERREQ__PRE_PTHREAD_MUTEX_LOCK = 0x3022, + /* args: pthread_mutex_t* */ + VG_USERREQ__POST_PTHREAD_MUTEX_LOCK = 0x3023, + /* args: pthread_mutex_t* */ + /* To notify the core of pthread_mutex_unlock calls */ + VG_USERREQ__PRE_PTHREAD_MUTEX_UNLOCK = 0x3024, + /* args: pthread_mutex_t* */ + /* To notify the core of pthread_mutex_unlock calls */ + VG_USERREQ__POST_PTHREAD_MUTEX_UNLOCK = 0x3025, + /* args: pthread_mutex_t* */ + + + /* To notify the core of a pthread_cond_init call */ + VG_USERREQ__POST_PTHREAD_COND_INIT = 0x3028, + /* args: Addr, SizeT */ + /* To notify the core of a pthread_cond_destroy call */ + VG_USERREQ__PRE_PTHREAD_COND_DESTROY = 0x3029, + /* args: Addr, SizeT */ + /* To notify the core of a pthread_cond_wait call */ + VG_USERREQ__PRE_PTHREAD_COND_WAIT = 0x302a, + /* args: Addr cond, Addr mutex */ + /* To notify the core of a pthread_cond_wait call */ + VG_USERREQ__POST_PTHREAD_COND_WAIT = 0x302b, + /* args: Addr cond, Addr mutex */ + } Vg_ClientRequest; #if !defined(__GNUC__) Index: include/pub_tool_basics.h =================================================================== --- include/pub_tool_basics.h (revision 6012) +++ include/pub_tool_basics.h (working copy) @@ -97,6 +97,16 @@ /* ThreadIds are simply indices into the VG_(threads)[] array. */ typedef UInt ThreadId; +/* A PosixThreadId uniquely identifies a POSIX thread in the client. This + datatype must be able to represent any client pthread_t value. The only + operations performed on this datatype are copying and comparison (==). + Note: the POSIX standard specifies that POSIX thread IDs may be implemented + as a struct, and that these must be compared by calling pthread_equal(). + Representing POSIX thread IDs by an integer, and comparing these IDs via + "==" is a shortcut that works (at least) on Linux. + */ +typedef UWord PosixThreadId; + /* An abstraction of syscall return values. When .isError == False, val holds the return value. When .isError == True, val holds the error code. Index: configure.in =================================================================== --- configure.in (revision 6012) +++ configure.in (working copy) @@ -738,6 +738,9 @@ none/tests/ppc64/Makefile none/tests/x86/Makefile none/docs/Makefile + drd/Makefile + drd/docs/Makefile + drd/tests/Makefile ) cat< #include +typedef struct +{ + void* (*start)(void*); + void* arg; +#if 0 + pthread_mutex_t mutex; + pthread_cond_t cond; +#else + int wrapper_started; +#endif +} VgPosixThreadArgs; + +static void* vg_thread_wrapper(void* arg) +{ + VgPosixThreadArgs* const arg_ptr = (VgPosixThreadArgs*)arg; + VgPosixThreadArgs const arg_copy = *arg_ptr; + int res; + +#if 0 + pthread_mutex_lock(arg_ptr->mutex); + pthread_cond_signal(arg_ptr->cond); + pthread_mutex_unlock(arg_ptr->mutex); +#else + arg_ptr->wrapper_started = 1; +#endif + + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SET_PTHREAD_SELF, + pthread_self(), 0, 0, 0, 0); + return (arg_copy.start)(arg_copy.arg); +} + // pthread_create PTH_FUNC(int, pthreadZucreateZAZa, // pthread_create@* pthread_t *thread, const pthread_attr_t *attr, void *(*start) (void *), void *arg) { - int ret; - void* fn; - VALGRIND_GET_NRADDR(fn); - fprintf(stderr, "<< pthread_create wrapper"); fflush(stderr); + int res; + int ret; + OrigFn fn; + VgPosixThreadArgs vgargs; + VALGRIND_GET_ORIG_FN(fn); + // Make sure that Valgrind knows about the main thread's POSIX thread ID. + // To do: move this statement to another place such that it is only called + // once during startup, instead of during every pthread_create() call. + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__SET_PTHREAD_SELF, + pthread_self(), 0, 0, 0, 0); + vgargs.start = start; + vgargs.arg = arg; + vgargs.wrapper_started = 0; +#if 0 + pthread_mutex_init(&vgargs.mutex, 0); + pthread_cond_init(&vgargs.cond, 0); + pthread_mutex_lock(&vgargs.mutex); +#endif + CALL_FN_W_WWWW(ret, fn, thread, attr, vg_thread_wrapper, &vgargs); +#if 0 + pthread_cond_wait(&vgargs.cond, &vgargs.mutex); + pthread_mutex_unlock(&vgargs.mutex); + pthread_cond_destroy(&vgargs.cond); + pthread_mutex_destroy(&vgargs.mutex); +#else + // Yes, you see it correctly, busy waiting ... The problem is that + // POSIX threads functions cannot be called here -- the functions defined + // in this file (vg_preloaded.c) would be called instead of those in + // libpthread.so. + while (! vgargs.wrapper_started) + ; +#endif + return ret; +} - CALL_FN_W_WWWW(ret, fn, thread,attr,start,arg); +// pthread_join +PTH_FUNC(int, pthreadZujoin, // pthread_join + pthread_t thread, void **thread_return) +{ + int ret; + int res; + OrigFn fn; - fprintf(stderr, " -> %d >>\n", ret); + VALGRIND_GET_ORIG_FN(fn); + CALL_FN_W_WW(ret, fn, thread, thread_return); + if (ret == 0) + { + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_PTHREAD_JOIN, + thread, 0, 0, 0, 0); + } return ret; } +// pthread_mutex_init +PTH_FUNC(int, pthreadZumutexZuinit, + pthread_mutex_t *mutex, + pthread_mutexattr_t const* attr) +{ + int ret; + int res; + OrigFn fn; + VALGRIND_GET_ORIG_FN(fn); + CALL_FN_W_WW(ret, fn, mutex, attr); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_MUTEX_INIT, + mutex, sizeof(*mutex), 0, 0, 0); + return ret; +} + +// pthread_mutex_destroy +PTH_FUNC(int, pthreadZumutexZudestroy, + pthread_mutex_t *mutex) +{ + int ret; + int res; + OrigFn fn; + VALGRIND_GET_ORIG_FN(fn); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_MUTEX_DESTROY, + mutex, sizeof(*mutex), 0, 0, 0); + CALL_FN_W_W(ret, fn, mutex); + return ret; +} + // pthread_mutex_lock PTH_FUNC(int, pthreadZumutexZulock, // pthread_mutex_lock pthread_mutex_t *mutex) { int ret; - void* fn; + int res; + OrigFn fn; VALGRIND_GET_ORIG_FN(fn); - fprintf(stderr, "<< pthread_mxlock %p", mutex); fflush(stderr); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_PTHREAD_MUTEX_LOCK, + mutex, 0, 0, 0, 0); + CALL_FN_W_W(ret, fn, mutex); + if (ret == 0) + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_PTHREAD_MUTEX_LOCK, + mutex, 0, 0, 0, 0); + return ret; +} +// pthread_mutex_trylock +PTH_FUNC(int, pthreadZumutexZutrylock, // pthread_mutex_trylock + pthread_mutex_t *mutex) +{ + int ret; + int res; + OrigFn fn; + VALGRIND_GET_ORIG_FN(fn); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_PTHREAD_MUTEX_LOCK, + mutex, 0, 0, 0, 0); CALL_FN_W_W(ret, fn, mutex); - - fprintf(stderr, " -> %d >>\n", ret); + if (ret == 0) + { + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_PTHREAD_MUTEX_LOCK, + mutex, 0, 0, 0, 0); + } return ret; } @@ -116,15 +237,44 @@ pthread_mutex_t *mutex) { int ret; - void* fn; + int res; + OrigFn fn; VALGRIND_GET_ORIG_FN(fn); - - fprintf(stderr, "<< pthread_mxunlk %p", mutex); fflush(stderr); - + VALGRIND_DO_CLIENT_REQUEST(res, -1, + VG_USERREQ__PRE_PTHREAD_MUTEX_UNLOCK, + mutex, 0, 0, 0, 0); CALL_FN_W_W(ret, fn, mutex); + if (ret == 0) + { + VALGRIND_DO_CLIENT_REQUEST(res, -1, + VG_USERREQ__POST_PTHREAD_MUTEX_UNLOCK, + mutex, 0, 0, 0, 0); + } + return ret; +} - fprintf(stderr, " -> %d >>\n", ret); +// pthread_cond_wait +PTH_FUNC(int, pthreadZucontZuwait, // pthread_cond_wait + pthread_cond_t *cond, + pthread_mutex_t *mutex) +{ + int ret; + int res; + OrigFn fn; + VALGRIND_GET_ORIG_FN(fn); + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__PRE_PTHREAD_COND_WAIT, + cond, mutex, 0, 0, 0); + CALL_FN_W_WW(ret, fn, cond, mutex); + if (ret == 0) + { + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__POST_PTHREAD_COND_WAIT, + cond, mutex, 0, 0, 0); + } return ret; } -#endif +/* + * Local variables: + * c-basic-offset: 3 + * End: + */ Index: coregrind/m_syswrap/syswrap-linux.c =================================================================== --- coregrind/m_syswrap/syswrap-linux.c (revision 6012) +++ coregrind/m_syswrap/syswrap-linux.c (working copy) @@ -164,7 +164,7 @@ assembler. */ #if defined(VGP_x86_linux) asm volatile ( - "movl %1, %0\n" /* set tst->status = VgTs_Empty */ + // "movl %1, %0\n" /* set tst->status = VgTs_Empty */ "movl %2, %%eax\n" /* set %eax = __NR_exit */ "movl %3, %%ebx\n" /* set %ebx = tst->os_state.exitcode */ "int $0x80\n" /* exit(tst->os_state.exitcode) */ @@ -172,7 +172,7 @@ : "n" (VgTs_Empty), "n" (__NR_exit), "m" (tst->os_state.exitcode)); #elif defined(VGP_amd64_linux) asm volatile ( - "movl %1, %0\n" /* set tst->status = VgTs_Empty */ + // "movl %1, %0\n" /* set tst->status = VgTs_Empty */ "movq %2, %%rax\n" /* set %rax = __NR_exit */ "movq %3, %%rdi\n" /* set %rdi = tst->os_state.exitcode */ "syscall\n" /* exit(tst->os_state.exitcode) */ @@ -181,7 +181,7 @@ #elif defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) { UInt vgts_empty = (UInt)VgTs_Empty; asm volatile ( - "stw %1,%0\n\t" /* set tst->status = VgTs_Empty */ + // "stw %1,%0\n\t" /* set tst->status = VgTs_Empty */ "li 0,%2\n\t" /* set r0 = __NR_exit */ "lwz 3,%3\n\t" /* set r3 = tst->os_state.exitcode */ "sc\n\t" /* exit(tst->os_state.exitcode) */ Index: coregrind/m_tooliface.c =================================================================== --- coregrind/m_tooliface.c (revision 6012) +++ coregrind/m_tooliface.c (working copy) @@ -326,13 +326,21 @@ DEF(track_post_thread_create, ThreadId, ThreadId) DEF(track_post_thread_join, ThreadId, ThreadId) -DEF(track_pre_mutex_lock, ThreadId, void*) -DEF(track_post_mutex_lock, ThreadId, void*) -DEF(track_post_mutex_unlock, ThreadId, void*) +DEF(track_post_mutex_init, ThreadId, Addr, SizeT) +DEF(track_pre_mutex_destroy, ThreadId, Addr, SizeT) +DEF(track_pre_mutex_lock, ThreadId, Addr) +DEF(track_post_mutex_lock, ThreadId, Addr) +DEF(track_pre_mutex_unlock, ThreadId, Addr) +DEF(track_post_mutex_unlock, ThreadId, Addr) DEF(track_pre_deliver_signal, ThreadId, Int sigNo, Bool) DEF(track_post_deliver_signal, ThreadId, Int sigNo) +DEF(track_post_cond_init, ThreadId, Addr, SizeT); +DEF(track_pre_cond_destroy, ThreadId, Addr, SizeT); +DEF(track_pre_cond_wait, ThreadId, Addr, Addr); +DEF(track_post_cond_wait, ThreadId, Addr, Addr); + /*--------------------------------------------------------------------*/ /*--- end ---*/ /*--------------------------------------------------------------------*/ Index: coregrind/pub_core_tooliface.h =================================================================== --- coregrind/pub_core_tooliface.h (revision 6012) +++ coregrind/pub_core_tooliface.h (working copy) @@ -205,10 +205,18 @@ void (*track_post_thread_create)(ThreadId, ThreadId); void (*track_post_thread_join) (ThreadId, ThreadId); - void (*track_pre_mutex_lock) (ThreadId, void*); - void (*track_post_mutex_lock) (ThreadId, void*); - void (*track_post_mutex_unlock)(ThreadId, void*); + void (*track_post_mutex_init) (ThreadId, Addr, SizeT); + void (*track_pre_mutex_destroy)(ThreadId, Addr, SizeT); + void (*track_pre_mutex_lock) (ThreadId, Addr); + void (*track_post_mutex_lock) (ThreadId, Addr); + void (*track_pre_mutex_unlock) (ThreadId, Addr); + void (*track_post_mutex_unlock)(ThreadId, Addr); + void (*track_post_cond_init) (ThreadId, Addr, SizeT); + void (*track_pre_cond_destroy) (ThreadId, Addr, SizeT); + void (*track_pre_cond_wait) (ThreadId, Addr, Addr); + void (*track_post_cond_wait) (ThreadId, Addr, Addr); + void (*track_pre_deliver_signal) (ThreadId, Int sigNo, Bool); void (*track_post_deliver_signal)(ThreadId, Int sigNo); Index: coregrind/m_debuginfo/debuginfo.c =================================================================== --- coregrind/m_debuginfo/debuginfo.c (revision 6012) +++ coregrind/m_debuginfo/debuginfo.c (working copy) @@ -912,6 +912,35 @@ return ret; } +Char* VG_(seginfo_sect_kind_name)(Addr a, Char* buf, UInt n_buf) +{ + switch (VG_(seginfo_sect_kind)(a)) + { + case Vg_SectUnknown: + VG_(snprintf)(buf, n_buf, "Unknown"); + break; + case Vg_SectText: + VG_(snprintf)(buf, n_buf, "Text"); + break; + case Vg_SectData: + VG_(snprintf)(buf, n_buf, "Data"); + break; + case Vg_SectBSS: + VG_(snprintf)(buf, n_buf, "BSS"); + break; + case Vg_SectGOT: + VG_(snprintf)(buf, n_buf, "GOT"); + break; + case Vg_SectPLT: + VG_(snprintf)(buf, n_buf, "PLT"); + break; + default: + VG_(snprintf)(buf, n_buf, "???"); + vg_assert(0); + } + return buf; +} + Int VG_(seginfo_syms_howmany) ( const SegInfo *si ) { return si->symtab_used; Index: coregrind/m_threadmodel.c =================================================================== --- coregrind/m_threadmodel.c (revision 6012) +++ coregrind/m_threadmodel.c (working copy) @@ -807,7 +807,7 @@ if (mx->state == MX_Locked && mx->owner == tid) /* deadlock */ mutex_report(tid, mutexp, MXE_Deadlock, "trylocking"); - VG_TRACK( pre_mutex_lock, tid, (void *)mutexp ); + VG_TRACK( pre_mutex_lock, tid, mutexp ); } /* Give up waiting for a mutex. Fails if: @@ -834,7 +834,7 @@ switch(mx->state) { case MX_Unlocking: /* ownership transfer or relock */ - VG_TRACK( post_mutex_unlock, mx->owner, (void *)mutexp ); + VG_TRACK( post_mutex_unlock, mx->owner, mutexp ); if (mx->owner != tid) thread_unblock_mutex(tid, mx, "acquiring mutex"); break; @@ -846,7 +846,7 @@ case MX_Locked: if (debug_mutex) VG_(printf)("mutex=%p mx->state=%s\n", mutexp, pp_mutexstate(mx)); - VG_TRACK( post_mutex_unlock, mx->owner, (void *)mutexp ); + VG_TRACK( post_mutex_unlock, mx->owner, mutexp ); mutex_report(tid, mutexp, MXE_Locked, "acquiring"); thread_unblock_mutex(tid, mx, "acquiring mutex"); break; @@ -859,7 +859,7 @@ mx->owner = tid; mutex_setstate(tid, mx, MX_Locked); - VG_TRACK( post_mutex_lock, tid, (void *)mutexp ); + VG_TRACK( post_mutex_lock, tid, mutexp ); } /* Try unlocking a lock. This will move it into a state where it can @@ -968,7 +968,7 @@ case MX_Unlocking: /* OK - we need to complete the unlock */ - VG_TRACK( post_mutex_unlock, tid, (void *)mutexp ); + VG_TRACK( post_mutex_unlock, tid, mutexp ); mutex_setstate(tid, mx, MX_Free); break; Index: coregrind/m_scheduler/scheduler.c =================================================================== --- coregrind/m_scheduler/scheduler.c (revision 6012) +++ coregrind/m_scheduler/scheduler.c (working copy) @@ -364,7 +364,10 @@ VG_(sigemptyset)(&VG_(threads)[tid].sig_mask); VG_(sigemptyset)(&VG_(threads)[tid].tmp_sig_mask); - os_state_clear(&VG_(threads)[tid]); + // Do NOT clear the OS state record here -- this data is still accessed + // after the thread exited from within vg_preloaded.c (pthread_join() + // wrapper). + // os_state_clear(&VG_(threads)[tid]); /* start with no altstack */ VG_(threads)[tid].altstack.ss_sp = (void *)0xdeadbeef; @@ -1215,6 +1218,72 @@ SET_CLREQ_RETVAL( tid, 0 ); /* return value is meaningless */ break; } + case VG_USERREQ__SET_PTHREAD_SELF: { + VG_(set_pthread_id)(VG_(get_running_tid)(), (PosixThreadId)(arg[1])); + break; + } + + case VG_USERREQ__POST_PTHREAD_JOIN: { + ThreadId const joinee = VG_(get_thread_id)(arg[1]); + // VG_(printf)("joinee = %d -> %d\n", arg[1], joinee); + vg_assert(joinee); + VG_TRACK(post_thread_join, + VG_(get_running_tid)(), + joinee); + if (joinee) + { + ThreadState *tst; + tst = VG_(get_ThreadState)(joinee); + vg_assert(tst); + vg_assert(tst->status == VgTs_Zombie); + tst->status = VgTs_Empty; + } + break; } + + case VG_USERREQ__POST_MUTEX_INIT: + VG_TRACK(post_mutex_init, VG_(get_running_tid)(), arg[1], arg[2]); + break; + + case VG_USERREQ__PRE_MUTEX_DESTROY: + VG_TRACK(pre_mutex_destroy, VG_(get_running_tid)(), arg[1], arg[2]); + break; + + case VG_USERREQ__PRE_PTHREAD_MUTEX_LOCK: + VG_TRACK(pre_mutex_lock, VG_(get_running_tid)(), arg[1]); + break; + + case VG_USERREQ__POST_PTHREAD_MUTEX_LOCK: + VG_TRACK(post_mutex_lock, VG_(get_running_tid)(), arg[1]); + break; + + case VG_USERREQ__PRE_PTHREAD_MUTEX_UNLOCK: + VG_TRACK(pre_mutex_unlock, VG_(get_running_tid)(), arg[1]); + break; + + case VG_USERREQ__POST_PTHREAD_MUTEX_UNLOCK: + VG_TRACK(post_mutex_unlock, VG_(get_running_tid)(), arg[1]); + break; + + case VG_USERREQ__POST_PTHREAD_COND_INIT: + VG_TRACK(post_cond_init, + VG_(get_running_tid)(), arg[1], arg[2]); + break; + + case VG_USERREQ__PRE_PTHREAD_COND_DESTROY: + VG_TRACK(pre_cond_destroy, + VG_(get_running_tid)(), arg[1], arg[2]); + break; + + case VG_USERREQ__PRE_PTHREAD_COND_WAIT: + VG_TRACK(pre_cond_wait, + VG_(get_running_tid)(), arg[1], arg[2]); + break; + + case VG_USERREQ__POST_PTHREAD_COND_WAIT: + VG_TRACK(post_cond_wait, + VG_(get_running_tid)(), arg[1], arg[2]); + break; + case VG_USERREQ__GET_MALLOCFUNCS: { struct vg_mallocfunc_info *info = (struct vg_mallocfunc_info *)arg[1]; @@ -1380,3 +1449,10 @@ /*--------------------------------------------------------------------*/ /*--- end ---*/ /*--------------------------------------------------------------------*/ + + +/* + * Local variables: + * c-basic-offset: 3 + * End: + */ Index: coregrind/m_threadstate.c =================================================================== --- coregrind/m_threadstate.c (revision 6012) +++ coregrind/m_threadstate.c (working copy) @@ -123,6 +123,41 @@ return VG_INVALID_THREADID; } +Int VG_(get_tid_lwp)(ThreadId const tid) +{ + vg_assert(1 <= tid && tid < VG_N_THREADS + && VG_(threads)[tid].status != VgTs_Empty); + return VG_(threads)[tid].os_state.lwpid; +} + +ThreadId VG_(get_thread_id)(PosixThreadId const posixthreadid) +{ + ThreadId tid; + for(tid = 1; tid < VG_N_THREADS; tid++) + { + if (VG_(threads)[tid].status != VgTs_Empty + && VG_(threads)[tid].os_state.posixthreadid == posixthreadid) + { + return tid; + } + } + return VG_INVALID_THREADID; +} + +PosixThreadId VG_(get_pthread_id)(ThreadId const tid) +{ + vg_assert(1 <= tid && tid < VG_N_THREADS + && VG_(threads)[tid].status != VgTs_Empty); + return VG_(threads)[tid].os_state.posixthreadid; +} + +void VG_(set_pthread_id)(ThreadId const tid, PosixThreadId const posixthreadid) +{ + vg_assert(1 <= tid && tid < VG_N_THREADS + && VG_(threads)[tid].status != VgTs_Empty); + VG_(threads)[tid].os_state.posixthreadid = posixthreadid; +} + /*--------------------------------------------------------------------*/ /*--- end ---*/ /*--------------------------------------------------------------------*/ Index: coregrind/pub_core_threadstate.h =================================================================== --- coregrind/pub_core_threadstate.h (revision 6012) +++ coregrind/pub_core_threadstate.h (working copy) @@ -112,6 +112,7 @@ struct { /* who we are */ Int lwpid; // PID of kernel task + PosixThreadId posixthreadid; // pthread_t, in case of a POSIX thread. Int threadgroup; // thread group id ThreadId parent; // parent tid (if any) @@ -242,6 +243,14 @@ ThreadId */ extern ThreadId VG_(get_lwp_tid)(Int lwpid); +ThreadId VG_(get_thread_id)(PosixThreadId const posixthreadid); + +PosixThreadId VG_(get_pthread_id)(ThreadId const tid); + +void VG_(set_pthread_id)(ThreadId const tid, + PosixThreadId const posixthreadid); + + #endif // __PUB_CORE_THREADSTATE_H /*--------------------------------------------------------------------*/