Add lock annotations to the header files of our threading libraries.

This change extends all of the functions present in the <pthread.h> and
<threads.h> headers to have lock annotations. This will allow Clang to
warn about the following:

- Locking a function twice,
- Unlocking a function without a mutex being locked,
- Forgetting to unlock a mutex before returning,
- Destroying or reinitializing a mutex that is currenty locked,
- Using an unlocked mutex in combination with a condition variable.

Enabling these annotations already allowed me to catch a bug in one of
our userspace tools (r270749).
This commit is contained in:
ed 2014-09-01 18:34:30 +00:00
parent b51450dbbd
commit 72b4dec586
2 changed files with 67 additions and 36 deletions

View File

@ -193,8 +193,10 @@ int pthread_cond_init(pthread_cond_t *,
const pthread_condattr_t *);
int pthread_cond_signal(pthread_cond_t *);
int pthread_cond_timedwait(pthread_cond_t *,
pthread_mutex_t *, const struct timespec *);
int pthread_cond_wait(pthread_cond_t *, pthread_mutex_t *);
pthread_mutex_t *__mutex, const struct timespec *)
__requires_exclusive(*__mutex);
int pthread_cond_wait(pthread_cond_t *, pthread_mutex_t *__mutex)
__requires_exclusive(*__mutex);
int pthread_create(pthread_t *, const pthread_attr_t *,
void *(*) (void *), void *);
int pthread_detach(pthread_t);
@ -213,27 +215,42 @@ int pthread_mutexattr_getpshared(const pthread_mutexattr_t *,
int pthread_mutexattr_gettype(pthread_mutexattr_t *, int *);
int pthread_mutexattr_settype(pthread_mutexattr_t *, int);
int pthread_mutexattr_setpshared(pthread_mutexattr_t *, int);
int pthread_mutex_destroy(pthread_mutex_t *);
int pthread_mutex_init(pthread_mutex_t *,
const pthread_mutexattr_t *);
int pthread_mutex_lock(pthread_mutex_t *);
int pthread_mutex_trylock(pthread_mutex_t *);
int pthread_mutex_timedlock(pthread_mutex_t *,
const struct timespec *);
int pthread_mutex_unlock(pthread_mutex_t *);
int pthread_mutex_destroy(pthread_mutex_t *__mutex)
__requires_unlocked(*__mutex);
int pthread_mutex_init(pthread_mutex_t *__mutex,
const pthread_mutexattr_t *)
__requires_unlocked(*__mutex);
int pthread_mutex_lock(pthread_mutex_t *__mutex)
__locks_exclusive(*__mutex);
int pthread_mutex_trylock(pthread_mutex_t *__mutex)
__trylocks_exclusive(0, *__mutex);
int pthread_mutex_timedlock(pthread_mutex_t *__mutex,
const struct timespec *)
__trylocks_exclusive(0, *__mutex);
int pthread_mutex_unlock(pthread_mutex_t *__mutex)
__unlocks(*__mutex);
int pthread_once(pthread_once_t *, void (*) (void));
int pthread_rwlock_destroy(pthread_rwlock_t *);
int pthread_rwlock_init(pthread_rwlock_t *,
const pthread_rwlockattr_t *);
int pthread_rwlock_rdlock(pthread_rwlock_t *);
int pthread_rwlock_timedrdlock(pthread_rwlock_t *,
const struct timespec *);
int pthread_rwlock_timedwrlock(pthread_rwlock_t *,
const struct timespec *);
int pthread_rwlock_tryrdlock(pthread_rwlock_t *);
int pthread_rwlock_trywrlock(pthread_rwlock_t *);
int pthread_rwlock_unlock(pthread_rwlock_t *);
int pthread_rwlock_wrlock(pthread_rwlock_t *);
int pthread_rwlock_destroy(pthread_rwlock_t *__rwlock)
__requires_unlocked(*__rwlock);
int pthread_rwlock_init(pthread_rwlock_t *__rwlock,
const pthread_rwlockattr_t *)
__requires_unlocked(*__rwlock);
int pthread_rwlock_rdlock(pthread_rwlock_t *__rwlock)
__locks_shared(*__rwlock);
int pthread_rwlock_timedrdlock(pthread_rwlock_t *__rwlock,
const struct timespec *)
__trylocks_shared(0, *__rwlock);
int pthread_rwlock_timedwrlock(pthread_rwlock_t *__rwlock,
const struct timespec *)
__trylocks_exclusive(0, *__rwlock);
int pthread_rwlock_tryrdlock(pthread_rwlock_t *__rwlock)
__trylocks_shared(0, *__rwlock);
int pthread_rwlock_trywrlock(pthread_rwlock_t *__rwlock)
__trylocks_exclusive(0, *__rwlock);
int pthread_rwlock_unlock(pthread_rwlock_t *__rwlock)
__unlocks(*__rwlock);
int pthread_rwlock_wrlock(pthread_rwlock_t *__rwlock)
__locks_exclusive(*__rwlock);
int pthread_rwlockattr_destroy(pthread_rwlockattr_t *);
int pthread_rwlockattr_getkind_np(const pthread_rwlockattr_t *,
int *);
@ -245,11 +262,16 @@ int pthread_rwlockattr_setpshared(pthread_rwlockattr_t *, int);
pthread_t pthread_self(void);
int pthread_setspecific(pthread_key_t, const void *);
int pthread_spin_init(pthread_spinlock_t *, int);
int pthread_spin_destroy(pthread_spinlock_t *);
int pthread_spin_lock(pthread_spinlock_t *);
int pthread_spin_trylock(pthread_spinlock_t *);
int pthread_spin_unlock(pthread_spinlock_t *);
int pthread_spin_init(pthread_spinlock_t *__spin, int)
__requires_unlocked(*__spin);
int pthread_spin_destroy(pthread_spinlock_t *__spin)
__requires_unlocked(*__spin);
int pthread_spin_lock(pthread_spinlock_t *__spin)
__locks_exclusive(*__spin);
int pthread_spin_trylock(pthread_spinlock_t *__spin)
__trylocks_exclusive(0, *__spin);
int pthread_spin_unlock(pthread_spinlock_t *__spin)
__unlocks(*__spin);
int pthread_cancel(pthread_t);
int pthread_setcancelstate(int, int *);
int pthread_setcanceltype(int, int *);

View File

@ -79,15 +79,24 @@ int cnd_broadcast(cnd_t *);
void cnd_destroy(cnd_t *);
int cnd_init(cnd_t *);
int cnd_signal(cnd_t *);
int cnd_timedwait(cnd_t *__restrict, mtx_t *__restrict,
const struct timespec *__restrict);
int cnd_wait(cnd_t *, mtx_t *);
void mtx_destroy(mtx_t *);
int mtx_init(mtx_t *, int);
int mtx_lock(mtx_t *);
int mtx_timedlock(mtx_t *__restrict, const struct timespec *__restrict);
int mtx_trylock(mtx_t *);
int mtx_unlock(mtx_t *);
int cnd_timedwait(cnd_t *__restrict, mtx_t *__restrict __mtx,
const struct timespec *__restrict)
__requires_exclusive(*__mtx);
int cnd_wait(cnd_t *, mtx_t *__mtx)
__requires_exclusive(*__mtx);
void mtx_destroy(mtx_t *__mtx)
__requires_unlocked(*__mtx);
int mtx_init(mtx_t *__mtx, int)
__requires_unlocked(*__mtx);
int mtx_lock(mtx_t *__mtx)
__locks_exclusive(*__mtx);
int mtx_timedlock(mtx_t *__restrict __mtx,
const struct timespec *__restrict)
__trylocks_exclusive(thrd_success, *__mtx);
int mtx_trylock(mtx_t *__mtx)
__trylocks_exclusive(thrd_success, *__mtx);
int mtx_unlock(mtx_t *__mtx)
__unlocks(*__mtx);
int thrd_create(thrd_t *, thrd_start_t, void *);
thrd_t thrd_current(void);
int thrd_detach(thrd_t);