2011-08-04 07:14:55 +08:00
|
|
|
// RUN: %clang_cc1 -analyze -analyzer-checker=experimental.unix.PthreadLock -verify %s
|
2011-07-20 04:21:41 +08:00
|
|
|
|
|
|
|
// Tests performing normal locking patterns and wrong locking orders
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
void *foo;
|
|
|
|
} pthread_mutex_t;
|
|
|
|
|
|
|
|
typedef pthread_mutex_t lck_mtx_t;
|
|
|
|
|
|
|
|
extern int pthread_mutex_lock(pthread_mutex_t *);
|
|
|
|
extern int pthread_mutex_unlock(pthread_mutex_t *);
|
|
|
|
extern int pthread_mutex_trylock(pthread_mutex_t *);
|
|
|
|
extern int lck_mtx_lock(lck_mtx_t *);
|
|
|
|
extern int lck_mtx_unlock(lck_mtx_t *);
|
|
|
|
extern int lck_mtx_try_lock(lck_mtx_t *);
|
|
|
|
|
|
|
|
pthread_mutex_t mtx1, mtx2;
|
|
|
|
lck_mtx_t lck1, lck2;
|
|
|
|
|
|
|
|
void
|
|
|
|
ok1(void)
|
|
|
|
{
|
|
|
|
pthread_mutex_lock(&mtx1); // no-warning
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ok2(void)
|
|
|
|
{
|
|
|
|
pthread_mutex_unlock(&mtx1); // no-warning
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ok3(void)
|
|
|
|
{
|
|
|
|
pthread_mutex_lock(&mtx1); // no-warning
|
|
|
|
pthread_mutex_unlock(&mtx1); // no-warning
|
|
|
|
pthread_mutex_lock(&mtx1); // no-warning
|
|
|
|
pthread_mutex_unlock(&mtx1); // no-warning
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ok4(void)
|
|
|
|
{
|
|
|
|
pthread_mutex_lock(&mtx1); // no-warning
|
|
|
|
pthread_mutex_unlock(&mtx1); // no-warning
|
|
|
|
pthread_mutex_lock(&mtx2); // no-warning
|
|
|
|
pthread_mutex_unlock(&mtx2); // no-warning
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ok5(void)
|
|
|
|
{
|
|
|
|
if (pthread_mutex_trylock(&mtx1) == 0) // no-warning
|
|
|
|
pthread_mutex_unlock(&mtx1); // no-warning
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ok6(void)
|
|
|
|
{
|
|
|
|
lck_mtx_lock(&lck1); // no-warning
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ok7(void)
|
|
|
|
{
|
|
|
|
if (lck_mtx_try_lock(&lck1) != 0) // no-warning
|
|
|
|
lck_mtx_unlock(&lck1); // no-warning
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
bad1(void)
|
|
|
|
{
|
|
|
|
pthread_mutex_lock(&mtx1); // no-warning
|
|
|
|
pthread_mutex_lock(&mtx1); // expected-warning{{This lock has already been acquired}}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
bad2(void)
|
|
|
|
{
|
|
|
|
pthread_mutex_lock(&mtx1); // no-warning
|
|
|
|
pthread_mutex_unlock(&mtx1); // no-warning
|
|
|
|
pthread_mutex_lock(&mtx1); // no-warning
|
|
|
|
pthread_mutex_lock(&mtx1); // expected-warning{{This lock has already been acquired}}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
bad3(void)
|
|
|
|
{
|
|
|
|
pthread_mutex_lock(&mtx1); // no-warning
|
|
|
|
pthread_mutex_lock(&mtx2); // no-warning
|
|
|
|
pthread_mutex_unlock(&mtx1); // expected-warning{{This was not the most recently acquired lock}}
|
|
|
|
pthread_mutex_unlock(&mtx2);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
bad4(void)
|
|
|
|
{
|
|
|
|
if (pthread_mutex_trylock(&mtx1)) // no-warning
|
|
|
|
return;
|
|
|
|
pthread_mutex_lock(&mtx2); // no-warning
|
|
|
|
pthread_mutex_unlock(&mtx1); // expected-warning{{This was not the most recently acquired lock}}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
bad5(void)
|
|
|
|
{
|
|
|
|
lck_mtx_lock(&lck1); // no-warning
|
|
|
|
lck_mtx_lock(&lck1); // expected-warning{{This lock has already been acquired}}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
bad6(void)
|
|
|
|
{
|
|
|
|
lck_mtx_lock(&lck1); // no-warning
|
|
|
|
lck_mtx_unlock(&lck1); // no-warning
|
|
|
|
lck_mtx_lock(&lck1); // no-warning
|
|
|
|
lck_mtx_lock(&lck1); // expected-warning{{This lock has already been acquired}}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
bad7(void)
|
|
|
|
{
|
|
|
|
lck_mtx_lock(&lck1); // no-warning
|
|
|
|
lck_mtx_lock(&lck2); // no-warning
|
|
|
|
lck_mtx_unlock(&lck1); // expected-warning{{This was not the most recently acquired lock}}
|
|
|
|
lck_mtx_unlock(&lck2);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
bad8(void)
|
|
|
|
{
|
|
|
|
if (lck_mtx_try_lock(&lck1) == 0) // no-warning
|
|
|
|
return;
|
|
|
|
lck_mtx_lock(&lck2); // no-warning
|
|
|
|
lck_mtx_unlock(&lck1); // expected-warning{{This was not the most recently acquired lock}}
|
|
|
|
}
|