From df0bcd77a8044b499bf301d299e976b70c59f587 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Mon, 27 Jul 2009 16:03:51 +0000 Subject: [PATCH] Implemented type checking for reader-writer synchronization objects: complain upon attempts to use a POSIX rwlock where a user-defined rwlock is expected and vice versa. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@10638 --- drd/drd_clientobj.h | 1 + drd/drd_rwlock.c | 47 ++++++++++++++++++++--- drd/tests/Makefile.am | 3 ++ drd/tests/rwlock_type_checking.c | 35 +++++++++++++++++ drd/tests/rwlock_type_checking.stderr.exp | 31 +++++++++++++++ drd/tests/rwlock_type_checking.vgtest | 4 ++ 6 files changed, 115 insertions(+), 6 deletions(-) create mode 100644 drd/tests/rwlock_type_checking.c create mode 100644 drd/tests/rwlock_type_checking.stderr.exp create mode 100644 drd/tests/rwlock_type_checking.vgtest diff --git a/drd/drd_clientobj.h b/drd/drd_clientobj.h index f24de5c83c..13941c5ea2 100644 --- a/drd/drd_clientobj.h +++ b/drd/drd_clientobj.h @@ -124,6 +124,7 @@ struct rwlock_info void (*cleanup)(union drd_clientobj*); void (*delete_thread)(union drd_clientobj*, DrdThreadId); ExeContext* first_observed_at; + RwLockT rwlock_type; OSet* thread_info; ULong acquiry_time_ms; ExeContext* acquired_at; diff --git a/drd/drd_rwlock.c b/drd/drd_rwlock.c index 62af861982..9554e5c7bb 100644 --- a/drd/drd_rwlock.c +++ b/drd/drd_rwlock.c @@ -194,9 +194,40 @@ static void DRD_(rwlock_combine_other_vc)(struct rwlock_info* const p, DRD_(vc_cleanup)(&old_vc); } +/** + * Compare the type of the rwlock specified at initialization time with + * the type passed as an argument, and complain if these two types do not + * match. + */ +static Bool drd_rwlock_check_type(struct rwlock_info* const p, + const RwLockT rwlock_type) +{ + tl_assert(p); + /* The code below has to be updated if additional rwlock types are added. */ + tl_assert(rwlock_type == pthread_rwlock || rwlock_type == user_rwlock); + tl_assert(p->rwlock_type == pthread_rwlock || p->rwlock_type == user_rwlock); + + if (p->rwlock_type == rwlock_type) + return True; + + { + RwlockErrInfo REI = { DRD_(thread_get_running_tid)(), p->a1 }; + VG_(maybe_record_error) + (VG_(get_running_tid)(), + RwlockErr, + VG_(get_IP)(VG_(get_running_tid)()), + rwlock_type == pthread_rwlock + ? "Attempt to use a user-defined rwlock as a POSIX rwlock" + : "Attempt to use a POSIX rwlock as a user-defined rwlock", + &REI); + } + return False; +} + /** Initialize the rwlock_info data structure *p. */ static -void DRD_(rwlock_initialize)(struct rwlock_info* const p, const Addr rwlock) +void DRD_(rwlock_initialize)(struct rwlock_info* const p, const Addr rwlock, + const RwLockT rwlock_type) { tl_assert(rwlock != 0); tl_assert(p->a1 == rwlock); @@ -205,6 +236,7 @@ void DRD_(rwlock_initialize)(struct rwlock_info* const p, const Addr rwlock) p->cleanup = (void(*)(DrdClientobj*))rwlock_cleanup; p->delete_thread = (void(*)(DrdClientobj*, DrdThreadId))rwlock_delete_thread; + p->rwlock_type = rwlock_type; p->thread_info = VG_(OSetGen_Create)( 0, 0, VG_(malloc), "drd.rwlock.ri.1", VG_(free)); p->acquiry_time_ms = 0; @@ -248,14 +280,17 @@ static void rwlock_cleanup(struct rwlock_info* p) static struct rwlock_info* -DRD_(rwlock_get_or_allocate)(const Addr rwlock) +DRD_(rwlock_get_or_allocate)(const Addr rwlock, const RwLockT rwlock_type) { struct rwlock_info* p; tl_assert(offsetof(DrdClientobj, rwlock) == 0); p = &(DRD_(clientobj_get)(rwlock, ClientRwlock)->rwlock); if (p) + { + drd_rwlock_check_type(p, rwlock_type); return p; + } if (DRD_(clientobj_present)(rwlock, rwlock + 1)) { @@ -269,7 +304,7 @@ DRD_(rwlock_get_or_allocate)(const Addr rwlock) } p = &(DRD_(clientobj_add)(rwlock, ClientRwlock)->rwlock); - DRD_(rwlock_initialize)(p, rwlock); + DRD_(rwlock_initialize)(p, rwlock, rwlock_type); return p; } @@ -307,7 +342,7 @@ struct rwlock_info* DRD_(rwlock_pre_init)(const Addr rwlock, return p; } - p = DRD_(rwlock_get_or_allocate)(rwlock); + p = DRD_(rwlock_get_or_allocate)(rwlock, rwlock_type); return p; } @@ -350,7 +385,7 @@ void DRD_(rwlock_pre_rdlock)(const Addr rwlock, const RwLockT rwlock_type) rwlock); } - p = DRD_(rwlock_get_or_allocate)(rwlock); + p = DRD_(rwlock_get_or_allocate)(rwlock, rwlock_type); tl_assert(p); if (DRD_(rwlock_is_wrlocked_by)(p, DRD_(thread_get_running_tid)())) @@ -422,7 +457,7 @@ void DRD_(rwlock_pre_wrlock)(const Addr rwlock, const RwLockT rwlock_type) } if (p == 0) - p = DRD_(rwlock_get_or_allocate)(rwlock); + p = DRD_(rwlock_get_or_allocate)(rwlock, rwlock_type); tl_assert(p); diff --git a/drd/tests/Makefile.am b/drd/tests/Makefile.am index 41413edb10..7f0b704f0f 100644 --- a/drd/tests/Makefile.am +++ b/drd/tests/Makefile.am @@ -144,6 +144,8 @@ EXTRA_DIST = \ rwlock_race.vgtest \ rwlock_test.stderr.exp \ rwlock_test.vgtest \ + rwlock_type_checking.stderr.exp \ + rwlock_type_checking.vgtest \ sem_as_mutex.stderr.exp \ sem_as_mutex.vgtest \ sem_as_mutex2.stderr.exp \ @@ -254,6 +256,7 @@ check_PROGRAMS = \ recursive_mutex \ rwlock_race \ rwlock_test \ + rwlock_type_checking \ sem_as_mutex \ sem_open \ sigalrm \ diff --git a/drd/tests/rwlock_type_checking.c b/drd/tests/rwlock_type_checking.c new file mode 100644 index 0000000000..ddcd5c08f7 --- /dev/null +++ b/drd/tests/rwlock_type_checking.c @@ -0,0 +1,35 @@ +/** + * @file rwlock_type_checking.c + * + * @brief Test whether DRD reports attempts to use a user-defined rwlock as + * a POSIX rwlock and vice versa. + */ + + +#define _GNU_SOURCE 1 + +#include +#include +#include "../../config.h" +#include "../../drd/drd.h" + + +int main(int argc, char** argv) +{ + pthread_rwlock_t posix_rwlock; + int user_defined_rwlock; + + ANNOTATE_RWLOCK_CREATE(&user_defined_rwlock); + pthread_rwlock_init(&posix_rwlock, 0); + + pthread_rwlock_rdlock((pthread_rwlock_t*)&user_defined_rwlock); + + ANNOTATE_READERLOCK_ACQUIRED(&posix_rwlock); + + pthread_rwlock_destroy(&posix_rwlock); + ANNOTATE_RWLOCK_DESTROY(&user_defined_rwlock); + + fprintf(stderr, "Finished.\n"); + + return 0; +} diff --git a/drd/tests/rwlock_type_checking.stderr.exp b/drd/tests/rwlock_type_checking.stderr.exp new file mode 100644 index 0000000000..db42de30ac --- /dev/null +++ b/drd/tests/rwlock_type_checking.stderr.exp @@ -0,0 +1,31 @@ + +Attempt to use a user-defined rwlock as a POSIX rwlock: rwlock 0x......... + at 0x........: pthread_rwlock_rdlock* (drd_pthread_intercepts.c:?) + by 0x........: main (rwlock_type_checking.c:?) +rwlock 0x........ was first observed at: + at 0x........: vgDrdCl_annotate_rwlock (drd.h:?) + by 0x........: main (rwlock_type_checking.c:?) + +Attempt to use a POSIX rwlock as a user-defined rwlock: rwlock 0x......... + at 0x........: vgDrdCl_annotate_rwlock (drd.h:?) + by 0x........: main (rwlock_type_checking.c:?) +rwlock 0x........ was first observed at: + at 0x........: pthread_rwlock_init* (drd_pthread_intercepts.c:?) + by 0x........: main (rwlock_type_checking.c:?) + +Destroying locked rwlock: rwlock 0x......... + at 0x........: pthread_rwlock_destroy* (drd_pthread_intercepts.c:?) + by 0x........: main (rwlock_type_checking.c:?) +rwlock 0x........ was first observed at: + at 0x........: pthread_rwlock_init* (drd_pthread_intercepts.c:?) + by 0x........: main (rwlock_type_checking.c:?) + +Destroying locked rwlock: rwlock 0x......... + at 0x........: vgDrdCl_annotate_rwlock (drd.h:?) + by 0x........: main (rwlock_type_checking.c:?) +rwlock 0x........ was first observed at: + at 0x........: vgDrdCl_annotate_rwlock (drd.h:?) + by 0x........: main (rwlock_type_checking.c:?) +Finished. + +ERROR SUMMARY: 4 errors from 4 contexts (suppressed: 0 from 0) diff --git a/drd/tests/rwlock_type_checking.vgtest b/drd/tests/rwlock_type_checking.vgtest new file mode 100644 index 0000000000..a7eb0f4877 --- /dev/null +++ b/drd/tests/rwlock_type_checking.vgtest @@ -0,0 +1,4 @@ +prereq: test -e rwlock_type_checking && ./supported_libpthread +vgopts: --read-var-info=yes --check-stack-var=yes --show-confl-seg=no +prog: rwlock_type_checking +stderr_filter: filter_stderr -- 2.47.3