Re: [PATCH] D14731: [libcxx] Add clang thread safety annotations to mutex and lock_guard
jamesr added a comment. Thank you for posting the LIT changes - that's the part I was unable to figure out. I have a number of additional failure test cases that I will add. I don't know what sort of code this could break, although I certainly don't claim to know more about these annotations than the author. Do you have a link to that discussion handy? The most obvious way this could break existing code would be if existing code was compiling with -Wthread-safety and had its own annotations that were inconsistent with these, but as it's a compile error to declare thread-safety relationships with types that aren't already annotated I can't see how any code that would be broken could compile today. Concretely, if some code is written like this today: struct Foo { int a __attribute__((guarded_by(m))); std::mutex m; }; void Bad(Foo* f) { f->a++; } will fail to compile without this patch in libc++ with the error: /tmp/test.cc:4:26: error: 'guarded_by' attribute requires arguments whose type is annotated with 'capability' attribute; type here is 'std::mutex' [-Werror,-Wthread-safety-attributes] int a __attribute__((guarded_by(m)) http://reviews.llvm.org/D14731 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D14731: [libcxx] Add clang thread safety annotations to mutex and lock_guard
jamesr added a comment. Ah, that's true. I didn't think of that case. With the design of these annotations the author of that function would have to disable checks in each piece of code that uses these patterns. What about adding a different guard for these annotations in libc++ that consumers could choose to toggle independently of the -Wthread-safety compiler option? That way consumers could choose to enable the libc++ annotations if their codebase was compatible with them. The alternative is that consumers have to fully wrap the std:: types in their own types to add the annotations which works but makes code reuse very difficult. http://reviews.llvm.org/D14731 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D14731: [libcxx] Add clang thread safety annotations to mutex and lock_guard
jamesr added a comment. In http://reviews.llvm.org/D14731#373289, @EricWF wrote: > My suggestion would be to make these annotations OFF by default and allow > users to turn them on with a macro. Our comments crossed streams but suggested the same thing :). Any suggestions on a naming convention for the guard? Also, would I set this macro unconditionally in LIT or is there a way to have it run tests both with and without the macro to ensure that when it is off code like the snippet you posted continues to build unmodified? http://reviews.llvm.org/D14731 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D14731: [libcxx] Add clang thread safety annotations to mutex and lock_guard
jamesr updated this revision to Diff 50481. jamesr added a comment. This patch guards the new annotations with _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS and adds a number of tests to check that the annotations produce errors when the annotations are enabled that code violates the thread safety rules, that correct code does not produce errors, and that code that does not enable the annotations does not produce errors even in code that the thread-safety feature in Clang does not understand. The feature guard is state in the positive as opposed to the negative as the annotations may be incompatible with correct code in some situations. http://reviews.llvm.org/D14731 Files: include/__config include/__mutex_base test/libcxx/test/format.py test/libcxx/thread/thread.mutex/thread_safety_access_guarded_without_lock.fail.cpp test/libcxx/thread/thread.mutex/thread_safety_annotations_not_enabled.cpp test/libcxx/thread/thread.mutex/thread_safety_call_requires_capability_without_having.fail.cpp test/libcxx/thread/thread.mutex/thread_safety_lock_guard.cpp test/libcxx/thread/thread.mutex/thread_safety_lock_unlock.cpp test/libcxx/thread/thread.mutex/thread_safety_missing_unlock.fail.cpp test/libcxx/thread/thread.mutex/thread_safety_requires_capability.cpp Index: test/libcxx/thread/thread.mutex/thread_safety_requires_capability.cpp === --- /dev/null +++ test/libcxx/thread/thread.mutex/thread_safety_requires_capability.cpp @@ -0,0 +1,22 @@ +#if !defined(__clang__) || !__has_attribute(acquire_capability) +// This test is only meaningful on versions of clang that understand thread +// safety annotations. + +#define _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS + +#include + +std::mutex m; +int foo __attribute__((guarded_by(m))); + +void increment() __attribute__((requires_capability(m))) { + foo++; +} + +int main() { + m.lock(); + increment(); + m.unlock(); +} + +#endif Index: test/libcxx/thread/thread.mutex/thread_safety_missing_unlock.fail.cpp === --- /dev/null +++ test/libcxx/thread/thread.mutex/thread_safety_missing_unlock.fail.cpp @@ -0,0 +1,15 @@ +#if !defined(__clang__) || !__has_attribute(acquire_capability) +// This test is only meaningful on versions of clang that understand thread +// safety annotations. +#error Test only supported on clang versions that support the acquire_capability annotation +#endif + +#define _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS + +#include + +std::mutex m; + +int main() { + m.lock(); +} // expected-error {{mutex 'm' is still held at the end of function}} Index: test/libcxx/thread/thread.mutex/thread_safety_lock_unlock.cpp === --- /dev/null +++ test/libcxx/thread/thread.mutex/thread_safety_lock_unlock.cpp @@ -0,0 +1,18 @@ +#if !defined(__clang__) || !__has_attribute(acquire_capability) +// This test is only meaningful on versions of clang that understand thread +// safety annotations. + +#define _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS + +#include + +std::mutex m; +int foo __attribute__((guarded_by(m))); + +int main() { + m.lock(); + foo++; + m.unlock(); +} + +#endif Index: test/libcxx/thread/thread.mutex/thread_safety_lock_guard.cpp === --- /dev/null +++ test/libcxx/thread/thread.mutex/thread_safety_lock_guard.cpp @@ -0,0 +1,17 @@ +#if !defined(__clang__) || !__has_attribute(acquire_capability) +// This test is only meaningful on versions of clang that understand thread +// safety annotations. + +#define _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS + +#include + +std::mutex m; +int foo __attribute__((guarded_by(m))); + +int main() { + std::lock_guard lock(m); + foo++; +} + +#endif Index: test/libcxx/thread/thread.mutex/thread_safety_call_requires_capability_without_having.fail.cpp === --- /dev/null +++ test/libcxx/thread/thread.mutex/thread_safety_call_requires_capability_without_having.fail.cpp @@ -0,0 +1,20 @@ +#if !defined(__clang__) || !__has_attribute(acquire_capability) +// This test is only meaningful on versions of clang that understand thread +// safety annotations. +#error Test only supported on clang versions that support the acquire_capability annotation +#endif + +#define _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS + +#include + +std::mutex m; +int foo __attribute__((guarded_by(m))); + +void increment() __attribute__((requires_capability(m))) { + foo++; +} + +int main() { + increment(); // expected-error{{calling function 'increment' requires holding mutex 'm' exclusively}} +} Index: test/libcxx/thread/thread.mutex/thread_safety_annotations_not_enabled.cpp === --- /dev/null +++ test/libcxx/thread/thread.mutex/thread_safety_annotations_not_enabled.cpp @@ -0,0 +1,
Re: [PATCH] D14731: [libcxx] Add clang thread safety annotations to mutex and lock_guard
jamesr marked 5 inline comments as done. jamesr added a comment. Thank you for the comments, new patch coming.. (is there a way to post comments and upload a new patch at the same time?) http://reviews.llvm.org/D14731 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D14731: [libcxx] Add clang thread safety annotations to mutex and lock_guard
jamesr updated this revision to Diff 50788. http://reviews.llvm.org/D14731 Files: include/__config include/__mutex_base test/libcxx/test/format.py test/libcxx/thread/thread.mutex/thread_safety_annotations_not_enabled.pass.cpp test/libcxx/thread/thread.mutex/thread_safety_lock_guard.pass.cpp test/libcxx/thread/thread.mutex/thread_safety_lock_unlock.pass.cpp test/libcxx/thread/thread.mutex/thread_safety_missing_unlock.fail.cpp test/libcxx/thread/thread.mutex/thread_safety_requires_capability.pass.cpp Index: test/libcxx/thread/thread.mutex/thread_safety_requires_capability.pass.cpp === --- /dev/null +++ test/libcxx/thread/thread.mutex/thread_safety_requires_capability.pass.cpp @@ -0,0 +1,26 @@ +#if !defined(__clang__) || !__has_attribute(acquire_capability) +// This test is only meaningful on versions of clang that understand thread +// safety annotations. + +#define _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS + +#include + +std::mutex m; +int foo __attribute__((guarded_by(m))); + +void increment() __attribute__((requires_capability(m))) { + foo++; +} + +int main() { + m.lock(); + increment(); + m.unlock(); +} + +#else + +int main() {} + +#endif Index: test/libcxx/thread/thread.mutex/thread_safety_missing_unlock.fail.cpp === --- /dev/null +++ test/libcxx/thread/thread.mutex/thread_safety_missing_unlock.fail.cpp @@ -0,0 +1,15 @@ +#if !defined(__clang__) || !__has_attribute(acquire_capability) +// This test is only meaningful on versions of clang that understand thread +// safety annotations. +#error Test only supported on clang versions that support the acquire_capability annotation +#endif + +#define _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS + +#include + +std::mutex m; + +int main() { + m.lock(); +} // expected-error {{mutex 'm' is still held at the end of function}} Index: test/libcxx/thread/thread.mutex/thread_safety_lock_unlock.pass.cpp === --- /dev/null +++ test/libcxx/thread/thread.mutex/thread_safety_lock_unlock.pass.cpp @@ -0,0 +1,22 @@ +#if !defined(__clang__) || !__has_attribute(acquire_capability) +// This test is only meaningful on versions of clang that understand thread +// safety annotations. + +#define _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS + +#include + +std::mutex m; +int foo __attribute__((guarded_by(m))); + +int main() { + m.lock(); + foo++; + m.unlock(); +} + +#else + +int main() {} + +#endif Index: test/libcxx/thread/thread.mutex/thread_safety_lock_guard.pass.cpp === --- /dev/null +++ test/libcxx/thread/thread.mutex/thread_safety_lock_guard.pass.cpp @@ -0,0 +1,21 @@ +#if !defined(__clang__) || !__has_attribute(acquire_capability) +// This test is only meaningful on versions of clang that understand thread +// safety annotations. + +#define _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS + +#include + +std::mutex m; +int foo __attribute__((guarded_by(m))); + +int main() { + std::lock_guard lock(m); + foo++; +} + +#else + +int main() {} + +#endif Index: test/libcxx/thread/thread.mutex/thread_safety_annotations_not_enabled.pass.cpp === --- /dev/null +++ test/libcxx/thread/thread.mutex/thread_safety_annotations_not_enabled.pass.cpp @@ -0,0 +1,13 @@ +// This test does not define _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS so it +// should compile without any warnings or errors even though this pattern is not +// understood by the thread safety annotations. + +#include + +int main() { + std::mutex m; + m.lock(); + { +std::unique_lock g(m, std::adopt_lock); + } +} Index: test/libcxx/test/format.py === --- test/libcxx/test/format.py +++ test/libcxx/test/format.py @@ -167,7 +167,7 @@ # when using Clang. extra_flags = [] if self.cxx.type != 'gcc': -extra_flags += ['-fsyntax-only'] +extra_flags += ['-fsyntax-only', '-Werror=thread-safety'] if use_verify: extra_flags += ['-Xclang', '-verify', '-Xclang', '-verify-ignore-unexpected=note'] Index: include/__mutex_base === --- include/__mutex_base +++ include/__mutex_base @@ -26,7 +26,15 @@ #ifndef _LIBCPP_HAS_NO_THREADS -class _LIBCPP_TYPE_VIS mutex +#ifndef _LIBCPP_THREAD_SAFETY_ANNOTATION +# ifdef _LIBCPP_HAS_THREAD_SAFETY_ANNOTATIONS +#define _LIBCPP_THREAD_SAFETY_ANNOTATION(x) __attribute__((x)) +# else +#define _LIBCPP_THREAD_SAFETY_ANNOTATION(x) +# endif +#endif // _LIBCPP_THREAD_SAFETY_ANNOTATION + +class _LIBCPP_TYPE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(capability("mutex")) mutex { pthread_mutex_t __m_; @@ -44,9 +52,9 @@ mutex& operator=(const mut
Re: [PATCH] D14731: [libcxx] Add clang thread safety annotations to mutex and lock_guard
jamesr added a comment. In http://reviews.llvm.org/D14731#376128, @EricWF wrote: > So I fixed up LIT so that it also adds "-Werror=thread-safety" for both > ".pass.cpp" and ".fail.cpp" tests. Could you apply it to your patch? > https://gist.github.com/EricWF/8a0bfb6ff02f8c9f9940 Cool! Applied and confirmed that it's set for both. Comment at: include/__mutex_base:37 @@ -30,1 +36,3 @@ + +class _LIBCPP_TYPE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(capability("mutex")) mutex { EricWF wrote: > Does `capability` have a alternative keyword that's a reserved name? ie > `__capability__`? If so we should use that instead. If I'm reading https://github.com/llvm-mirror/clang/blob/master/include/clang/Basic/Attr.td#L1657 correctly: def Capability : InheritableAttr { let Spellings = [GNU<"capability">, CXX11<"clang", "capability">, GNU<"shared_capability">, CXX11<"clang", "shared_capability">]; then the answer is unfortunately "no" http://reviews.llvm.org/D14731 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D14731: [libcxx] Add clang thread safety annotations to mutex and lock_guard
jamesr updated this revision to Diff 50790. http://reviews.llvm.org/D14731 Files: include/__config include/__mutex_base test/libcxx/test/config.py test/libcxx/thread/thread.mutex/thread_safety_annotations_not_enabled.pass.cpp test/libcxx/thread/thread.mutex/thread_safety_lock_guard.pass.cpp test/libcxx/thread/thread.mutex/thread_safety_lock_unlock.pass.cpp test/libcxx/thread/thread.mutex/thread_safety_missing_unlock.fail.cpp test/libcxx/thread/thread.mutex/thread_safety_requires_capability.pass.cpp Index: test/libcxx/thread/thread.mutex/thread_safety_requires_capability.pass.cpp === --- /dev/null +++ test/libcxx/thread/thread.mutex/thread_safety_requires_capability.pass.cpp @@ -0,0 +1,26 @@ +#if !defined(__clang__) || !__has_attribute(acquire_capability) +// This test is only meaningful on versions of clang that understand thread +// safety annotations. + +#define _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS + +#include + +std::mutex m; +int foo __attribute__((guarded_by(m))); + +void increment() __attribute__((requires_capability(m))) { + foo++; +} + +int main() { + m.lock(); + increment(); + m.unlock(); +} + +#else + +int main() {} + +#endif Index: test/libcxx/thread/thread.mutex/thread_safety_missing_unlock.fail.cpp === --- /dev/null +++ test/libcxx/thread/thread.mutex/thread_safety_missing_unlock.fail.cpp @@ -0,0 +1,15 @@ +#if !defined(__clang__) || !__has_attribute(acquire_capability) +// This test is only meaningful on versions of clang that understand thread +// safety annotations. +#error Test only supported on clang versions that support the acquire_capability annotation +#endif + +#define _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS + +#include + +std::mutex m; + +int main() { + m.lock(); +} // expected-error {{mutex 'm' is still held at the end of function}} Index: test/libcxx/thread/thread.mutex/thread_safety_lock_unlock.pass.cpp === --- /dev/null +++ test/libcxx/thread/thread.mutex/thread_safety_lock_unlock.pass.cpp @@ -0,0 +1,22 @@ +#if !defined(__clang__) || !__has_attribute(acquire_capability) +// This test is only meaningful on versions of clang that understand thread +// safety annotations. + +#define _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS + +#include + +std::mutex m; +int foo __attribute__((guarded_by(m))); + +int main() { + m.lock(); + foo++; + m.unlock(); +} + +#else + +int main() {} + +#endif Index: test/libcxx/thread/thread.mutex/thread_safety_lock_guard.pass.cpp === --- /dev/null +++ test/libcxx/thread/thread.mutex/thread_safety_lock_guard.pass.cpp @@ -0,0 +1,21 @@ +#if !defined(__clang__) || !__has_attribute(acquire_capability) +// This test is only meaningful on versions of clang that understand thread +// safety annotations. + +#define _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS + +#include + +std::mutex m; +int foo __attribute__((guarded_by(m))); + +int main() { + std::lock_guard lock(m); + foo++; +} + +#else + +int main() {} + +#endif Index: test/libcxx/thread/thread.mutex/thread_safety_annotations_not_enabled.pass.cpp === --- /dev/null +++ test/libcxx/thread/thread.mutex/thread_safety_annotations_not_enabled.pass.cpp @@ -0,0 +1,13 @@ +// This test does not define _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS so it +// should compile without any warnings or errors even though this pattern is not +// understood by the thread safety annotations. + +#include + +int main() { + std::mutex m; + m.lock(); + { +std::unique_lock g(m, std::adopt_lock); + } +} Index: test/libcxx/test/config.py === --- test/libcxx/test/config.py +++ test/libcxx/test/config.py @@ -98,6 +98,7 @@ self.configure_cxx_library_root() self.configure_use_system_cxx_lib() self.configure_use_clang_verify() +self.configure_use_thread_safety() self.configure_execute_external() self.configure_ccache() self.configure_compile_flags() @@ -218,6 +219,14 @@ self.lit_config.note( "inferred use_clang_verify as: %r" % self.use_clang_verify) +def configure_use_thread_safety(self): +'''If set, run clang with -verify on failing tests.''' +has_thread_safety = self.cxx.hasCompileFlag('-Werror=thread-safety') +if has_thread_safety: +self.cxx.compile_flags += ['-Werror=thread-safety'] +self.config.available_features.add('thread-safety') +self.lit_config.note("enabling thread-safety annotations") + def configure_execute_external(self): # Choose between lit's internal shell pipeline runner and a real shell. # If LIT_USE_INTERNAL_SHELL is in the environmen
Re: [PATCH] D14731: [libcxx] Add clang thread safety annotations to mutex and lock_guard
jamesr added a comment. In http://reviews.llvm.org/D14731#376138, @EricWF wrote: > So this LGTM except for one last change (I'm sorry). LIT now knows when > "-Werror=thread-safety" is being passed. Could you change the tests guarded > by "#if !defined(__clang__) || !__has_attribute(aquire_capability)` to say > "// REQUIRES: thread-safety" instead? I prefer using LIT to manage when tests > run because it can report un-run tests where simply using macros cant. > > After that LGTM. If I do that, does that mean I can omit the extra main()s, etc, and the LIT harness will avoid attempting the test at all when the feature bit is set? http://reviews.llvm.org/D14731 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D14731: [libcxx] Add clang thread safety annotations to mutex and lock_guard
jamesr updated this revision to Diff 50791. jamesr added a comment. Use // REQUIRES: thread-safety instead of macros to feature guard tests http://reviews.llvm.org/D14731 Files: include/__config include/__mutex_base test/libcxx/test/config.py test/libcxx/thread/thread.mutex/thread_safety_annotations_not_enabled.pass.cpp test/libcxx/thread/thread.mutex/thread_safety_lock_guard.pass.cpp test/libcxx/thread/thread.mutex/thread_safety_lock_unlock.pass.cpp test/libcxx/thread/thread.mutex/thread_safety_missing_unlock.fail.cpp test/libcxx/thread/thread.mutex/thread_safety_requires_capability.pass.cpp Index: test/libcxx/thread/thread.mutex/thread_safety_requires_capability.pass.cpp === --- /dev/null +++ test/libcxx/thread/thread.mutex/thread_safety_requires_capability.pass.cpp @@ -0,0 +1,18 @@ +// REQUIRES: thread-safety + +#define _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS + +#include + +std::mutex m; +int foo __attribute__((guarded_by(m))); + +void increment() __attribute__((requires_capability(m))) { + foo++; +} + +int main() { + m.lock(); + increment(); + m.unlock(); +} Index: test/libcxx/thread/thread.mutex/thread_safety_missing_unlock.fail.cpp === --- /dev/null +++ test/libcxx/thread/thread.mutex/thread_safety_missing_unlock.fail.cpp @@ -0,0 +1,11 @@ +// REQUIRES: thread-safety + +#define _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS + +#include + +std::mutex m; + +int main() { + m.lock(); +} // expected-error {{mutex 'm' is still held at the end of function}} Index: test/libcxx/thread/thread.mutex/thread_safety_lock_unlock.pass.cpp === --- /dev/null +++ test/libcxx/thread/thread.mutex/thread_safety_lock_unlock.pass.cpp @@ -0,0 +1,14 @@ +// REQUIRES: thread-safety + +#define _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS + +#include + +std::mutex m; +int foo __attribute__((guarded_by(m))); + +int main() { + m.lock(); + foo++; + m.unlock(); +} Index: test/libcxx/thread/thread.mutex/thread_safety_lock_guard.pass.cpp === --- /dev/null +++ test/libcxx/thread/thread.mutex/thread_safety_lock_guard.pass.cpp @@ -0,0 +1,13 @@ +// REQUIRES: thread-safety + +#define _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS + +#include + +std::mutex m; +int foo __attribute__((guarded_by(m))); + +int main() { + std::lock_guard lock(m); + foo++; +} Index: test/libcxx/thread/thread.mutex/thread_safety_annotations_not_enabled.pass.cpp === --- /dev/null +++ test/libcxx/thread/thread.mutex/thread_safety_annotations_not_enabled.pass.cpp @@ -0,0 +1,13 @@ +// This test does not define _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS so it +// should compile without any warnings or errors even though this pattern is not +// understood by the thread safety annotations. + +#include + +int main() { + std::mutex m; + m.lock(); + { +std::unique_lock g(m, std::adopt_lock); + } +} Index: test/libcxx/test/config.py === --- test/libcxx/test/config.py +++ test/libcxx/test/config.py @@ -98,6 +98,7 @@ self.configure_cxx_library_root() self.configure_use_system_cxx_lib() self.configure_use_clang_verify() +self.configure_use_thread_safety() self.configure_execute_external() self.configure_ccache() self.configure_compile_flags() @@ -218,6 +219,14 @@ self.lit_config.note( "inferred use_clang_verify as: %r" % self.use_clang_verify) +def configure_use_thread_safety(self): +'''If set, run clang with -verify on failing tests.''' +has_thread_safety = self.cxx.hasCompileFlag('-Werror=thread-safety') +if has_thread_safety: +self.cxx.compile_flags += ['-Werror=thread-safety'] +self.config.available_features.add('thread-safety') +self.lit_config.note("enabling thread-safety annotations") + def configure_execute_external(self): # Choose between lit's internal shell pipeline runner and a real shell. # If LIT_USE_INTERNAL_SHELL is in the environment, we use that as the Index: include/__mutex_base === --- include/__mutex_base +++ include/__mutex_base @@ -26,7 +26,15 @@ #ifndef _LIBCPP_HAS_NO_THREADS -class _LIBCPP_TYPE_VIS mutex +#ifndef _LIBCPP_THREAD_SAFETY_ANNOTATION +# ifdef _LIBCPP_HAS_THREAD_SAFETY_ANNOTATIONS +#define _LIBCPP_THREAD_SAFETY_ANNOTATION(x) __attribute__((x)) +# else +#define _LIBCPP_THREAD_SAFETY_ANNOTATION(x) +# endif +#endif // _LIBCPP_THREAD_SAFETY_ANNOTATION + +class _LIBCPP_TYPE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(capability("mutex")) mutex { pthread_mutex_t __m_; @@ -44,9 +52,9 @@
Re: [PATCH] D14731: [libcxx] Add clang thread safety annotations to mutex and lock_guard
jamesr updated this revision to Diff 50793. jamesr added a comment. Add LLVM license headers to new test files http://reviews.llvm.org/D14731 Files: include/__config include/__mutex_base test/libcxx/test/config.py test/libcxx/thread/thread.mutex/thread_safety_annotations_not_enabled.pass.cpp test/libcxx/thread/thread.mutex/thread_safety_lock_guard.pass.cpp test/libcxx/thread/thread.mutex/thread_safety_lock_unlock.pass.cpp test/libcxx/thread/thread.mutex/thread_safety_missing_unlock.fail.cpp test/libcxx/thread/thread.mutex/thread_safety_requires_capability.pass.cpp Index: test/libcxx/thread/thread.mutex/thread_safety_requires_capability.pass.cpp === --- /dev/null +++ test/libcxx/thread/thread.mutex/thread_safety_requires_capability.pass.cpp @@ -0,0 +1,29 @@ +//===--===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===--===// + +// REQUIRES: thread-safety + +// + +#define _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS + +#include + +std::mutex m; +int foo __attribute__((guarded_by(m))); + +void increment() __attribute__((requires_capability(m))) { + foo++; +} + +int main() { + m.lock(); + increment(); + m.unlock(); +} Index: test/libcxx/thread/thread.mutex/thread_safety_missing_unlock.fail.cpp === --- /dev/null +++ test/libcxx/thread/thread.mutex/thread_safety_missing_unlock.fail.cpp @@ -0,0 +1,22 @@ +//===--===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===--===// + +// REQUIRES: thread-safety + +// + +#define _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS + +#include + +std::mutex m; + +int main() { + m.lock(); +} // expected-error {{mutex 'm' is still held at the end of function}} Index: test/libcxx/thread/thread.mutex/thread_safety_lock_unlock.pass.cpp === --- /dev/null +++ test/libcxx/thread/thread.mutex/thread_safety_lock_unlock.pass.cpp @@ -0,0 +1,25 @@ +//===--===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===--===// + +// REQUIRES: thread-safety + +// + +#define _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS + +#include + +std::mutex m; +int foo __attribute__((guarded_by(m))); + +int main() { + m.lock(); + foo++; + m.unlock(); +} Index: test/libcxx/thread/thread.mutex/thread_safety_lock_guard.pass.cpp === --- /dev/null +++ test/libcxx/thread/thread.mutex/thread_safety_lock_guard.pass.cpp @@ -0,0 +1,24 @@ +//===--===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===--===// + +// REQUIRES: thread-safety + +// + +#define _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS + +#include + +std::mutex m; +int foo __attribute__((guarded_by(m))); + +int main() { + std::lock_guard lock(m); + foo++; +} Index: test/libcxx/thread/thread.mutex/thread_safety_annotations_not_enabled.pass.cpp === --- /dev/null +++ test/libcxx/thread/thread.mutex/thread_safety_annotations_not_enabled.pass.cpp @@ -0,0 +1,24 @@ +//===--===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===--===// + +// + +// This test does not define _LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS so it +// should compile without any warnings or errors even though this pattern is not +// understood by the thread safety annotations. + +#include + +int main() { + std::mutex m; + m.lock(); + { +std::unique_lock g(m, std::adopt_lock); + } +} Index: test/libcxx/test/config.py ===
Re: [PATCH] D18347: [PATCH] Fix thread_annotation negtest for thread safety.
jamesr added a comment. In http://reviews.llvm.org/D18347#380792, @EricWF wrote: > And looking at the current state of the single-threaded test suite this isn't > the only test that needs this fix applied. > > http://lab.llvm.org:8011/builders/libcxx-libcxxabi-singlethreaded-x86_64-linux-debian/builds/869 Indeed! I assumed by reading other nearby tests that there was some mechanism that disabled the thread/ tests when threads were disabled, but didn't verify this. Sorry about the breakage. http://reviews.llvm.org/D18347 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D14731: [libcxx] Add clang thread safety annotations to mutex and lock_guard
jamesr created this revision. jamesr added a subscriber: cfe-commits. This adds clang thread safety annotations to std::mutex and std::lock_guard so code using these types can use these types directly instead of having to wrap the types to provide annotations. These checks when enabled by -Wthread-safety provide simple but useful static checking to detect potential race conditions. See http://clang.llvm.org/docs/ThreadSafetyAnalysis.html for details. http://reviews.llvm.org/D14731 Files: include/__config include/__mutex_base Index: include/__mutex_base === --- include/__mutex_base +++ include/__mutex_base @@ -26,7 +26,7 @@ #ifndef _LIBCPP_HAS_NO_THREADS -class _LIBCPP_TYPE_VIS mutex +class _LIBCPP_TYPE_VIS _LIBCPP_THREAD_ANNOTATION(capability("mutex")) mutex { pthread_mutex_t __m_; @@ -44,9 +44,9 @@ mutex& operator=(const mutex&);// = delete; public: -void lock(); -bool try_lock() _NOEXCEPT; -void unlock() _NOEXCEPT; +void lock() _LIBCPP_THREAD_ANNOTATION(acquire_capability()); +bool try_lock() _NOEXCEPT _LIBCPP_THREAD_ANNOTATION(try_acquire_capability(true)); +void unlock() _NOEXCEPT _LIBCPP_THREAD_ANNOTATION(release_capability()); typedef pthread_mutex_t* native_handle_type; _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__m_;} @@ -71,7 +71,7 @@ #endif template -class _LIBCPP_TYPE_VIS_ONLY lock_guard +class _LIBCPP_TYPE_VIS_ONLY _LIBCPP_THREAD_ANNOTATION(scoped_lockable) lock_guard { public: typedef _Mutex mutex_type; @@ -81,13 +81,13 @@ public: _LIBCPP_INLINE_VISIBILITY -explicit lock_guard(mutex_type& __m) +explicit lock_guard(mutex_type& __m) _LIBCPP_THREAD_ANNOTATION(acquire_capability(__m)) : __m_(__m) {__m_.lock();} _LIBCPP_INLINE_VISIBILITY -lock_guard(mutex_type& __m, adopt_lock_t) +lock_guard(mutex_type& __m, adopt_lock_t) _LIBCPP_THREAD_ANNOTATION(requires_capability(__m)) : __m_(__m) {} _LIBCPP_INLINE_VISIBILITY -~lock_guard() {__m_.unlock();} +~lock_guard() _LIBCPP_THREAD_ANNOTATION(release_capability()) {__m_.unlock();} private: lock_guard(lock_guard const&);// = delete; Index: include/__config === --- include/__config +++ include/__config @@ -825,6 +825,12 @@ #define _LIBCPP_HAS_NO_ATOMIC_HEADER #endif +#if defined(__clang__) +#define _LIBCPP_THREAD_ANNOTATION(x) __attribute__((x)) +#else +#define _LIBCPP_THREAD_ANNOTATION(x) +#endif + #endif // __cplusplus #endif // _LIBCPP_CONFIG Index: include/__mutex_base === --- include/__mutex_base +++ include/__mutex_base @@ -26,7 +26,7 @@ #ifndef _LIBCPP_HAS_NO_THREADS -class _LIBCPP_TYPE_VIS mutex +class _LIBCPP_TYPE_VIS _LIBCPP_THREAD_ANNOTATION(capability("mutex")) mutex { pthread_mutex_t __m_; @@ -44,9 +44,9 @@ mutex& operator=(const mutex&);// = delete; public: -void lock(); -bool try_lock() _NOEXCEPT; -void unlock() _NOEXCEPT; +void lock() _LIBCPP_THREAD_ANNOTATION(acquire_capability()); +bool try_lock() _NOEXCEPT _LIBCPP_THREAD_ANNOTATION(try_acquire_capability(true)); +void unlock() _NOEXCEPT _LIBCPP_THREAD_ANNOTATION(release_capability()); typedef pthread_mutex_t* native_handle_type; _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__m_;} @@ -71,7 +71,7 @@ #endif template -class _LIBCPP_TYPE_VIS_ONLY lock_guard +class _LIBCPP_TYPE_VIS_ONLY _LIBCPP_THREAD_ANNOTATION(scoped_lockable) lock_guard { public: typedef _Mutex mutex_type; @@ -81,13 +81,13 @@ public: _LIBCPP_INLINE_VISIBILITY -explicit lock_guard(mutex_type& __m) +explicit lock_guard(mutex_type& __m) _LIBCPP_THREAD_ANNOTATION(acquire_capability(__m)) : __m_(__m) {__m_.lock();} _LIBCPP_INLINE_VISIBILITY -lock_guard(mutex_type& __m, adopt_lock_t) +lock_guard(mutex_type& __m, adopt_lock_t) _LIBCPP_THREAD_ANNOTATION(requires_capability(__m)) : __m_(__m) {} _LIBCPP_INLINE_VISIBILITY -~lock_guard() {__m_.unlock();} +~lock_guard() _LIBCPP_THREAD_ANNOTATION(release_capability()) {__m_.unlock();} private: lock_guard(lock_guard const&);// = delete; Index: include/__config === --- include/__config +++ include/__config @@ -825,6 +825,12 @@ #define _LIBCPP_HAS_NO_ATOMIC_HEADER #endif +#if defined(__clang__) +#define _LIBCPP_THREAD_ANNOTATION(x) __attribute__((x)) +#else +#define _LIBCPP_THREAD_ANNOTATION(x) +#endif + #endif // __cplusplus #endif // _LIBCPP_CONFIG ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D14731: [libcxx] Add clang thread safety annotations to mutex and lock_guard
jamesr updated this revision to Diff 41581. jamesr added a comment. Updates the macros to avoid defining anything if _LIBCPP_THREAD_ANNOTATION is already defined and to define _LIBCPP_THREAD_ANNOTATION to nothing if __clang__ is not set, __has_attribute(acquire_capability) is not set, or _LIBCPP_HAS_NO_THREAD_ANNOTATIONS is set. It turns out there's not a clean feature guard for the thread safety annotations (i.e. no __has_feature() guard). The annotations were added over time to clang. I'm not sure at which point the feature was considered stable enough for general use. Looking at clang's history the most recently added annotation out of the ones this patch uses is acquire_capability which was added in this commit: https://llvm.org/svn/llvm-project/cfe/trunk@201890, so I'm testing for that annotation to test for support for the feature as a whole. It's quite possible that there are revisions of clang after the annotation support was added that contain bugs that make the annotations not very useful but the fix for any users trying to use such versions of clang is easy - just avoid passing -Wthread-safety to these versions of clang. http://reviews.llvm.org/D14731 Files: include/__config include/__mutex_base Index: include/__mutex_base === --- include/__mutex_base +++ include/__mutex_base @@ -26,7 +26,15 @@ #ifndef _LIBCPP_HAS_NO_THREADS -class _LIBCPP_TYPE_VIS mutex +#ifndef _LIBCPP_THREAD_ANNOTATION +# ifndef _LIBCPP_HAS_NO_THREAD_ANNOTATIONS +#define _LIBCPP_THREAD_ANNOTATION(x) __attribute__((x)) +# else +#define _LIBCPP_THREAD_ANNOTATION(x) +# endif +#endif // _LIBCPP_THREAD_ANNOTATION + +class _LIBCPP_TYPE_VIS _LIBCPP_THREAD_ANNOTATION(capability("mutex")) mutex { pthread_mutex_t __m_; @@ -44,9 +52,9 @@ mutex& operator=(const mutex&);// = delete; public: -void lock(); -bool try_lock() _NOEXCEPT; -void unlock() _NOEXCEPT; +void lock() _LIBCPP_THREAD_ANNOTATION(acquire_capability()); +bool try_lock() _NOEXCEPT _LIBCPP_THREAD_ANNOTATION(try_acquire_capability(true)); +void unlock() _NOEXCEPT _LIBCPP_THREAD_ANNOTATION(release_capability()); typedef pthread_mutex_t* native_handle_type; _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__m_;} @@ -71,7 +79,7 @@ #endif template -class _LIBCPP_TYPE_VIS_ONLY lock_guard +class _LIBCPP_TYPE_VIS_ONLY _LIBCPP_THREAD_ANNOTATION(scoped_lockable) lock_guard { public: typedef _Mutex mutex_type; @@ -81,13 +89,13 @@ public: _LIBCPP_INLINE_VISIBILITY -explicit lock_guard(mutex_type& __m) +explicit lock_guard(mutex_type& __m) _LIBCPP_THREAD_ANNOTATION(acquire_capability(__m)) : __m_(__m) {__m_.lock();} _LIBCPP_INLINE_VISIBILITY -lock_guard(mutex_type& __m, adopt_lock_t) +lock_guard(mutex_type& __m, adopt_lock_t) _LIBCPP_THREAD_ANNOTATION(requires_capability(__m)) : __m_(__m) {} _LIBCPP_INLINE_VISIBILITY -~lock_guard() {__m_.unlock();} +~lock_guard() _LIBCPP_THREAD_ANNOTATION(release_capability()) {__m_.unlock();} private: lock_guard(lock_guard const&);// = delete; Index: include/__config === --- include/__config +++ include/__config @@ -825,6 +825,11 @@ #define _LIBCPP_HAS_NO_ATOMIC_HEADER #endif +#if (!defined(_LIBCPP_HAS_NO_THREAD_ANNOTATIONS) && (!defined(__clang__) \ + || !__has_attribute(acquire_capability))) +#define _LIBCPP_HAS_NO_THREAD_ANNOTATIONS +#endif + #endif // __cplusplus #endif // _LIBCPP_CONFIG Index: include/__mutex_base === --- include/__mutex_base +++ include/__mutex_base @@ -26,7 +26,15 @@ #ifndef _LIBCPP_HAS_NO_THREADS -class _LIBCPP_TYPE_VIS mutex +#ifndef _LIBCPP_THREAD_ANNOTATION +# ifndef _LIBCPP_HAS_NO_THREAD_ANNOTATIONS +#define _LIBCPP_THREAD_ANNOTATION(x) __attribute__((x)) +# else +#define _LIBCPP_THREAD_ANNOTATION(x) +# endif +#endif // _LIBCPP_THREAD_ANNOTATION + +class _LIBCPP_TYPE_VIS _LIBCPP_THREAD_ANNOTATION(capability("mutex")) mutex { pthread_mutex_t __m_; @@ -44,9 +52,9 @@ mutex& operator=(const mutex&);// = delete; public: -void lock(); -bool try_lock() _NOEXCEPT; -void unlock() _NOEXCEPT; +void lock() _LIBCPP_THREAD_ANNOTATION(acquire_capability()); +bool try_lock() _NOEXCEPT _LIBCPP_THREAD_ANNOTATION(try_acquire_capability(true)); +void unlock() _NOEXCEPT _LIBCPP_THREAD_ANNOTATION(release_capability()); typedef pthread_mutex_t* native_handle_type; _LIBCPP_INLINE_VISIBILITY native_handle_type native_handle() {return &__m_;} @@ -71,7 +79,7 @@ #endif template -class _LIBCPP_TYPE_VIS_ONLY lock_guard +class _LIBCPP_TYPE_VIS_ONLY _LIBCPP_THREAD_ANNOTATION(scoped_lockable) lock_guard { public: typedef _Mutex mutex_type; @@ -81,13 +89,13 @@ public: _
Re: [PATCH] D14731: [libcxx] Add clang thread safety annotations to mutex and lock_guard
jamesr added a comment. In http://reviews.llvm.org/D14731#299152, @mclow.lists wrote: > Where are the tests? There aren't any yet. I investigated a few avenues for testing but none seem very useful. The most obvious testing strategy would be to write some code that fails the -Wthread-safety checks such as std::mutex m; m.lock(); m.lock(); and verify that this generates the expected warning. There's a harness for expected warnings that does this in the clang repo but no such harness exists in libcxx. Depending on the text of warnings from clang in libcxx tests seems like a layering violation, anyway. Another check would be to test that such code fails to compile with -Wthread-safety -Werror set. libcxx's test suite does support negative compilation tests but I can't find any way to specify that particular tests should be compiled with particular flags. I tried enabling -Wthread-safety for all tests, but other tests fail because they do things that the annotations do not understand (deliberately, the annotations are for static checking not dynamic code analysis). I could add suppressions to all of these tests but that seems backwards. This also hits the problem that such annotations would only have meaning for new-enough versions of clang and there's no way for the driver to cleanly tell if the cxx being used supports the annotations or not. The annotations are (by design) not supposed to have an influence on the program other than generating warnings in non-default configs so there isn't any other testing hook I can think of. http://reviews.llvm.org/D14731 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D14731: [libcxx] Add clang thread safety annotations to mutex and lock_guard
jamesr added a subscriber: aaron.ballman. jamesr added a comment. It looks like Aaron Ballman was involved with adding parsing for these attributes in clang - perhaps he has an idea of a better way to detect these than __has_attribute(acquire_capability). http://reviews.llvm.org/D14731 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D14731: [libcxx] Add clang thread safety annotations to mutex and lock_guard
jamesr added a comment. Marshall - friendly ping. If you know a way to test functionality guarded by a compile-time flag in the libcxx test suite I'd be happy to wire in tests for this, but if that doesn't exist (and I think it does not currently) then I think the only way to verify this is by inspection. Let me know what you'd prefer when you get a chance. Thanks! http://reviews.llvm.org/D14731 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits