/* _test_locks4.c: test of locks and gets and puts of a specified DTYPE data type.

        Date created    : September 24, 2002
        Date modified   : November 4, 2002

	Function tested: upc_global_lock_alloc, upc_lock_init, upc_lock, upc_unlock
        
	Description:
	-  Intended originally to test and see if locking and unlocking a lock twice is allowed
	   by the MuPC RTS. Locking: Similar to Compaq's RTS, MuPC hangs when a thread tries
	   to lock a "lock" twice. Unlocking: Program ran fine when a thread unlocks a lock twice.
	   Output is correct too. No warning or message appeared.
 	- A simple test case that allocates a lock and then updates the value of the lock. 
	- Critical region protected by the lock just simply increments and decrements the value 
       	  of counter continuously.
	- Thread 0 performs error checking at end.
 
        Platform Tested         No. Proc        Date Tested             Success
        UPC0                    2	        September 24, 2002	No	
	UPC0			2, 4		September 25, 2002	Yes
	UPC0 (all types)	4		October 29, 2002	Yes
	UPC0 (all - D)		4		November 5, 2002	Partial        
	CSE0 (all - D)		2,4,8,16	November 11, 2002	Partial
	CSE0 (double)		2,4,8,12,16	November 17, 2002	Yes
	LION (all types)	2,4,8,16,32	November 19, 2002	No
	UPC0 (all types)	2		December 3, 2002	Yes

	Bugs Found:
[FIXED]	[9/24/2002] Value of counter != 0. Bug reported to programmer. 
		[thread 0, i = 500] counter = 1073867952
		[thread 1, i = 500] counter = 1073867952
		[thread 0] counter = 1073867952
		[thread 1] counter = 1073867952
[FIXED]	[11/05/2002] Test case fails for DTYPE=double. Bug reported to programmer.
		MPI process 64330 died from signal 8 (Floating point exception)
[FIXED]	[11/11/2002] On cse0, test case fails for DTYPE=double, COUNT=50, n=12,16
		MPI process rank 1 (n0, p4550) caught a SIGFPE in MPI_Test.
	[11/19/2002] On lionel, test case fails for DTYPE=all, n=2,4,8,16,32, C=50.
		MPI process rank 0 (n0, p884) caught a SIGSEGV.
		
	Notes:
	[9/25/2002] Bug reported above has been fixed. Bug was caused by the buffering system.
   		    When locks are used together with gets, entries in the buffering system's queue 
		    (generated by locks) that weren't removed affected the other entries in the 
  		    User Get (UG) queue, thus producing the wrong results in this test case.
*/

#include <upc.h>
#include <stdio.h>

//#define VERBOSE0
#define DTYPE DATA 
#define COUNT 1000 

upc_lock_t* shared lock_1;
shared DTYPE counter;
shared int error;

int main (void) 
{
	int i;
	error = 0;

	if (MYTHREAD == 0) {
		lock_1 = upc_global_lock_alloc();
#if 0
		upc_lock_init(lock_1);
#endif
		counter = (DTYPE)(0);
	}

	upc_barrier;
	
	upc_lock(lock_1);
	for (i = 0; i < COUNT; i++) {	
		counter += (DTYPE)(1);
		counter -= (DTYPE)(1);
	}
	upc_unlock(lock_1);

	upc_barrier;

#ifdef VERBOSE0	
	printf("[thread %d] counter = %d\n", MYTHREAD, counter);
#endif

	if (MYTHREAD == 0) {
		if (counter != (DTYPE)(0)) 
			error = 1;

		if (error)
                        printf("Error: test_locks4.c failed! [th=%d, error=%d, DATA]\n", THREADS, error);
                else
                        printf("Success: test_locks4.c passed! [th=%d, error=%d, DATA]\n", THREADS, error);
	}	
	return (error);
}
