]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Implemented type checking for reader-writer synchronization
authorBart Van Assche <bvanassche@acm.org>
Mon, 27 Jul 2009 16:03:51 +0000 (16:03 +0000)
committerBart Van Assche <bvanassche@acm.org>
Mon, 27 Jul 2009 16:03:51 +0000 (16:03 +0000)
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
drd/drd_rwlock.c
drd/tests/Makefile.am
drd/tests/rwlock_type_checking.c [new file with mode: 0644]
drd/tests/rwlock_type_checking.stderr.exp [new file with mode: 0644]
drd/tests/rwlock_type_checking.vgtest [new file with mode: 0644]

index f24de5c83c7a999678e34cb1bdff589ffa919d66..13941c5ea2aa35cf561a47f0dea503972453726c 100644 (file)
@@ -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;
index 62af86198255a982adf12d5df79b94ce253fa481..9554e5c7bb4320c2b809151b49233d6d0d37bb2c 100644 (file)
@@ -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);
 
index 41413edb108112db3f770d1fba51cff111ae5793..7f0b704f0f5a019902d0d69951d28b71708054e6 100644 (file)
@@ -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 (file)
index 0000000..ddcd5c0
--- /dev/null
@@ -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 <pthread.h>
+#include <stdio.h>
+#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 (file)
index 0000000..db42de3
--- /dev/null
@@ -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 (file)
index 0000000..a7eb0f4
--- /dev/null
@@ -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