<div dir="ltr">Hey David,<div><br></div><div>Thanks for your reply, please correct me if my understanding is wrong,</div><div><br></div><div>Since I only use the thread safety attributes defined in clang, there should be no requirement on gcc extension.</div>
<div><br></div><div>Actually, I think it does not make very much sense to check<span style="font-family:arial,sans-serif;font-size:13px"> </span><span style="font-family:arial,sans-serif;font-size:13px">for each of the attributes individually, since we only use these attributes for </span><font face="arial, sans-serif">semantic analysis and your cpp test (warn-thread-safety-analysis.cpp</font><span style="font-family:arial,sans-serif">) is every detailed.</span></div>
<div><br></div><div>Kind Regards,</div><div>Alex Wang,</div></div><div class="gmail_extra"><br><br><div class="gmail_quote">On Thu, Jul 25, 2013 at 4:31 AM, David Chisnall <span dir="ltr"><<a href="mailto:David.Chisnall@cl.cam.ac.uk" target="_blank">David.Chisnall@cl.cam.ac.uk</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi,<br>
<br>
What is the __has_extension() variable to check for support for these? Or do we need to check for each of the attributes individually?<br>
<br>
David<br>
<div><div class="h5"><br>
On 25 Jul 2013, at 02:16, Alex Wang <<a href="mailto:alexw@nicira.com">alexw@nicira.com</a>> wrote:<br>
<br>
> This commit adds test to the -Wthread-safety check for C code.<br>
><br>
> Co-authored-by: Ethan Jackson <<a href="mailto:ethan@nicira.com">ethan@nicira.com</a>><br>
> Signed-off-by: Alex Wang <<a href="mailto:alexw@nicira.com">alexw@nicira.com</a>><br>
><br>
> Index: warn-thread-safety-analysis.c<br>
> ===================================================================<br>
> --- warn-thread-safety-analysis.c (revision 0)<br>
> +++ warn-thread-safety-analysis.c (revision 0)<br>
> @@ -0,0 +1,132 @@<br>
> +// RUN: %clang -fsyntax-only -verify -Wthread-safety -Wthread-safety-beta -fcxx-exceptions %s<br>
> +<br>
> +#include <assert.h><br>
> +<br>
> +#define LOCKABLE __attribute__ ((lockable))<br>
> +#define SCOPED_LOCKABLE __attribute__ ((scoped_lockable))<br>
> +#define GUARDED_BY(x) __attribute__ ((guarded_by(x)))<br>
> +#define GUARDED_VAR __attribute__ ((guarded_var))<br>
> +#define PT_GUARDED_BY(x) __attribute__ ((pt_guarded_by(x)))<br>
> +#define PT_GUARDED_VAR __attribute__ ((pt_guarded_var))<br>
> +#define ACQUIRED_AFTER(...) __attribute__ ((acquired_after(__VA_ARGS__)))<br>
> +#define ACQUIRED_BEFORE(...) __attribute__ ((acquired_before(__VA_ARGS__)))<br>
> +#define EXCLUSIVE_LOCK_FUNCTION(...) __attribute__ ((exclusive_lock_function(__VA_ARGS__)))<br>
> +#define SHARED_LOCK_FUNCTION(...) __attribute__ ((shared_lock_function(__VA_ARGS__)))<br>
> +#define ASSERT_EXCLUSIVE_LOCK(...) __attribute__ ((assert_exclusive_lock(__VA_ARGS__)))<br>
> +#define ASSERT_SHARED_LOCK(...) __attribute__ ((assert_shared_lock(__VA_ARGS__)))<br>
> +#define EXCLUSIVE_TRYLOCK_FUNCTION(...) __attribute__ ((exclusive_trylock_function(__VA_ARGS__)))<br>
> +#define SHARED_TRYLOCK_FUNCTION(...) __attribute__ ((shared_trylock_function(__VA_ARGS__)))<br>
> +#define UNLOCK_FUNCTION(...) __attribute__ ((unlock_function(__VA_ARGS__)))<br>
> +#define LOCK_RETURNED(x) __attribute__ ((lock_returned(x)))<br>
> +#define LOCKS_EXCLUDED(...) __attribute__ ((locks_excluded(__VA_ARGS__)))<br>
> +#define EXCLUSIVE_LOCKS_REQUIRED(...) \<br>
> + __attribute__ ((exclusive_locks_required(__VA_ARGS__)))<br>
> +#define SHARED_LOCKS_REQUIRED(...) \<br>
> + __attribute__ ((shared_locks_required(__VA_ARGS__)))<br>
> +#define NO_THREAD_SAFETY_ANALYSIS __attribute__ ((no_thread_safety_analysis))<br>
> +<br>
> +// Define the mutex struct.<br>
> +// Simplified only for test purpose.<br>
> +struct LOCKABLE Mutex {};<br>
> +<br>
> +struct Foo {<br>
> + struct Mutex *mu_;<br>
> +};<br>
> +<br>
> +// Define mutex lock/unlock functions.<br>
> +void mutex_exclusive_lock(struct Mutex *mu) EXCLUSIVE_LOCK_FUNCTION(mu) {<br>
> +}<br>
> +<br>
> +void mutex_shared_lock(struct Mutex *mu) SHARED_LOCK_FUNCTION(mu) {<br>
> +}<br>
> +<br>
> +void mutex_unlock(struct Mutex *mu) UNLOCK_FUNCTION(mu) {<br>
> +}<br>
> +<br>
> +// Define global variables.<br>
> +struct Mutex mu1;<br>
> +struct Mutex mu2 ACQUIRED_AFTER(mu1);<br>
> +struct Foo foo_ = {&mu1};<br>
> +int a_ GUARDED_BY(foo_.mu_);<br>
> +int *b_ PT_GUARDED_BY(foo_.mu_) = &a_;<br>
> +int c_ GUARDED_VAR;<br>
> +int *d_ PT_GUARDED_VAR = &c_;<br>
> +<br>
> +// Define test functions.<br>
> +int Foo_fun1(int i) SHARED_LOCKS_REQUIRED(mu2) EXCLUSIVE_LOCKS_REQUIRED(mu1) {<br>
> + return i;<br>
> +}<br>
> +<br>
> +int Foo_fun2(int i) EXCLUSIVE_LOCKS_REQUIRED(mu2) SHARED_LOCKS_REQUIRED(mu1) {<br>
> + return i;<br>
> +}<br>
> +<br>
> +int Foo_func3(int i) LOCKS_EXCLUDED(mu1, mu2) {<br>
> + return i;<br>
> +}<br>
> +<br>
> +static int Bar_fun1(int i) EXCLUSIVE_LOCKS_REQUIRED(mu1) {<br>
> + return i;<br>
> +}<br>
> +<br>
> +void set_value(int *a, int value) EXCLUSIVE_LOCKS_REQUIRED(foo_.mu_) {<br>
> + *a = value;<br>
> +}<br>
> +<br>
> +int get_value(int *p) SHARED_LOCKS_REQUIRED(foo_.mu_){<br>
> + return *p;<br>
> +}<br>
> +<br>
> +int main() {<br>
> +<br>
> + Foo_fun1(1); // \<br>
> + // expected-warning{{calling function 'Foo_fun1' requires shared lock on 'mu2'}}<br>
> + // expected-warning{{calling function 'Foo_fun1' requires exclusive lock on 'mu1'}}<br>
> +<br>
> + mutex_exclusive_lock(&mu1);<br>
> + mutex_shared_lock(&mu2);<br>
> + Foo_fun1(1);<br>
> +<br>
> + mutex_shared_lock(&mu1); // \<br>
> + // expected-warning{{locking 'mu1' that is already locked}}<br>
> + mutex_unlock(&mu1);<br>
> + mutex_unlock(&mu2);<br>
> + mutex_shared_lock(&mu1);<br>
> + mutex_exclusive_lock(&mu2);<br>
> + Foo_fun2(2);<br>
> +<br>
> + mutex_unlock(&mu2);<br>
> + mutex_unlock(&mu1);<br>
> + mutex_exclusive_lock(&mu1);<br>
> + Bar_fun1(3);<br>
> + mutex_unlock(&mu1);<br>
> +<br>
> + mutex_exclusive_lock(&mu1);<br>
> + Foo_func3(4); // \<br>
> + // expected-warning{{cannot call function 'Foo_func3' while mutex 'mu1' is locked}}<br>
> + mutex_unlock(&mu1);<br>
> +<br>
> + Foo_func3(5);<br>
> +<br>
> + set_value(&a_, 0); // \<br>
> + // expected-warning{{calling function 'setA' requires exclusive lock on 'foo_.mu_'}}<br>
> + get_value(b_); // \<br>
> + // expected-warning{{calling function 'getB' requires shared lock on 'foo_.mu_'}}<br>
> + mutex_exclusive_lock(foo_.mu_);<br>
> + set_value(&a_, 1);<br>
> + mutex_unlock(foo_.mu_);<br>
> + mutex_shared_lock(foo_.mu_);<br>
> + assert(get_value(b_) == 1);<br>
> + mutex_unlock(foo_.mu_);<br>
> +<br>
> + c_ = 0; // \<br>
> + // expected-warning{{writing variable 'c_' requires locking any mutex exclusively}}<br>
> + assert(*d_ == 0); // \<br>
> + // expected-warning{{reading the value pointed to by 'd_' requires locking any mutex}}<br>
> + mutex_exclusive_lock(foo_.mu_);<br>
> + c_ = 1;<br>
> + assert(*d_ == 1);<br>
> + mutex_unlock(foo_.mu_);<br>
> +<br>
> + return 0;<br>
> +}<br>
</div></div>> _______________________________________________<br>
> cfe-dev mailing list<br>
> <a href="mailto:cfe-dev@cs.uiuc.edu">cfe-dev@cs.uiuc.edu</a><br>
> <a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev</a><br>
<br>
</blockquote></div><br></div>