868 lines
30 KiB
Diff
868 lines
30 KiB
Diff
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<<EOF
|
|
Index: Makefile.am
|
|
===================================================================
|
|
--- Makefile.am (revision 6012)
|
|
+++ Makefile.am (working copy)
|
|
@@ -8,6 +8,7 @@
|
|
callgrind \
|
|
massif \
|
|
lackey \
|
|
+ drd \
|
|
none
|
|
|
|
# Temporary: we want to compile Helgrind, but not regtest it.
|
|
Index: coregrind/vg_preloaded.c
|
|
===================================================================
|
|
--- coregrind/vg_preloaded.c (revision 6012)
|
|
+++ coregrind/vg_preloaded.c (working copy)
|
|
@@ -71,8 +71,6 @@
|
|
/*--- end ---*/
|
|
/*--------------------------------------------------------------------*/
|
|
|
|
-#if 0
|
|
-
|
|
#define PTH_FUNC(ret_ty, f, args...) \
|
|
ret_ty VG_WRAP_FUNCTION_ZZ(libpthreadZdsoZd0,f)(args); \
|
|
ret_ty VG_WRAP_FUNCTION_ZZ(libpthreadZdsoZd0,f)(args)
|
|
@@ -80,34 +78,157 @@
|
|
#include <stdio.h>
|
|
#include <pthread.h>
|
|
|
|
+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
|
|
|
|
/*--------------------------------------------------------------------*/
|