#include "stdio.h"
#include "pthread.h"

pthread_t thread1, thread2;
pthread_mutex_t lock1, lock2, lock3;
pthread_cond_t cond;



void f4()
{
	int i=0; 
	while(i++<10) 
	{
		while( i> 5) 
		{
			break; 
			i*=2;
		} 
		i++;
	}
	/* DFixer added:*/ /* DFixer multiple entries (clear)*/  if( ! preAcqTaken( & lock2 )) { pthread_mutex_lock( &lock2); }                           ;

	/* DFixer added:*/ /* DFixer: loop */ if ( !preAcqTaken( & lock2) ) { pthread_mutex_unlock ( & lock2); }/* DFixer added:*/ /* DFixer multiple entries (clear) */  clearPreAcq( & lock2);                              ;
}

void f3() {
	printf("xxxxxx"); 
	if((int)(&lock1) % 3 == 1)
	{ 
		int i=10; 
		while(i--> 0) 
			f4(); 
	} /* 
	{
		for(int i=10; i> 0; i--)
			f4(); 
	} */
}

void* f1 ( void* arg ) {

	/* DFixer added:*/ /* DFixer preAcquisitoin */ preAcq_pthread_mutex_lock(& lock1, & lock2); /* DFixer multiple entries (set) */ setPreAcqTaken ( & lock2 );                          ;

	/* DFixer added:*/ /* DFixer: handle other lock acquisitions */ setHWCondOn( &lock1, &lock2); pthread_mutex_unlock( &lock2); preAcq_pthread_mutex_lock( &lock3, &lock2); setHWCondOff( &lock1, &lock2);                          ; 
	/* DFixer added:*/ /* DFixer: handle wait(k) */ setHWCondOn( &lock1, &lock2); pthread_mutex_unlock(&lock2); pthread_cond_wait(&cond, &lock3); pthread_mutex_unlock( &lock3); preAcq_pthread_mutex_lock( &lock3, &lock2); setHWCondOff( &lock1, &lock2);                                ; //pthread_cond_wait(&cond, &lock1); 
	pthread_mutex_unlock(&lock3);
	
	printf("Test thread 1\n");
	
	if((int)(&lock1) % 7 == 1)
	{
		goto _exit_;
	}
	
	if((int)(&lock2) % 3 == 1) 
	{ printf("test\n");
		f3();/* DFixer appended:*/ /* DFixer: loop */ if ( preAcqTaken( & lock2) ) { pthread_mutex_unlock ( & lock2 ); /* DFixer multiple entries (clear again) */  clearPreAcq( & lock2); } 
	}

_exit_:
	/* DFixer added:*/ /* DFixer multiple exits */ if( ! preAcqTaken( & lock2 )) {pthread_mutex_unlock ( & lock2 ); /* DFixer multiple entries (clear again) */  clearPreAcq( & lock2); } pthread_mutex_unlock(&lock1);
	
	return NULL;
}
void* f2 ( void* arg ) {

	/* DFixer added:*/ /* DFixer: handle other lock acquisitions (the second thread) */  while(pthread_mutex_trylock(&lock2)){ if( getHWCond( &lock2, &lock1)) pthread_mutex_unlock(&lock2); else break; }                           ;

	printf("Test thread 2\n");

	pthread_mutex_lock(&lock1);

	
	pthread_mutex_unlock(&lock1);
	pthread_mutex_unlock(&lock2);
	
	return NULL;
}

int main ( void ) 
{

	pthread_create(&thread1, NULL, f1, NULL);
	pthread_create(&thread2, NULL, f2, NULL);

	pthread_join(thread1, NULL);
	pthread_join(thread2, NULL);

	printf("Finished.\n");
	return 0;
}
