forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			516 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			516 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
| // RUN: %clang_analyze_cc1 -analyzer-checker=alpha.unix.PthreadLock -verify %s
 | |
| 
 | |
| // Tests performing normal locking patterns and wrong locking orders
 | |
| 
 | |
| #include "Inputs/system-header-simulator-for-pthread-lock.h"
 | |
| 
 | |
| pthread_mutex_t mtx1, mtx2;
 | |
| pthread_mutex_t *pmtx;
 | |
| lck_mtx_t lck1, lck2;
 | |
| lck_grp_t grp1;
 | |
| lck_rw_t rw;
 | |
| 
 | |
| #define NULL 0
 | |
| 
 | |
| 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
 | |
| ok8(void)
 | |
| {
 | |
| 	pthread_mutex_lock(&mtx1);	// no-warning
 | |
| 	pthread_mutex_lock(&mtx2);	// no-warning
 | |
| 	pthread_mutex_unlock(&mtx2);	// no-warning
 | |
| 	pthread_mutex_unlock(&mtx1);	// no-warning
 | |
| }
 | |
| 
 | |
| void
 | |
| ok9(void)
 | |
| {
 | |
| 	pthread_mutex_unlock(&mtx1);		// no-warning
 | |
| 	if (pthread_mutex_trylock(&mtx1) == 0)	// no-warning
 | |
| 		pthread_mutex_unlock(&mtx1);	// no-warning
 | |
| }
 | |
| 
 | |
| void
 | |
| ok10(void)
 | |
| {
 | |
| 	if (pthread_mutex_trylock(&mtx1) != 0)	// no-warning
 | |
| 		pthread_mutex_lock(&mtx1);	// no-warning
 | |
| 	pthread_mutex_unlock(&mtx1);		// no-warning
 | |
| }
 | |
| 
 | |
| void
 | |
| ok11(void)
 | |
| {
 | |
| 	pthread_mutex_destroy(&mtx1);	// no-warning
 | |
| }
 | |
| 
 | |
| void
 | |
| ok12(void)
 | |
| {
 | |
| 	pthread_mutex_destroy(&mtx1);	// no-warning
 | |
| 	pthread_mutex_destroy(&mtx2);	// no-warning
 | |
| }
 | |
| 
 | |
| void
 | |
| ok13(void)
 | |
| {
 | |
| 	pthread_mutex_unlock(&mtx1);	// no-warning
 | |
| 	pthread_mutex_destroy(&mtx1);	// no-warning
 | |
| }
 | |
| 
 | |
| void
 | |
| ok14(void)
 | |
| {
 | |
| 	pthread_mutex_unlock(&mtx1);	// no-warning
 | |
| 	pthread_mutex_destroy(&mtx1);	// no-warning
 | |
| 	pthread_mutex_unlock(&mtx2);	// no-warning
 | |
| 	pthread_mutex_destroy(&mtx2);	// no-warning
 | |
| }
 | |
| 
 | |
| void
 | |
| ok15(void)
 | |
| {
 | |
| 	pthread_mutex_lock(&mtx1);	// no-warning
 | |
| 	pthread_mutex_unlock(&mtx1);	// no-warning
 | |
| 	pthread_mutex_destroy(&mtx1);	// no-warning
 | |
| }
 | |
| 
 | |
| void
 | |
| ok16(void)
 | |
| {
 | |
| 	pthread_mutex_init(&mtx1, NULL);	// no-warning
 | |
| }
 | |
| 
 | |
| void
 | |
| ok17(void)
 | |
| {
 | |
| 	pthread_mutex_init(&mtx1, NULL);	// no-warning
 | |
| 	pthread_mutex_init(&mtx2, NULL);	// no-warning
 | |
| }
 | |
| 
 | |
| void
 | |
| ok18(void)
 | |
| {
 | |
| 	pthread_mutex_destroy(&mtx1);		// no-warning
 | |
| 	pthread_mutex_init(&mtx1, NULL);	// no-warning
 | |
| }
 | |
| 
 | |
| void
 | |
| ok19(void)
 | |
| {
 | |
| 	pthread_mutex_destroy(&mtx1);		// no-warning
 | |
| 	pthread_mutex_init(&mtx1, NULL);	// no-warning
 | |
| 	pthread_mutex_destroy(&mtx2);		// no-warning
 | |
| 	pthread_mutex_init(&mtx2, NULL);	// no-warning
 | |
| }
 | |
| 
 | |
| void
 | |
| ok20(void)
 | |
| {
 | |
| 	pthread_mutex_unlock(&mtx1);		// no-warning
 | |
| 	pthread_mutex_destroy(&mtx1);		// no-warning
 | |
| 	pthread_mutex_init(&mtx1, NULL);	// no-warning
 | |
| 	pthread_mutex_destroy(&mtx1);		// no-warning
 | |
| 	pthread_mutex_init(&mtx1, NULL);	// no-warning
 | |
| }
 | |
| 
 | |
| void
 | |
| ok21(void) {
 | |
|   pthread_mutex_lock(pmtx);    // no-warning
 | |
|   pthread_mutex_unlock(pmtx);  // no-warning
 | |
| }
 | |
| 
 | |
| void
 | |
| ok22(void) {
 | |
|   pthread_mutex_lock(pmtx);    // no-warning
 | |
|   pthread_mutex_unlock(pmtx);  // no-warning
 | |
|   pthread_mutex_lock(pmtx);    // no-warning
 | |
|   pthread_mutex_unlock(pmtx);  // no-warning
 | |
| }
 | |
| 
 | |
| void ok23(void) {
 | |
|   if (pthread_mutex_destroy(&mtx1) != 0) // no-warning
 | |
|     pthread_mutex_destroy(&mtx1);        // no-warning
 | |
| }
 | |
| 
 | |
| void ok24(void) {
 | |
|   if (pthread_mutex_destroy(&mtx1) != 0) // no-warning
 | |
|     pthread_mutex_lock(&mtx1);           // no-warning
 | |
| }
 | |
| 
 | |
| void ok25(void) {
 | |
|   if (pthread_mutex_destroy(&mtx1) != 0) // no-warning
 | |
|     pthread_mutex_unlock(&mtx1);         // no-warning
 | |
| }
 | |
| 
 | |
| void ok26(void) {
 | |
|   pthread_mutex_unlock(&mtx1);           // no-warning
 | |
|   if (pthread_mutex_destroy(&mtx1) != 0) // no-warning
 | |
|     pthread_mutex_lock(&mtx1);           // no-warning
 | |
| }
 | |
| 
 | |
| void ok27(void) {
 | |
|   pthread_mutex_unlock(&mtx1);           // no-warning
 | |
|   if (pthread_mutex_destroy(&mtx1) != 0) // no-warning
 | |
|     pthread_mutex_lock(&mtx1);           // no-warning
 | |
|   else
 | |
|     pthread_mutex_init(&mtx1, NULL); // no-warning
 | |
| }
 | |
| 
 | |
| void ok28(void) {
 | |
|   if (pthread_mutex_destroy(&mtx1) != 0) { // no-warning
 | |
|     pthread_mutex_lock(&mtx1);             // no-warning
 | |
|     pthread_mutex_unlock(&mtx1);           // no-warning
 | |
|     pthread_mutex_destroy(&mtx1);          // no-warning
 | |
|   }
 | |
| }
 | |
| 
 | |
| void ok29(void) {
 | |
|   lck_rw_lock_shared(&rw);
 | |
|   lck_rw_unlock_shared(&rw);
 | |
|   lck_rw_lock_exclusive(&rw); // no-warning
 | |
|   lck_rw_unlock_exclusive(&rw); // no-warning
 | |
| }
 | |
| 
 | |
| void escape_mutex(pthread_mutex_t *m);
 | |
| void ok30(void) {
 | |
|   pthread_mutex_t local_mtx;
 | |
|   pthread_mutex_init(&local_mtx, NULL);
 | |
|   pthread_mutex_lock(&local_mtx);
 | |
|   escape_mutex(&local_mtx);
 | |
|   pthread_mutex_lock(&local_mtx); // no-warning
 | |
|   pthread_mutex_unlock(&local_mtx);
 | |
|   pthread_mutex_destroy(&local_mtx);
 | |
| }
 | |
| 
 | |
| void ok31(void) {
 | |
|   pthread_mutex_t local_mtx;
 | |
|   pthread_mutex_init(&local_mtx, NULL);
 | |
|   pthread_mutex_lock(&local_mtx);
 | |
|   fake_system_function_that_takes_a_mutex(&local_mtx);
 | |
|   pthread_mutex_lock(&local_mtx); // no-warning
 | |
|   pthread_mutex_unlock(&local_mtx);
 | |
|   pthread_mutex_destroy(&local_mtx);
 | |
| }
 | |
| 
 | |
| 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}}
 | |
| }
 | |
| 
 | |
| void
 | |
| bad9(void)
 | |
| {
 | |
| 	lck_mtx_unlock(&lck1);		// no-warning
 | |
| 	lck_mtx_unlock(&lck1);		// expected-warning{{This lock has already been unlocked}}
 | |
| }
 | |
| 
 | |
| void
 | |
| bad10(void)
 | |
| {
 | |
| 	lck_mtx_lock(&lck1);		// no-warning
 | |
| 	lck_mtx_unlock(&lck1);		// no-warning
 | |
| 	lck_mtx_unlock(&lck1);		// expected-warning{{This lock has already been unlocked}}
 | |
| }
 | |
| 
 | |
| static void
 | |
| bad11_sub(pthread_mutex_t *lock)
 | |
| {
 | |
| 	lck_mtx_unlock(lock);		// expected-warning{{This lock has already been unlocked}}
 | |
| }
 | |
| 
 | |
| void
 | |
| bad11(int i)
 | |
| {
 | |
| 	lck_mtx_lock(&lck1);		// no-warning
 | |
| 	lck_mtx_unlock(&lck1);		// no-warning
 | |
| 	if (i < 5)
 | |
| 		bad11_sub(&lck1);
 | |
| }
 | |
| 
 | |
| void
 | |
| bad12(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
 | |
| 	pthread_mutex_unlock(&mtx1);	// expected-warning{{This lock has already been unlocked}}
 | |
| }
 | |
| 
 | |
| void
 | |
| bad13(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
 | |
| 	pthread_mutex_unlock(&mtx1);	// expected-warning{{This lock has already been unlocked}}
 | |
| }
 | |
| 
 | |
| void
 | |
| bad14(void)
 | |
| {
 | |
| 	pthread_mutex_lock(&mtx1);	// no-warning
 | |
| 	pthread_mutex_lock(&mtx2);	// no-warning
 | |
| 	pthread_mutex_unlock(&mtx2);	// no-warning
 | |
| 	pthread_mutex_unlock(&mtx1);	// no-warning
 | |
| 	pthread_mutex_unlock(&mtx2);	// expected-warning{{This lock has already been unlocked}}
 | |
| }
 | |
| 
 | |
| void
 | |
| bad15(void)
 | |
| {
 | |
| 	pthread_mutex_lock(&mtx1);	// no-warning
 | |
| 	pthread_mutex_lock(&mtx2);	// no-warning
 | |
| 	pthread_mutex_unlock(&mtx2);	// no-warning
 | |
| 	pthread_mutex_unlock(&mtx1);	// no-warning
 | |
| 	pthread_mutex_lock(&mtx1);	// no-warning
 | |
| 	pthread_mutex_unlock(&mtx2);	// expected-warning{{This lock has already been unlocked}}
 | |
| }
 | |
| 
 | |
| void
 | |
| bad16(void)
 | |
| {
 | |
| 	pthread_mutex_destroy(&mtx1);	// no-warning
 | |
| 	pthread_mutex_lock(&mtx1);	// expected-warning{{This lock has already been destroyed}}
 | |
| }
 | |
| 
 | |
| void
 | |
| bad17(void)
 | |
| {
 | |
| 	pthread_mutex_destroy(&mtx1);	// no-warning
 | |
| 	pthread_mutex_unlock(&mtx1);	// expected-warning{{This lock has already been destroyed}}
 | |
| }
 | |
| 
 | |
| void
 | |
| bad18(void)
 | |
| {
 | |
| 	pthread_mutex_destroy(&mtx1);	// no-warning
 | |
| 	pthread_mutex_destroy(&mtx1);	// expected-warning{{This lock has already been destroyed}}
 | |
| }
 | |
| 
 | |
| void
 | |
| bad19(void)
 | |
| {
 | |
| 	pthread_mutex_lock(&mtx1);	// no-warning
 | |
| 	pthread_mutex_destroy(&mtx1);	// expected-warning{{This lock is still locked}}
 | |
| }
 | |
| 
 | |
| void
 | |
| bad20(void)
 | |
| {
 | |
| 	lck_mtx_destroy(&mtx1, &grp1);	// no-warning
 | |
| 	lck_mtx_lock(&mtx1);		// expected-warning{{This lock has already been destroyed}}
 | |
| }
 | |
| 
 | |
| void
 | |
| bad21(void)
 | |
| {
 | |
| 	lck_mtx_destroy(&mtx1, &grp1);	// no-warning
 | |
| 	lck_mtx_unlock(&mtx1);		// expected-warning{{This lock has already been destroyed}}
 | |
| }
 | |
| 
 | |
| void
 | |
| bad22(void)
 | |
| {
 | |
| 	lck_mtx_destroy(&mtx1, &grp1);	// no-warning
 | |
| 	lck_mtx_destroy(&mtx1, &grp1);	// expected-warning{{This lock has already been destroyed}}
 | |
| }
 | |
| 
 | |
| void
 | |
| bad23(void)
 | |
| {
 | |
| 	lck_mtx_lock(&mtx1);		// no-warning
 | |
| 	lck_mtx_destroy(&mtx1, &grp1);	// expected-warning{{This lock is still locked}}
 | |
| }
 | |
| 
 | |
| void
 | |
| bad24(void)
 | |
| {
 | |
| 	pthread_mutex_init(&mtx1, NULL);	// no-warning
 | |
| 	pthread_mutex_init(&mtx1, NULL);	// expected-warning{{This lock has already been initialized}}
 | |
| }
 | |
| 
 | |
| void
 | |
| bad25(void)
 | |
| {
 | |
| 	pthread_mutex_lock(&mtx1);		// no-warning
 | |
| 	pthread_mutex_init(&mtx1, NULL);	// expected-warning{{This lock is still being held}}
 | |
| }
 | |
| 
 | |
| void
 | |
| bad26(void)
 | |
| {
 | |
| 	pthread_mutex_unlock(&mtx1);		// no-warning
 | |
| 	pthread_mutex_init(&mtx1, NULL);	// expected-warning{{This lock has already been initialized}}
 | |
| }
 | |
| 
 | |
| void bad27(void) {
 | |
|   pthread_mutex_unlock(&mtx1);            // no-warning
 | |
|   int ret = pthread_mutex_destroy(&mtx1); // no-warning
 | |
|   if (ret != 0)                           // no-warning
 | |
|     pthread_mutex_lock(&mtx1);            // no-warning
 | |
|   else
 | |
|     pthread_mutex_unlock(&mtx1); // expected-warning{{This lock has already been destroyed}}
 | |
| }
 | |
| 
 | |
| void bad28(void) {
 | |
|   pthread_mutex_unlock(&mtx1);            // no-warning
 | |
|   int ret = pthread_mutex_destroy(&mtx1); // no-warning
 | |
|   if (ret != 0)                           // no-warning
 | |
|     pthread_mutex_lock(&mtx1);            // no-warning
 | |
|   else
 | |
|     pthread_mutex_lock(&mtx1); // expected-warning{{This lock has already been destroyed}}
 | |
| }
 | |
| 
 | |
| void bad29(void) {
 | |
|   pthread_mutex_lock(&mtx1);             // no-warning
 | |
|   pthread_mutex_unlock(&mtx1);           // no-warning
 | |
|   if (pthread_mutex_destroy(&mtx1) != 0) // no-warning
 | |
|     pthread_mutex_init(&mtx1, NULL);     // expected-warning{{This lock has already been initialized}}
 | |
|   else
 | |
|     pthread_mutex_init(&mtx1, NULL); // no-warning
 | |
| }
 | |
| 
 | |
| void bad30(void) {
 | |
|   pthread_mutex_lock(&mtx1);             // no-warning
 | |
|   pthread_mutex_unlock(&mtx1);           // no-warning
 | |
|   if (pthread_mutex_destroy(&mtx1) != 0) // no-warning
 | |
|     pthread_mutex_init(&mtx1, NULL);     // expected-warning{{This lock has already been initialized}}
 | |
|   else
 | |
|     pthread_mutex_destroy(&mtx1); // expected-warning{{This lock has already been destroyed}}
 | |
| }
 | |
| 
 | |
| void bad31(void) {
 | |
|   int ret = pthread_mutex_destroy(&mtx1); // no-warning
 | |
|   pthread_mutex_lock(&mtx1);              // expected-warning{{This lock has already been destroyed}}
 | |
|   if (ret != 0)
 | |
|     pthread_mutex_lock(&mtx1);
 | |
| }
 | |
| 
 | |
| void bad32(void) {
 | |
|   lck_rw_lock_shared(&rw);
 | |
|   lck_rw_unlock_exclusive(&rw); // FIXME: warn - should be shared?
 | |
|   lck_rw_lock_exclusive(&rw);
 | |
|   lck_rw_unlock_shared(&rw); // FIXME: warn - should be exclusive?
 | |
| }
 | |
| 
 | |
| void bad33(void) {
 | |
|   pthread_mutex_lock(pmtx);
 | |
|   fake_system_function();
 | |
|   pthread_mutex_lock(pmtx); // expected-warning{{This lock has already been acquired}}
 | |
| }
 |