This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] [Annotalysis] Bugfix for spurious thread safety warnings with shared mutexes
- From: Delesley Hutchins <delesley at google dot com>
- To: gcc-patches <gcc-patches at gcc dot gnu dot org>, Diego Novillo <dnovillo at google dot com>, Ollie Wild <aaw at google dot com>
- Date: Mon, 10 Oct 2011 13:37:50 -0700
- Subject: [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