This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] [Annotalysis] Bugfix for spurious thread safety warnings with shared mutexes


This patch fixes an error where Annotalysis generates bogus warnings
when a shared lock is released in a function that has a "universal
lock" -- typically produced when gcc cannot parse a lock expression.

Bootstrapped and passed gcc regression testsuite on
x86_64-unknown-linux-gnu.  Okay for google/gcc-4_6?

 -DeLesley

Changelog.google-4_6:
2011-10-10  DeLesley Hutchins  <delesley@google.com>

    * tree-threadsafe-analyze.c (remove_lock_from_lockset)

testsuite/Changelog.google-4_6:
2011-10-10  DeLesley Hutchins  <delesley@google.com>

    * g++.dg/thread-ann/thread_annot_lock-83.C:
        New regression test


Index: gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-83.C
===================================================================
--- gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-83.C	(revision 0)
+++ gcc/testsuite/g++.dg/thread-ann/thread_annot_lock-83.C	(revision 0)
@@ -0,0 +1,31 @@
+// Regression test for bugfix, where shared locks are not properly
+// removed from locksets if a "universal lock" is present.
+// { dg-do compile }
+// { dg-options "-Wthread-safety" }
+
+#include "thread_annot_common.h"
+
+class Foo;
+
+class Bar {
+public:
+  Foo*  foo;
+  Mutex mu_;
+
+  // foo->mu_ is not visible at this point in the code.
+  // so the attribute will become a "universal lock."
+  void bar() EXCLUSIVE_LOCKS_REQUIRED(foo->mu_);
+};
+
+
+class Foo {
+public:
+  Mutex mu_;
+  int a;
+};
+
+
+void Bar::bar() {
+  ReaderMutexLock rlock(&mu_);
+}
+
Index: gcc/tree-threadsafe-analyze.c
===================================================================
--- gcc/tree-threadsafe-analyze.c	(revision 179771)
+++ gcc/tree-threadsafe-analyze.c	(working copy)
@@ -1830,14 +1830,27 @@ remove_lock_from_lockset (tree lockable, struct po
 {
   tree lock_contained;

-  if ((lock_contained = lock_set_contains(live_excl_locks, lockable, NULL_TREE,
-                                          false)) != NULL_TREE)
+  /* Try to remove the actual lock. */
+  if ((lock_contained = lock_set_contains(live_excl_locks, lockable,
+                                          NULL_TREE, true)) != NULL_TREE)
     pointer_set_delete (live_excl_locks, lock_contained);
   else if ((lock_contained = lock_set_contains(live_shared_locks, lockable,
-                                               NULL_TREE, false)) != NULL_TREE)
+                                               NULL_TREE, true)) != NULL_TREE)
     pointer_set_delete (live_shared_locks, lock_contained);

-  return lock_contained;
+  if (lock_contained)
+    return lock_contained;
+
+  /* If either of lock sets contains the universal lock, then pretend that
+   we've removed it, to avoid a warning about unlocking a lock that was
+   not acquired. */
+  if (pointer_set_contains (live_excl_locks, error_mark_node))
+    return lockable;
+
+  if (pointer_set_contains(live_shared_locks, error_mark_node))
+    return lockable;
+
+  return NULL_TREE;
 }

 /* This function handles function calls that release locks (i.e. the


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]