On Tue, Jul 30, 2013 at 03:31:48PM -0700, Alex Wang wrote: > From: Ethan Jackson <et...@nicira.com> > > This commit adds annotations for thread safety check. And the > check can be conducted by using -Wthread-safety flag in clang. > > Co-authored-by: Alex Wang <al...@nicira.com> > Signed-off-by: Alex Wang <al...@nicira.com> > Signed-off-by: Ethan Jackson <et...@nicira.com>
The lockfile logging change in this patch caused test failures for me. I didn't see a reason for the logging change, so I just dropped it. We can do it in a separate patch if there is a good reason.. I did a little editing of compiler and ovs-thread.[ch]. Diff appended. Hope it's OK. My only unresolved comment is that the 'where' member of the new struct is write-only: nothing ever reads it. But this is important enough that I'm willing to resolve that one way or another later. Applied to master, thanks to both of you! diff --git a/lib/compiler.h b/lib/compiler.h index a95a065..1c01fd1 100644 --- a/lib/compiler.h +++ b/lib/compiler.h @@ -51,46 +51,49 @@ * OVS_LOCKABLE indicates that the struct contains mutex element * which can be locked by functions like ovs_mutex_lock(). * - * The word 'MUTEX' in the following text can stand for more than - * one OVS_LOCKABLE structs. This means that we can require a function - * to hold multiple locks while invoked. - * e.g. some_function() OVS_REQ_WRLOCK(wrlock_file1, wrlock_file2) + * Below, the word MUTEX stands for the name of an object with an OVS_LOCKABLE + * struct type. It can also be a comma-separated list of multiple structs, + * e.g. to require a function to hold multiple locks while invoked. * * - * In a global variable declaration: + * On a variable: * - * OVS_GUARDED_VAR indicates that the variable may only be accessed while - * some MUTEX is acquired. + * - OVS_GUARDED indicates that the variable may only be accessed some mutex + * is held. * - * OVS_GUARDED_BY(...) indicates that the variable may only be accessed while - * MUTEX is acquired. + * - OVS_GUARDED_BY(MUTEX) indicates that the variable may only be accessed + * while the specific MUTEX is held. * * - * In a function prototype: + * On a function, the following attributes apply to mutexes: * - * OVS_ACQ_RDLOCK(...), OVS_ACQ_WRLOCK(...) and OVS_ACQUIRES(...) indicate - * that the function may only be called without MUTEX acquired and that it - * returns with MUTEX acquired. OVS_ACQUIRES(...) is used for plain MUTEX, - * and the other two for readers-writer MUTEX. + * - OVS_ACQUIRES(MUTEX) indicate that the function must be called without + * holding MUTEX and that it returns holding MUTEX. * - * OVS_RELEASES(...) indicates that the function may only be called with - * MUTEX acquired and that it returns with MUTEX released. It can be used - * for all types of MUTEX. + * - OVS_RELEASES(MUTEX) indicates that the function may only be called with + * MUTEX held and that it returns with MUTEX released. It can be used for + * all types of MUTEX. * - * OVS_TRY_RDLOCK(...) and OVS_TRY_WRLOCK(...) and OVS_TRY_LOCK(...) indicate - * that the function will try to acquire MUTEX. The macro takes one or more - * arguments. The first argument is an interger or boolean value specifying - * the return value of a successful lock acquisition. The remaining arguments - * are MUTEX. OVS_TRY_LOCK(...) is used for plain MUTEX, and the other two - * for readers-writer MUTEX. + * - OVS_TRY_LOCK(RETVAL, MUTEX) indicate that the function will try to + * acquire MUTEX. RETVAL is an integer or boolean value specifying the + * return value of a successful lock acquisition. * - * OVS_REQ_RDLOCK(...), OVS_REQ_WRLOCK(...) and OVS_REQUIRES(...) indicate - * that the function may only be called with MUTEX acquired by the caller - * and that the function does not release MUTEX. OVS_REQUIRES(...) is used - * for plain MUTEX, and the other two for readers-writer MUTEX. + * - OVS_REQUIRES(MUTEX) indicate that the function may only be called with + * MUTEX held and that the function does not release MUTEX. * - * OVS_LOCKS_EXCLUDED(MUTEX) indicates that the function may only be called - * without MUTEX acquired. */ + * - OVS_LOCKS_EXCLUDED(MUTEX) indicates that the function may only be + * called when MUTEX is not held. + * + * The following variants, with the same syntax, apply to reader-writer locks: + * + * mutex rwlock, for reading rwlock, for writing + * ------------------- ------------------- ------------------- + * OVS_ACQUIRES OVS_ACQ_RDLOCK OVS_ACQ_WRLOCK + * OVS_RELEASES OVS_RELEASES OVS_RELEASES + * OVS_TRY_LOCK OVS_TRY_RDLOCK OVS_TRY_WRLOCK + * OVS_REQUIRES OVS_REQ_RDLOCK OVS_REQ_WRLOCK + * OVS_LOCKS_EXCLUDED OVS_LOCKS_EXCLUDED OVS_LOCKS_EXCLUDED + */ #define OVS_LOCKABLE __attribute__((lockable)) #define OVS_REQ_RDLOCK(...) __attribute__((shared_locks_required(__VA_ARGS__))) #define OVS_ACQ_RDLOCK(...) __attribute__((shared_lock_function(__VA_ARGS__))) @@ -102,12 +105,12 @@ __attribute__((exclusive_locks_required(__VA_ARGS__))) #define OVS_ACQUIRES(...) \ __attribute__((exclusive_lock_function(__VA_ARGS__))) -#define OVS_TRY_WRLOCK(...) \ - __attribute__((exclusive_trylock_function(__VA_ARGS__))) -#define OVS_TRY_RDLOCK(...) \ - __attribute__((shared_trylock_function(__VA_ARGS__))) -#define OVS_TRY_LOCK(...) \ - __attribute__((exclusive_trylock_function(__VA_ARGS__))) +#define OVS_TRY_WRLOCK(RETVAL, ...) \ + __attribute__((exclusive_trylock_function(RETVAL, __VA_ARGS__))) +#define OVS_TRY_RDLOCK(RETVAL, ...) \ + __attribute__((shared_trylock_function(RETVAL, __VA_ARGS__))) +#define OVS_TRY_LOCK(RETVAL, ...) \ + __attribute__((exclusive_trylock_function(RETVAL, __VA_ARGS__))) #define OVS_GUARDED __attribute__((guarded_var)) #define OVS_GUARDED_BY(...) __attribute__((guarded_by(__VA_ARGS__))) #define OVS_RELEASES(...) __attribute__((unlock_function(__VA_ARGS__))) @@ -126,9 +129,9 @@ #define OVS_ACQ_WRLOCK(...) __attribute__((context(MUTEX, 0, 1))) #define OVS_REQUIRES(...) __attribute__((context(MUTEX, 1, 1))) #define OVS_ACQUIRES(...) __attribute__((context(MUTEX, 0, 1))) -#define OVS_TRY_WRLOCK(...) -#define OVS_TRY_RDLOCK(...) -#define OVS_TRY_LOCK(...) +#define OVS_TRY_WRLOCK(RETVAL, ...) +#define OVS_TRY_RDLOCK(RETVAL, ...) +#define OVS_TRY_LOCK(REVAL, ...) #define OVS_GUARDED #define OVS_GUARDED_BY(...) #define OVS_RELEASES(...) __attribute__((context(MUTEX, 1, 0))) diff --git a/lib/ovs-thread.c b/lib/ovs-thread.c index 640cb4c..c8b2c15 100644 --- a/lib/ovs-thread.c +++ b/lib/ovs-thread.c @@ -131,14 +131,13 @@ void ovs_mutex_init(const struct ovs_mutex *l_, int type) { struct ovs_mutex *l = CONST_CAST(struct ovs_mutex *, l_); - int error; pthread_mutexattr_t attr; + int error; l->where = NULL; xpthread_mutexattr_init(&attr); xpthread_mutexattr_settype(&attr, type); - error = pthread_mutex_init(&l->lock, - CONST_CAST(const pthread_mutexattr_t *, &attr)); + error = pthread_mutex_init(&l->lock, &attr); if (OVS_UNLIKELY(error)) { ovs_abort(error, "pthread_mutex_init failed"); } diff --git a/lib/ovs-thread.h b/lib/ovs-thread.h index 5c72d93..f5e171a 100644 --- a/lib/ovs-thread.h +++ b/lib/ovs-thread.h @@ -69,7 +69,7 @@ struct OVS_LOCKABLE ovs_mutex { * Most of these functions abort the process with an error message on any * error. ovs_mutex_trylock() is an exception: it passes through a 0 or EBUSY * return value to the caller and aborts on any other error. */ -void ovs_mutex_init(const struct ovs_mutex *, int); +void ovs_mutex_init(const struct ovs_mutex *, int type); void ovs_mutex_destroy(const struct ovs_mutex *); void ovs_mutex_unlock(const struct ovs_mutex *mutex) OVS_RELEASES(mutex); void ovs_mutex_lock_at(const struct ovs_mutex *mutex, const char *where) _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev