public void run()
		{
			//---------------------------------------
			//Mutex wait ensure atomicity of phase 1
			//---------------------------------------
			mutex.P();
			System.out.println("\n\n*******************************************************");
			System.out.println("StackProber thread [TID=" + this.iTID + "] starts executing.");
			
			
			phase1();

			try
			{
				for(int i = 0; i < siThreadSteps; i++)
				{
					System.out.print("Stack Prober [TID=" + this.iTID + "]: Stack state: ");

					// [s] - means ordinay slot of a stack
					// (s) - current top of the stack
					for(int s = 0; s < soStack.getiSize(); s++)
						System.out.print
						(
							(s == BlockManager.soStack.getiTop() ? "(" : "[") +
							BlockManager.soStack.getAt(s) +
							(s == BlockManager.soStack.getiTop() ? ")" : "]")
						);

					System.out.println(".");

				}
			}
			catch(Exception e)
			{
				reportException(e);
				System.exit(1);
			}
			//----------------------------------------
			//Release mutex once Phase 1 is completed
			//----------------------------------------
			mutex.V();
			
			
			//------------------------------------------------
			//Using semaphores we ensure that Phase 2 doesn't
			//start before all Phase 1 are complete
			//------------------------------------------------	
			s1.V();
			s2.P();
			s2.V();
			
			//---------------------------------------------
			//Continually checks whether or not if current 
			//thread is allowed to go
			//---------------------------------------------
			do
			{
				mutex.P();
				if(this.turnTestAndSet())
				{
					phase2();
					break;
				}
				mutex.V();
			}while(!this.turnTestAndSet());
			
			mutex.V();
			
			

			
			System.out.println("StackProber thread [TID=" + this.iTID + "] terminates.");
			System.out.println("*******************************************************\n\n");
			
			

		}