kerneltest/e32test/prime/t_semutx.cpp
changeset 201 43365a9b78a3
parent 152 657f875b013e
child 257 3e88ff8f41d5
--- a/kerneltest/e32test/prime/t_semutx.cpp	Wed Jun 23 19:44:53 2010 +0300
+++ b/kerneltest/e32test/prime/t_semutx.cpp	Tue Jul 06 15:50:07 2010 +0300
@@ -40,7 +40,9 @@
 
 #define __E32TEST_EXTENSION__
 #include <e32test.h>
-#include <u32std.h>
+#include <hal.h>
+#include <e32atomics.h>
+#include <u32hal.h>
 #include <e32svr.h>
 
 const TInt KMaxBufferSize=10;
@@ -51,13 +53,352 @@
 
 RTest test(_L("T_SEMUTX"));
 RMutex mutex;
-RCriticalSection criticalSn;	
+RCriticalSection criticalSn;
 TInt thread1Count,thread2Count;
 TInt arrayIndex;
-TInt array[KMaxArraySize];  
+TInt array[KMaxArraySize];
 TInt consumerArray[KNumProducerItems];
-RSemaphore slotAvailable,itemAvailable;  
+RSemaphore slotAvailable,itemAvailable;
+TBool doCpuLocking = EFalse;
+
+// return num of cpus in system
+TInt NumCpus()
+	{
+	TInt r = UserSvr::HalFunction(EHalGroupKernel, EKernelHalNumLogicalCpus, 0, 0);
+	return r;
+	}
+
+
+TInt LockCurrentThreadToCpu0(TBool aCallingIsMainTestThread = EFalse)
+	{
+	if (aCallingIsMainTestThread) 
+		{
+		if (NumCpus() > 1) 
+			{
+			doCpuLocking = ETrue;
+			return UserSvr::HalFunction(EHalGroupKernel, EKernelHalLockThreadToCpu, 0, 0); 
+			}
+		else
+			{
+			return KErrNone;
+			}
+		}
+	return UserSvr::HalFunction(EHalGroupKernel, EKernelHalLockThreadToCpu, 0, 0); 
+	}
+
+TInt UnlockCurrentThreadToCpu0(TBool aCallingIsMainTestThread = EFalse)
+	{
+	if (aCallingIsMainTestThread) 
+		{
+		if (NumCpus() > 1) 
+			{
+			doCpuLocking = EFalse;
+			return UserSvr::HalFunction(EHalGroupKernel, EKernelHalLockThreadToCpu, (TAny*) 0xffffffffu, 0); 
+			}
+		else
+			{
+			return KErrNone;
+			}
+		}
+	return UserSvr::HalFunction(EHalGroupKernel, EKernelHalLockThreadToCpu, (TAny*) 0xffffffffu, 0); 
+	}
+
+
+/******************************************************************************
+ * Random Number Generation
+ ******************************************************************************/
+void Random(TUint64& a)
+	{
+	TInt i;
+	for (i=64; i>0; --i)
+		{
+		TUint64 x = a<<1;
+		TUint64 y = x<<1;
+		x^=y;
+		a = (y>>1) | (x>>63);
+		}
+	}
+
+// Returns 256*log2(a/2^64)
+TInt Log2(TUint64 a)
+	{
+	const TUint64 KBit63 = UI64LIT(0x8000000000000000);
+	TInt n = __e32_find_ms1_64(a);
+	a <<= (63-n);
+	n -= 64;
+	TInt i;
+	for (i=0; i<8; ++i)
+		{
+		a >>= 32;
+		a *= a;
+		n <<= 1;
+		if (a & KBit63)
+			{
+			++n;
+			}
+		else
+			{
+			a <<= 1;
+			}
+		}
+	return n;
+	}
+
+TUint32 ExpRV(TUint64 aU, TUint32 aMean, TUint32 aTick)
+	{
+	TInt n = -Log2(aU);
+	TUint64 x = TUint64(n) * TUint64(aMean);
+	x *= TUint64(22713);	// 2^15 * ln2
+	TUint64 p(aTick);
+	p <<= 22;
+	x += p;
+	p += p;
+	x /= p;
+	return I64LOW(x);
+	}
+
+
+
+/*----------------------------------------------------------------------------*/
+class MLock
+	{
+public:
+	enum {EPollable=1, ETimeoutAvail=2, ENestable=4, ELimit1=8, ELooseTimeout=16};
+public:
+	virtual TInt Flags()=0;
+	virtual void Release()=0;
+	virtual void Wait()=0;
+	virtual void Signal()=0;
+	virtual TInt Wait(TInt aTimeout);
+	virtual TInt Poll();
+	};
+
+TInt MLock::Wait(TInt)
+	{ return KErrNotSupported; }
+TInt MLock::Poll()
+	{ return KErrNotSupported; }
+
+/*----------------------------------------------------------------------------*/
+class LockS : public MLock
+	{
+public:
+	LockS();
+	virtual TInt Flags();
+	virtual void Release();
+	virtual void Wait();
+	virtual void Signal();
+	virtual TInt Wait(TInt aTimeout);
+	virtual TInt Poll();
+public:
+	RSemaphore	iT;
+	};
+
+LockS::LockS()
+	{ test_KErrNone(iT.CreateLocal(1)); }
+TInt LockS::Flags()
+	{ return EPollable|ETimeoutAvail; }
+void LockS::Release()
+	{ iT.Close(); }
+void LockS::Wait()
+	{ iT.Wait(); }
+void LockS::Signal()
+	{ iT.Signal(); }
+TInt LockS::Wait(TInt aTimeout)
+	{ return iT.Wait(aTimeout); }
+TInt LockS::Poll()
+	{ return iT.Poll(); }
+
+/*----------------------------------------------------------------------------*/
+class LockM : public MLock
+	{
+public:
+	LockM();
+	virtual TInt Flags();
+	virtual void Release();
+	virtual void Wait();
+	virtual void Signal();
+	virtual TInt Wait(TInt aTimeout);
+	virtual TInt Poll();
+public:
+	RMutex		iT;
+	};
+
+LockM::LockM()
+	{ test_KErrNone(iT.CreateLocal()); }
+TInt LockM::Flags()
+	{ return EPollable|ETimeoutAvail|ENestable|ELimit1; }
+void LockM::Release()
+	{ iT.Close(); }
+void LockM::Wait()
+	{ iT.Wait(); }
+void LockM::Signal()
+	{ iT.Signal(); }
+TInt LockM::Wait(TInt aTimeout)
+	{ return iT.Wait(aTimeout); }
+TInt LockM::Poll()
+	{ return iT.Poll(); }
+
+/*----------------------------------------------------------------------------*/
+
+class LockFL : public MLock
+	{
+public:
+	LockFL();
+	virtual TInt Flags();
+	virtual void Release();
+	virtual void Wait();
+	virtual void Signal();
+	virtual TInt Wait(TInt aTimeout);
+	virtual TInt Poll();
+public:
+	RFastLock	iT;
+	};
+
+LockFL::LockFL()
+	{ test_KErrNone(iT.CreateLocal()); }
+TInt LockFL::Flags()
+	{ return ETimeoutAvail|EPollable|ELimit1|ELooseTimeout; }
+void LockFL::Release()
+	{ iT.Close(); }
+void LockFL::Wait()
+	{ iT.Wait(); }
+void LockFL::Signal()
+	{ iT.Signal(); }
+TInt LockFL::Wait(TInt aTimeout)
+	{ return iT.Wait(aTimeout); }
+TInt LockFL::Poll()
+	{ return iT.Poll(); }
+
+/*----------------------------------------------------------------------------*/
+class LockCS : public MLock
+	{
+public:
+	LockCS();
+	virtual TInt Flags();
+	virtual void Release();
+	virtual void Wait();
+	virtual void Signal();
+public:
+	RCriticalSection iT;
+	};
+
+LockCS::LockCS()
+	{ test_KErrNone(iT.CreateLocal()); }
+TInt LockCS::Flags()
+	{ return ELimit1; }
+void LockCS::Release()
+	{ iT.Close(); }
+void LockCS::Wait()
+	{ iT.Wait(); }
+void LockCS::Signal()
+	{ iT.Signal(); }
+
+
 			 
+/*----------------------------------------------------------------------------*/
+class LFSR
+	{
+public:
+	LFSR(TInt aBits, TInt aTap2, TInt aTap3=0, TInt aTap4=0);
+	~LFSR();
+	void Step();
+	void Step(TInt aSteps);
+	TBool operator==(const LFSR& a) const;
+public:
+	TUint32* iData;
+	TInt iBits;
+	TInt iTap2;
+	TInt iTap3;
+	TInt iTap4;
+	TInt iNW;
+	TInt iSh1;
+	TInt iIx2;
+	TInt iSh2;
+	TInt iIx3;
+	TInt iSh3;
+	TInt iIx4;
+	TInt iSh4;
+	};
+
+LFSR::LFSR(TInt aBits, TInt aTap2, TInt aTap3, TInt aTap4)
+	{
+	iBits = aBits;
+	iTap2 = aTap2;
+	iTap3 = aTap3;
+	iTap4 = aTap4;
+	iNW = (aBits + 31) >> 5;
+	iData = (TUint32*)User::AllocZ(iNW*sizeof(TUint32));
+	test(iData!=0);
+	iData[0] = 1;
+	iSh1 = (aBits-1)&31;
+	iIx2 = (iTap2-1)>>5;
+	iSh2 = (iTap2-1)&31;
+	if (iTap3)
+		{
+		iIx3 = (iTap3-1)>>5;
+		iSh3 = (iTap3-1)&31;
+		}
+	else
+		{
+		iIx3 = -1;
+		iSh3 = 0;
+		}
+	if (iTap4)
+		{
+		iIx4 = (iTap4-1)>>5;
+		iSh4 = (iTap4-1)&31;
+		}
+	else
+		{
+		iIx4 = -1;
+		iSh4 = 0;
+		}
+	}
+
+LFSR::~LFSR()
+	{
+	User::Free(iData);
+	}
+
+void LFSR::Step(TInt aSteps)
+	{
+	while (aSteps--)
+		Step();
+	}
+
+void LFSR::Step()
+	{
+	TUint32 b = iData[iNW-1]>>iSh1;
+	b ^= (iData[iIx2]>>iSh2);
+	if (iIx3>=0)
+		b ^= (iData[iIx3]>>iSh3);
+	if (iIx4>=0)
+		b ^= (iData[iIx4]>>iSh4);
+	b &= 1;
+	TInt i;
+	for (i=0; i<iNW; ++i)
+		{
+		TUint32 bb = iData[i] >> 31;
+		iData[i] = (iData[i]<<1)|b;
+		b = bb;
+		}
+	iData[iNW-1] &= ((2u<<iSh1)-1u);
+	}
+
+TBool LFSR::operator==(const LFSR& a) const
+	{
+	if (iBits!=a.iBits || iTap2!=a.iTap2 || iTap3!=a.iTap3 || iTap4!=a.iTap4 || iNW!=a.iNW)
+		return EFalse;
+	if (iData==a.iData)
+		return ETrue;
+	if (memcompare((const TUint8*)iData, iNW, (const TUint8*)a.iData, a.iNW))
+		return EFalse;
+	return ETrue;
+	}
+
+
+
+/*----------------------------------------------------------------------------*/
 class CStack
 	{
 public:	   
@@ -118,6 +459,7 @@
 // Mutex test thread 1
 //
 	{	
+	TInt n = NumCpus();
 
 	thread1Count=0;
 	TBool running=ETrue;
@@ -133,6 +475,16 @@
 		else
 			running=EFalse;
 		mutex.Signal();
+
+		if (n > 1) 
+			{
+			// when the mutex is singaled, due to priority balancing, the other
+			// thread will be scheduled to run on a CPU other than this one. The delay
+			// in getting that thread to run means that this one can manage to re-claim the 
+			// mutex before the other thread gets to run. So we add a small delay here 
+			User::After(100); 
+			}
+
 		} while (running);
 	return(KErrNone);
 	}
@@ -142,6 +494,7 @@
 // Mutex test thread 2
 //
 	{
+	TInt n = NumCpus();
 
 	thread2Count=0;
 	TBool running=ETrue;
@@ -157,6 +510,17 @@
 		else
 			running=EFalse;
 		mutex.Signal();
+
+		if (n > 1) 
+			{
+			// when the mutex is singaled, due to priority balancing, the other
+			// thread will be scheduled to run on a CPU other than this one. The delay
+			// in getting that thread to run means that this one can manage to re-claim the 
+			// mutex before the other thread gets to run. So we add a small delay here 
+			User::After(100); 
+			}
+		
+
 		} while (running);
 	return(KErrNone);
 	}
@@ -209,27 +573,80 @@
 	return(KErrNone);
 	}
 
-struct SWaitSem
+
+/*----------------------------------------------------------------------------*/
+struct SWaitLock
 	{
-	RSemaphore iSem;
+	enum {EDummy=-2, EPoll=-1, EInfinite=0};
+
+	static TInt WaitLockThread(TAny*);
+	void Start(RThread& aT, TThreadPriority aP=EPriorityLess);
+	void Wait(RThread& aT, TInt aResult);
+	TInt DoTest2(RThread& aT, TInt aTimeout, TInt aResult, TThreadPriority aP=EPriorityLess);
+	void Test2();
+	void TestSignalled();
+	void TestNotSignalled();
+	void TestState();
+
+
+	MLock* iLock;
 	TInt iTimeout;
 	};
 
-TInt WaitSemThread(TAny* a)
+TInt SWaitLock::WaitLockThread(TAny* a)
 	{
-	SWaitSem& ws = *(SWaitSem*)a;
-	return ws.iSem.Wait(ws.iTimeout);
+	
+	if (doCpuLocking)
+		{
+		TInt r = LockCurrentThreadToCpu0();
+		if (KErrNone!=r) return r;
+		// Rendevous was requested
+		RThread::Rendezvous(KErrNone);
+		}
+	
+	SWaitLock& w = *(SWaitLock*)a;
+	TInt lfl = w.iLock->Flags();
+	TBool limit1 = lfl & MLock::ELimit1;
+	TInt r;
+	switch (w.iTimeout)
+		{
+		case EDummy:
+			return KErrNone;
+		case EPoll:
+			r = w.iLock->Poll();
+			break;
+		case EInfinite:
+			w.iLock->Wait();
+			r = KErrNone;
+			break;
+		default:
+			r = w.iLock->Wait(w.iTimeout);
+			break;
+		}
+	if (limit1 && r==KErrNone)
+		w.iLock->Signal();
+	return r;
 	}
 
-void StartWaitSemThread(RThread& aT, SWaitSem& aW, TThreadPriority aP=EPriorityLess)
+void SWaitLock::Start(RThread& aT, TThreadPriority aP)
 	{
-	TInt r = aT.Create(KNullDesC, &WaitSemThread, 0x1000, 0x1000, 0x1000, &aW);
+	TRequestStatus st;
+	TInt r = aT.Create(KNullDesC, &WaitLockThread, 0x1000, 0x1000, 0x1000, this);
 	test_KErrNone(r);
 	aT.SetPriority(aP);
+	if (doCpuLocking) 
+		{
+		aT.Rendezvous(st);
+		}
 	aT.Resume();
+	if (doCpuLocking) 
+		{
+		User::WaitForRequest(st);
+		test_KErrNone(st.Int());
+		}
 	}
 
-void WaitForWaitSemThread(RThread& aT, TInt aResult)
+void SWaitLock::Wait(RThread& aT, TInt aResult)
 	{
 	TRequestStatus s;
 	aT.Logon(s);
@@ -240,32 +657,67 @@
 	CLOSE_AND_WAIT(aT);
 	}
 
-TInt DummyThread(TAny*)
+TInt SWaitLock::DoTest2(RThread& aT, TInt aTimeout, TInt aResult, TThreadPriority aP)
 	{
-	return 0;
+	TTime initial;
+	TTime final;
+	iTimeout = aTimeout;
+	initial.HomeTime();
+	Start(aT, aP);
+	Wait(aT, aResult);
+	final.HomeTime();
+	TInt elapsed = I64INT(final.Int64()-initial.Int64());
+	return elapsed;
+	}
+
+void SWaitLock::TestSignalled()
+	{
+	TInt r = iLock->Poll();
+	if (r == KErrNotSupported)
+		r = iLock->Wait(1);
+	test_KErrNone(r);
 	}
 
-void TestSemaphore2()
+void SWaitLock::TestNotSignalled()
+	{
+	TInt r = iLock->Poll();
+	if (r == KErrNotSupported)
+		r = iLock->Wait(1);
+	test_Equal(KErrTimedOut, r);
+	}
+
+void SWaitLock::TestState()
 	{
-	test.Start(_L("Test semaphore wait with timeout"));
-	SWaitSem ws;
+	if (iLock->Flags() & MLock::ELimit1)
+		TestSignalled();	// not signalled afterwards
+	else
+		TestNotSignalled();
+	}
+
+void SWaitLock::Test2()
+	{
+	test.Start(_L("SWaitLock::Test2"));
 	RThread t;
+	RThread t2;
 	TTime initial;
 	TTime final;
-	TInt elapsed=0;
-	TInt r = ws.iSem.CreateLocal(0);
-	test_KErrNone(r);
+	TInt elapsed = 0;
+	TInt r = 0;
+	TInt lfl = iLock->Flags();
+	TBool nestable = lfl & MLock::ENestable;
+	TBool limit1 = lfl & MLock::ELimit1;
+	TBool pollable = lfl & MLock::EPollable;
+	TBool to = lfl & MLock::ETimeoutAvail;
+	TBool lto = lfl & MLock::ELooseTimeout;
 
 	RThread().SetPriority(EPriorityAbsoluteVeryLow);
 	TInt threadcount=0;
+	iTimeout = EDummy;
 	initial.HomeTime();
 	while (elapsed<1000000)
 		{
-		r = t.Create(KNullDesC, &DummyThread, 0x1000, NULL, NULL);
-		test_KErrNone(r);
-		t.SetPriority(EPriorityMore);
-		t.Resume();
-		t.Close();
+		Start(t, EPriorityMore);
+		Wait(t, KErrNone);
 		++threadcount;
 		final.HomeTime();
 		elapsed = I64INT(final.Int64()-initial.Int64());
@@ -275,125 +727,735 @@
 	TInt overhead = 1000000/threadcount;
 	test.Printf(_L("overhead = %dus\n"),overhead);
 
-	ws.iTimeout=1000000;
-	initial.HomeTime();
-	StartWaitSemThread(t, ws);
-	WaitForWaitSemThread(t, KErrTimedOut);
-	final.HomeTime();
-	elapsed = I64INT(final.Int64()-initial.Int64());
-	test.Printf(_L("Time taken = %dus\n"), elapsed);
-	test(elapsed>=900000+overhead && elapsed<1500000+overhead);
+	iLock->Wait();
 
-	ws.iTimeout=-1;
-	initial.HomeTime();
-	StartWaitSemThread(t, ws);
-	WaitForWaitSemThread(t, KErrArgument);
-	final.HomeTime();
-	elapsed = I64INT(final.Int64()-initial.Int64());
-	test.Printf(_L("Time taken = %dus\n"), elapsed);
+	if (to)
+		{
+		elapsed = DoTest2(t, 1000000, KErrTimedOut);
+		test.Printf(_L("Time taken = %dus\n"), elapsed);
+		test(elapsed>=900000+overhead && elapsed<1500000+overhead);
+		elapsed = DoTest2(t, -99, KErrArgument);
+		test.Printf(_L("Time taken = %dus\n"), elapsed);
+		}
 
-	ws.iTimeout=2000000;
-	initial.HomeTime();
-	StartWaitSemThread(t, ws);
-	User::After(1000000);
-	ws.iSem.Signal();
-	WaitForWaitSemThread(t, KErrNone);
-	final.HomeTime();
-	elapsed = I64INT(final.Int64()-initial.Int64());
-	test.Printf(_L("Time taken = %dus\n"), elapsed);
-	test(elapsed>=900000+overhead && elapsed<1500000+overhead);
+	if (pollable)
+		{
+		test.Printf(_L("Testing Poll() function\n"));
+		r = iLock->Poll();
+		test_Equal((nestable ? KErrNone : KErrTimedOut), r);
+		if (nestable)
+			{
+			iTimeout=EPoll;
+			r = iLock->Poll();
+			test_KErrNone(r);
+			iLock->Signal();
+			Start(t, EPriorityMore);
+			Wait(t, KErrTimedOut);
+			}
+		iLock->Signal();
+		if (nestable)
+			{
+			iTimeout=EPoll;
+			r = iLock->Poll();
+			test_KErrNone(r);
+			iLock->Signal();
+			Start(t, EPriorityMore);
+			Wait(t, KErrTimedOut);
+			iLock->Signal();
+			Start(t, EPriorityMore);
+			Wait(t, KErrNone);
+			}
+		r = iLock->Poll();
+		test_KErrNone(r);
+		if (!nestable)
+			{
+			r = iLock->Poll();
+			test_Equal(KErrTimedOut, r);
+			iLock->Signal();
+			if (!limit1)
+				{
+				iLock->Signal();
+				r = iLock->Poll();
+				test_KErrNone(r);
+				}
+			r = iLock->Poll();
+			test_KErrNone(r);
+			r = iLock->Poll();
+			test_Equal(KErrTimedOut, r);
+			}
+		elapsed = DoTest2(t, EPoll, KErrTimedOut);
+		test.Printf(_L("Time taken = %dus\n"), elapsed);
+		test(elapsed<=50000+3*overhead);
+		iLock->Signal();
+		elapsed = DoTest2(t, EPoll, KErrNone);
+		test.Printf(_L("Time taken = %dus\n"), elapsed);
+		test(elapsed<=50000+3*overhead);
+		TestState();
+		iLock->Signal();
+		r = LockCurrentThreadToCpu0(ETrue);
+		test_KErrNone(r);
+		Start(t, EPriorityMuchMore);
+		Start(t2, EPriorityMore);
+		test_Equal(EExitKill, t2.ExitType());
+		test_Equal(EExitKill, t.ExitType());
+		Wait(t2, limit1 ? KErrNone : KErrTimedOut);
+		Wait(t, KErrNone);
+		r = UnlockCurrentThreadToCpu0(ETrue);
+		test_KErrNone(r);
+		TestState();
+		}
+	else
+		{
+		test.Printf(_L("Poll() function not supported\n"));
+		}
 
-	ws.iTimeout=100000;
-	StartWaitSemThread(t, ws, EPriorityMore);
-	t.Suspend();
-	ws.iSem.Signal();
-	User::After(200000);
-	t.Resume();
-	WaitForWaitSemThread(t, KErrTimedOut);
-	test_KErrNone(ws.iSem.Wait(1));
+	if (to)
+		{
+		iTimeout=2000000;
+		initial.HomeTime();
+		Start(t);
+		User::After(1000000);
+		iLock->Signal();
+		Wait(t, KErrNone);
+		final.HomeTime();
+		elapsed = I64INT(final.Int64()-initial.Int64());
+		test.Printf(_L("Time taken = %dus\n"), elapsed);
+		test(elapsed>=900000+overhead && elapsed<1500000+overhead);
+		TestState();
 
-	ws.iTimeout=100000;
-	StartWaitSemThread(t, ws, EPriorityMore);
-	t.Suspend();
-	ws.iSem.Signal();
-	User::After(50000);
-	t.Resume();
-	WaitForWaitSemThread(t, KErrNone);
-	test_Equal(KErrTimedOut, ws.iSem.Wait(1));
+		r = LockCurrentThreadToCpu0(ETrue);
+		test_KErrNone(r);
 
-	RThread t2;
-	ws.iTimeout=100000;
-	StartWaitSemThread(t, ws, EPriorityMuchMore);
-	StartWaitSemThread(t2, ws, EPriorityMore);
-	t.Suspend();
-	ws.iSem.Signal();
-	test_Equal(EExitKill, t2.ExitType());
-	test_Equal(EExitPending, t.ExitType());
-	t.Resume();
-	WaitForWaitSemThread(t, KErrTimedOut);
-	WaitForWaitSemThread(t2, KErrNone);
-	test_Equal(KErrTimedOut, ws.iSem.Wait(1));
+		if (!lto)
+			{
+			iTimeout=100000;
+			Start(t, EPriorityMore);
+			t.Suspend();
+			iLock->Signal();
+			User::After(200000);
+			t.Resume();
+			Wait(t, KErrTimedOut);
+			TestSignalled();
 
-	ws.iTimeout=1000000;
-	initial.HomeTime();
-	StartWaitSemThread(t2, ws, EPriorityMore);
-	StartWaitSemThread(t, ws, EPriorityMuchMore);
-	ws.iSem.Signal();
-	WaitForWaitSemThread(t, KErrNone);
-	final.HomeTime();
-	elapsed = I64INT(final.Int64()-initial.Int64());
-	test.Printf(_L("Time taken = %dus\n"), elapsed);
-	WaitForWaitSemThread(t2, KErrTimedOut);
-	final.HomeTime();
-	elapsed = I64INT(final.Int64()-initial.Int64());
-	test.Printf(_L("Time taken = %dus\n"), elapsed);
-	test(elapsed>=900000+2*overhead && elapsed<1500000+2*overhead);
+			iTimeout=100000;
+			Start(t, EPriorityMore);
+			t.Suspend();
+			iLock->Signal();
+			User::After(50000);
+			t.Resume();
+			Wait(t, KErrNone);
+			TestState();
+
+			iTimeout=100000;
+			Start(t, EPriorityMuchMore);
+			Start(t2, EPriorityMore);
+			t.Suspend();
+			iLock->Signal();
+			test_Equal(EExitKill, t2.ExitType());
+			test_Equal(EExitPending, t.ExitType());
+			t.Resume();
+			Wait(t, limit1 ? KErrNone : KErrTimedOut);
+			Wait(t2, KErrNone);
+			TestState();
+			}
 
-	ws.iTimeout=1000000;
-	initial.HomeTime();
-	StartWaitSemThread(t2, ws, EPriorityMore);
-	StartWaitSemThread(t, ws, EPriorityMuchMore);
-	WaitForWaitSemThread(t, KErrTimedOut);
-	final.HomeTime();
-	elapsed = I64INT(final.Int64()-initial.Int64());
-	test.Printf(_L("Time taken = %dus\n"), elapsed);
-	WaitForWaitSemThread(t2, KErrTimedOut);
-	final.HomeTime();
-	elapsed = I64INT(final.Int64()-initial.Int64());
-	test.Printf(_L("Time taken = %dus\n"), elapsed);
-	test(elapsed>=900000+2*overhead && elapsed<1500000+2*overhead);
+		iTimeout=1000000;
+		initial.HomeTime();
+		Start(t2, EPriorityMore);
+		Start(t, EPriorityMuchMore);
+		iLock->Signal();
+		Wait(t, KErrNone);
+		final.HomeTime();
+		elapsed = I64INT(final.Int64()-initial.Int64());
+		test.Printf(_L("Time taken = %dus\n"), elapsed);
+		Wait(t2, limit1 ? KErrNone : KErrTimedOut);
+		final.HomeTime();
+		elapsed = I64INT(final.Int64()-initial.Int64());
+		test.Printf(_L("Time taken = %dus\n"), elapsed);
+		if (!limit1)
+			{
+			test(elapsed>=900000+2*overhead && elapsed<1500000+2*overhead);
+			}
+		TestState();
+
+		iTimeout=1000000;
+		initial.HomeTime();
+		Start(t2, EPriorityMore);
+		Start(t, EPriorityMuchMore);
+		Wait(t, KErrTimedOut);
+		final.HomeTime();
+		elapsed = I64INT(final.Int64()-initial.Int64());
+		test.Printf(_L("Time taken = %dus\n"), elapsed);
+		Wait(t2, KErrTimedOut);
+		final.HomeTime();
+		elapsed = I64INT(final.Int64()-initial.Int64());
+		test.Printf(_L("Time taken = %dus\n"), elapsed);
+		test(elapsed>=900000+2*overhead && elapsed<1500000+2*overhead);
 
-	ws.iTimeout=1000000;
-	initial.HomeTime();
-	StartWaitSemThread(t2, ws, EPriorityMore);
-	StartWaitSemThread(t, ws, EPriorityMuchMore);
-	t.Kill(299792458);
-	WaitForWaitSemThread(t2, KErrTimedOut);
-	WaitForWaitSemThread(t, 299792458);
-	final.HomeTime();
-	elapsed = I64INT(final.Int64()-initial.Int64());
-	test.Printf(_L("Time taken = %dus\n"), elapsed);
-	test(elapsed>=900000+2*overhead && elapsed<1500000+2*overhead);
+		iTimeout=1000000;
+		initial.HomeTime();
+		Start(t2, EPriorityMore);
+		Start(t, EPriorityMuchMore);
+		t.Kill(299792458);
+		Wait(t2, KErrTimedOut);
+		Wait(t, 299792458);
+		final.HomeTime();
+		elapsed = I64INT(final.Int64()-initial.Int64());
+		test.Printf(_L("Time taken = %dus\n"), elapsed);
+		test(elapsed>=900000+2*overhead && elapsed<1500000+2*overhead);
 
-	ws.iTimeout=1000000;
-	initial.HomeTime();
-	StartWaitSemThread(t, ws, EPriorityMore);
-	StartWaitSemThread(t2, ws, EPriorityMuchMore);
-	test_Equal(EExitPending, t.ExitType());
-	test_Equal(EExitPending, t2.ExitType());
-	ws.iSem.Close();
-	test_Equal(EExitKill, t.ExitType());
-	test_Equal(EExitKill, t2.ExitType());
-	WaitForWaitSemThread(t2, KErrGeneral);
-	WaitForWaitSemThread(t, KErrGeneral);
-	final.HomeTime();
-	elapsed = I64INT(final.Int64()-initial.Int64());
-	test.Printf(_L("Time taken = %dus\n"), elapsed);
-	test(elapsed<=50000+3*overhead);
-
+		iTimeout=1000000;
+		initial.HomeTime();
+		Start(t, EPriorityMore);
+		Start(t2, EPriorityMuchMore);
+		test_Equal(EExitPending, t.ExitType());
+		test_Equal(EExitPending, t2.ExitType());
+		iLock->Release();
+		test_Equal(EExitKill, t.ExitType());
+		test_Equal(EExitKill, t2.ExitType());
+		Wait(t2, KErrGeneral);
+		Wait(t, KErrGeneral);
+		final.HomeTime();
+		elapsed = I64INT(final.Int64()-initial.Int64());
+		test.Printf(_L("Time taken = %dus\n"), elapsed);
+		test(elapsed<=50000+3*overhead);
+		r = UnlockCurrentThreadToCpu0(ETrue);
+		test_KErrNone(r);
+		}
+	else
+		{
+		test.Printf(_L("Timed waits not supported\n"));
+		iLock->Release();
+		}
 	test.End();
 	}
 
+volatile TBool NoRepeat = EFalse;
+void TestPollTimeout()
+	{
+	SWaitLock w;
+	do	{
+		test.Printf(_L("TestPollTimeout - RSemaphore\n"));
+		LockS ls;
+		w.iLock = &ls;
+		w.Test2();	// Release()s ls
+		} while(NoRepeat);
+	do	{
+		test.Printf(_L("TestPollTimeout - RMutex\n"));
+		LockM lm;
+		w.iLock = &lm;
+		w.Test2();	// Release()s lm
+		} while(NoRepeat);
+	do	{
+		test.Printf(_L("TestPollTimeout - RFastLock\n"));
+		LockFL fl;
+		w.iLock = &fl;
+		w.Test2();	// Release()s fl
+		} while(NoRepeat);
+	}
+
+
+/*----------------------------------------------------------------------------*/
+class CMXThreadGrp;
+
+struct SStats
+	{
+	SStats();
+	void Add(TInt aValue);
+	void Add(const SStats& aS);
+	TInt Count() const {return iN;}
+	TInt Min() const;
+	TInt Max() const;
+	TInt Mean() const;
+
+	TInt64	iSum;
+	TInt	iMin;
+	TInt	iMax;
+	TInt	iN;
+	TInt	iSp;
+	};
+
+SStats::SStats()
+	{
+	iSum = 0;
+	iMax = KMinTInt;
+	iMin = ~iMax;
+	iN = 0;
+	iSp = 0;
+	}
+
+void SStats::Add(TInt aValue)
+	{
+	TInt64 v = aValue;
+	iSum += v;
+	++iN;
+	if (aValue > iMax)
+		iMax = aValue;
+	if (aValue < iMin)
+		iMin = aValue;
+	}
+
+void SStats::Add(const SStats& a)
+	{
+	iN += a.iN;
+	iSum += a.iSum;
+	if (a.iMax > iMax)
+		iMax = a.iMax;
+	if (a.iMin < iMin)
+		iMin = a.iMin;
+	}
+
+TInt SStats::Min() const
+	{return iN ? iMin : 0;}
+
+TInt SStats::Max() const
+	{return iN ? iMax : 0;}
+
+TInt SStats::Mean() const
+	{
+	if (iN==0)
+		return 0;
+	return (TInt)(iSum/TInt64(iN));
+	}
+
+TUint32 ticks_to_us(TUint32 aTicks, TUint32 aF)
+	{
+	TUint64 x = aTicks;
+	TUint64 f = aF;
+	x *= TUint64(1000000);
+	x += (f>>1);
+	x /= f;
+	return I64LOW(x);
+	}
+
+class CMXThread : public CBase
+	{
+private:
+	CMXThread();
+	~CMXThread();
+	static CMXThread* New(CMXThreadGrp* aG, TUint32 aId, TUint32 aL, TUint32 aD);
+	void Start();
+	void Wait();
+	TInt Construct(CMXThreadGrp* aG, TUint32 aId, TUint32 aL, TUint32 aD);
+	TInt Steps();
+	TInt Action();
+	TInt Run();
+	static TInt ThreadFunc(TAny*);
+	void PrintStats();
+private:
+	TUint64 iSeed;
+	RThread	iThread;
+	TRequestStatus iExitStatus;
+	CMXThreadGrp* iG;
+	LFSR* iDummyLfsr;
+	TUint32 iId;
+	TUint32 iLambda;
+	TUint32 iDummySteps;
+	TInt iTotalSteps;
+	TInt iIterations;
+	TInt iPolls;
+	TInt iPollFails;
+	SStats iStats;
+	SStats iTimeoutStats;
+private:
+	friend class CMXThreadGrp;
+	};
+
+class CMXThreadGrp : public CBase
+	{
+public:
+	static CMXThreadGrp* New(MLock* aLock, TInt aNThreads, TUint32 aLambda, TUint32 aDummySteps, TUint32 aTime);
+	CMXThreadGrp();
+	~CMXThreadGrp();
+	TBool Run();
+	void PrintStats();
+private:
+	TInt Construct(MLock* aLock, TInt aNThreads, TUint32 aLambda, TUint32 aDummySteps, TUint32 aTime);
+private:
+	TInt iNThreads;
+	CMXThread** iThreads;
+	MLock* iLock;
+	LFSR* iLfsr;
+	LFSR* iLfsr0;
+	TUint32 iNTickPeriod;
+	TUint32 iFCF;
+	TUint32 iNTicks;
+	TInt iTotalSteps;
+	TInt iIterations;
+	TInt iPolls;
+	TInt iPollFails;
+	SStats iStats;
+	SStats iTimeoutStats;
+private:
+	friend class CMXThread;
+	};
+
+CMXThread::CMXThread()
+	{
+	iThread.SetHandle(0);
+	}
+
+CMXThread::~CMXThread()
+	{
+	delete iDummyLfsr;
+	if (iThread.Handle())
+		{
+		if (iThread.ExitType() == EExitPending)
+			{
+			iThread.Kill(0);
+			Wait();
+			}
+		CLOSE_AND_WAIT(iThread);
+		}
+	}
+
+void CMXThread::PrintStats()
+	{
+	test.Printf(_L("Thread %d:\n"), iId);
+	test.Printf(_L(" ST:%10d IT:%10d P:%10d PF:%10d TO:%10d\n"), iTotalSteps, iIterations, iPolls, iPollFails, iTimeoutStats.Count());
+	TUint32 min, max, mean;
+	min = ticks_to_us(iStats.Min(), iG->iFCF);
+	max = ticks_to_us(iStats.Max(), iG->iFCF);
+	mean = ticks_to_us(iStats.Mean(), iG->iFCF);
+	test.Printf(_L(" Lock acquire times MIN %10d MAX %10d AVG %10d\n"), min, max, mean);
+	min = ticks_to_us(iTimeoutStats.Min(), iG->iFCF);
+	max = ticks_to_us(iTimeoutStats.Max(), iG->iFCF);
+	mean = ticks_to_us(iTimeoutStats.Mean(), iG->iFCF);
+	test.Printf(_L(" Lock timeout times MIN %10d MAX %10d AVG %10d\n"), min, max, mean);
+	}
+
+TInt CMXThread::Construct(CMXThreadGrp* aG, TUint32 aId, TUint32 aL, TUint32 aD)
+	{
+	iG = aG;
+	iId = aId;
+	iLambda = aL;
+	iDummySteps = aD;
+	iSeed = iId + 1;
+	iDummyLfsr = new LFSR(785,693);
+	if (!iDummyLfsr)
+		return KErrNoMemory;
+	TBuf<16> name = _L("TSThrd");
+	name.AppendNum(iId);
+	TInt r = iThread.Create(name, &ThreadFunc, 0x1000, NULL, this);
+	if (r!=KErrNone)
+		return r;
+	iThread.Logon(iExitStatus);
+	if (iExitStatus != KRequestPending)
+		{
+		iThread.Kill(0);
+		iThread.Close();
+		iThread.SetHandle(0);
+		return iExitStatus.Int();
+		}
+	iThread.SetPriority(EPriorityLess);
+	return KErrNone;
+	}
+
+CMXThread* CMXThread::New(CMXThreadGrp* aG, TUint32 aId, TUint32 aL, TUint32 aD)
+	{
+	CMXThread* p = new CMXThread;
+	if (p)
+		{
+		TInt r = p->Construct(aG, aId, aL, aD);
+		if (r != KErrNone)
+			{
+			delete p;
+			p = 0;
+			}
+		}
+	return p;
+	}
+
+void CMXThread::Start()
+	{
+	iThread.Resume();
+	}
+
+void CMXThread::Wait()
+	{
+	User::WaitForRequest(iExitStatus);
+	}
+
+TInt CMXThread::ThreadFunc(TAny* aPtr)
+	{
+	CMXThread& a = *(CMXThread*)aPtr;
+	return a.Run();
+	}
+
+TInt CMXThread::Steps()
+	{
+	Random(iSeed);
+	return ExpRV(iSeed, iLambda, 1);
+	}
+
+TInt CMXThread::Action()
+	{
+	Random(iSeed);
+	return I64LOW(iSeed)%3;
+	}
+
+TInt CMXThread::Run()
+	{
+	MLock* lock = iG->iLock;
+	LFSR* lfsr = iG->iLfsr;
+	TInt lfl = lock->Flags();
+	TBool pollable = lfl & MLock::EPollable;
+	TBool to = lfl & MLock::ETimeoutAvail;
+	TUint32 start_time = User::NTickCount();
+	TInt r;
+
+	FOREVER
+		{
+		TUint32 now = User::NTickCount();
+		if (now - start_time >= iG->iNTicks)
+			break;
+		++iIterations;
+		iDummyLfsr->Step(iDummySteps);
+		TInt action = Action();
+		TInt steps = Steps();
+		TUint32 initial = User::FastCounter();
+		if (action==2 && to)
+			{
+			r = lock->Wait(1000);
+			if (r!=KErrNone)
+				{
+				TUint32 final = User::FastCounter();
+				TInt elapsed = TInt(final - initial);
+				iTimeoutStats.Add(elapsed);
+				}
+			}
+		else if (action==1 && pollable)
+			{
+			++iPolls;
+			r = lock->Poll();
+			if (r!=KErrNone)
+				++iPollFails;
+			}
+		else
+			{
+			lock->Wait();
+			r = KErrNone;
+			}
+		if (r == KErrNone)
+			{
+			TUint32 final = User::FastCounter();
+			lfsr->Step(steps);
+			lock->Signal();
+			TInt elapsed = TInt(final - initial);
+			iTotalSteps += steps;
+			iStats.Add(elapsed);
+			}
+		}
+
+	return KErrNone;
+	}
+
+CMXThreadGrp* CMXThreadGrp::New(MLock* aLock, TInt aNThreads, TUint32 aLambda, TUint32 aDummySteps, TUint32 aTime)
+	{
+	CMXThreadGrp* p = new CMXThreadGrp;
+	if (p)
+		{
+		TInt r = p->Construct(aLock, aNThreads, aLambda, aDummySteps, aTime);
+		if (r != KErrNone)
+			{
+			delete p;
+			p = 0;
+			}
+		}
+	return p;
+	}
+
+CMXThreadGrp::CMXThreadGrp()
+	{
+	}
+
+TInt CMXThreadGrp::Construct(MLock* aLock, TInt aNThreads, TUint32 aLambda, TUint32 aDummySteps, TUint32 aTime)
+	{
+	iNThreads = aNThreads;
+	iLock = aLock;
+	TInt r = HAL::Get(HAL::EFastCounterFrequency, (TInt&)iFCF);
+	if (r!=KErrNone)
+		return r;
+	r = HAL::Get(HAL::ENanoTickPeriod, (TInt&)iNTickPeriod);
+	if (r!=KErrNone)
+		return r;
+	iNTicks = (aTime+iNTickPeriod-1)/iNTickPeriod;
+	iLfsr = new LFSR(785,693);
+	iLfsr0 = new LFSR(785,693);
+	if (!iLfsr || !iLfsr0)
+		return KErrNoMemory;
+	iThreads = (CMXThread**)User::AllocZ(iNThreads*sizeof(CMXThread*));
+	if (!iThreads)
+		return KErrNoMemory;
+	TInt i;
+	for (i=0; i<iNThreads; ++i)
+		{
+		iThreads[i] = CMXThread::New(this, i, aLambda, aDummySteps);
+		if (!iThreads[i])
+			return KErrNoMemory;
+		}
+	return KErrNone;
+	}
+
+CMXThreadGrp::~CMXThreadGrp()
+	{
+	delete iLfsr;
+	delete iLfsr0;
+	if (iThreads)
+		{
+		TInt i;
+		for (i=0; i<iNThreads; ++i)
+			delete iThreads[i];
+		}
+	User::Free(iThreads);
+	}
+
+TBool CMXThreadGrp::Run()
+	{
+	TInt i;
+	test.Printf(_L("Starting test with N=%d L=%d D=%d T=%d\n"), iNThreads, iThreads[0]->iLambda, iThreads[0]->iDummySteps, iNTicks);
+	for (i=0; i<iNThreads; ++i)
+		iThreads[i]->Start();
+	for (i=0; i<iNThreads; ++i)
+		iThreads[i]->Wait();
+	for (i=0; i<iNThreads; ++i)
+		{
+		iTotalSteps += iThreads[i]->iTotalSteps;
+		iIterations += iThreads[i]->iIterations;
+		iPolls += iThreads[i]->iPolls;
+		iPollFails += iThreads[i]->iPollFails;
+		iStats.Add(iThreads[i]->iStats);
+		iTimeoutStats.Add(iThreads[i]->iTimeoutStats);
+		}
+	test.Printf(_L("Total LFSR steps %d\n"), iTotalSteps);
+	iLfsr0->Step(iTotalSteps);
+	TBool ok = (*iLfsr == *iLfsr0);
+	return ok;
+	}
+
+void CMXThreadGrp::PrintStats()
+	{
+	TInt i;
+	for (i=0; i<iNThreads; ++i)
+		{
+		iThreads[i]->PrintStats();
+		}
+	test.Printf(_L("TOTALS:\n"));
+	test.Printf(_L(" ST:%10d IT:%10d P:%10d PF:%10d TO:%10d\n"), iTotalSteps, iIterations, iPolls, iPollFails, iTimeoutStats.Count());
+	TUint32 min, max, mean;
+	min = ticks_to_us(iStats.Min(), iFCF);
+	max = ticks_to_us(iStats.Max(), iFCF);
+	mean = ticks_to_us(iStats.Mean(), iFCF);
+	test.Printf(_L(" Lock acquire times MIN %10d MAX %10d AVG %10d\n"), min, max, mean);
+	min = ticks_to_us(iTimeoutStats.Min(), iFCF);
+	max = ticks_to_us(iTimeoutStats.Max(), iFCF);
+	mean = ticks_to_us(iTimeoutStats.Mean(), iFCF);
+	test.Printf(_L(" Lock timeout times MIN %10d MAX %10d AVG %10d\n"), min, max, mean);
+	}
+
+TUint32 Calibrate()
+	{
+	TUint32 fcf;
+	TInt r = HAL::Get(HAL::EFastCounterFrequency, (TInt&)fcf);
+	test_KErrNone(r);
+	LFSR* d = new LFSR(785,693);
+	test(d!=0);
+	TInt steps = 2;
+	TUint32 ticks = fcf/10;
+	TUint32 elapsed;
+	FOREVER
+		{
+		TUint32 h0 = User::FastCounter();
+		d->Step(steps);
+		TUint32 h1 = User::FastCounter();
+		elapsed = h1 - h0;
+		if (elapsed > ticks)
+			break;
+		steps *= 2;
+		}
+	delete d;
+	test.Printf(_L("%d steps in %d fast ticks\n"), steps, elapsed);
+	TUint64 x = elapsed;
+	TUint64 s = steps;
+	TUint64 y = fcf;
+	y /= x;
+	s *= y;	// steps per second
+	TUint32 res = I64LOW(s);
+	test.Printf(_L("%d steps per second\n"), res);
+	return res;
+	}
+
+void DoTMX(MLock* aLock, TInt aNThreads, TUint32 aLambda, TUint32 aDummySteps, TUint32 aTime, TBool aShouldFail=EFalse)
+	{
+	CMXThreadGrp* g = CMXThreadGrp::New(aLock, aNThreads, aLambda, aDummySteps, aTime);
+	test(g!=0);
+	TBool ok = g->Run();
+	if (aShouldFail)
+		{
+		test(!ok);
+		}
+	else
+		{
+		test(ok);
+		}
+	g->PrintStats();
+	delete g;
+	}
+
+void DoTMX(MLock* aLock, TUint32 aLambda, TUint32 aDummySteps, TUint32 aTime)
+	{
+	TInt n;
+	for (n=1; n<=4; ++n)
+		{
+		TUint32 l = (n<2) ? aLambda : (aLambda/(n-1));
+		DoTMX(aLock, n, l, aDummySteps, aTime);
+		}
+	aLock->Release();
+	}
+
+
+void TestMutualExclusion()
+	{
+	TInt ntp;
+	TInt r = HAL::Get(HAL::ENanoTickPeriod, ntp);
+	test_KErrNone(r);
+	test.Printf(_L("Nanokernel tick period = %dus\n"), ntp);
+	TUint32 sps = Calibrate();
+	TUint32 lambda = sps/2000;
+	TUint32 dummy = sps/2000;
+	TUint32 time = 5000000;
+	do	{
+		test.Printf(_L("TestMutualExclusion - RSemaphore\n"));
+		LockS ls;
+		DoTMX(&ls, lambda, dummy, time);
+		} while(NoRepeat);
+	do	{
+		test.Printf(_L("TestMutualExclusion - RSemaphore init=2\n"));
+		LockS ls2;
+		ls2.Signal();	// count=2
+		DoTMX(&ls2, 4, lambda, dummy, time, ETrue);
+		} while(NoRepeat);
+	do	{
+		test.Printf(_L("TestMutualExclusion - RMutex\n"));
+		LockM lm;
+		DoTMX(&lm, lambda, dummy, time);
+		} while(NoRepeat);
+	do	{
+		test.Printf(_L("TestMutualExclusion - RFastLock\n"));
+		LockFL fl;
+		DoTMX(&fl, lambda, dummy, time);
+		} while(NoRepeat);
+	do	{
+		test.Printf(_L("TestMutualExclusion - RCriticalSection\n"));
+		LockCS cs;
+		DoTMX(&cs, lambda, dummy, time);
+		} while(NoRepeat);
+	}
+
+
+
+
+/*----------------------------------------------------------------------------*/
 void TestSemaphore()
 	{
 /*********** TO DO ************/
@@ -417,23 +1479,23 @@
 	test.Next(_L("Producer/Consumer scenario"));
 	// Test Rsemaphore with the producer/consumer scenario	RThread thread1, thread2;
 	TRequestStatus stat1, stat2;
-	test_KErrNone(mutex.CreateLocal());
-	test_KErrNone(slotAvailable.CreateLocal(KMaxBufferSize));
-	test_KErrNone(itemAvailable.CreateLocal(0));
-	test_KErrNone(thread1.Create(_L("Thread1"),Producer,KDefaultStackSize,0x200,0x200,NULL));
-	test_KErrNone(thread2.Create(_L("Thread2"),Consumer,KDefaultStackSize,0x200,0x200,NULL));
+	test(mutex.CreateLocal()==KErrNone);
+	test(slotAvailable.CreateLocal(KMaxBufferSize)==KErrNone);
+	test(itemAvailable.CreateLocal(0)==KErrNone);
+	test(thread1.Create(_L("Thread1"),Producer,KDefaultStackSize,0x200,0x200,NULL)==KErrNone);
+	test(thread2.Create(_L("Thread2"),Consumer,KDefaultStackSize,0x200,0x200,NULL)==KErrNone);
 	thread1.Logon(stat1);
 	thread2.Logon(stat2);
-	test_Equal(KRequestPending, stat1.Int());
-	test_Equal(KRequestPending, stat2.Int());
+	test(stat1==KRequestPending);
+	test(stat2==KRequestPending);
 	thread1.Resume(); 
 	thread2.Resume();
 	User::WaitForRequest(stat1);
 	User::WaitForRequest(stat2);
-	test_KErrNone(stat1.Int());
-	test_KErrNone(stat2.Int());
+	test(stat1==KErrNone);
+	test(stat2==KErrNone);
 	for(TInt jj=0;jj<KNumProducerItems;jj++)
-		test_Equal(jj, consumerArray[jj]);		
+		test(consumerArray[jj]==jj);		
 	
 	test.Next(_L("Close"));
 	mutex.Close();
@@ -446,7 +1508,7 @@
 	{
 	RMutex m;
 	test.Start(_L("Create"));
-	test_KErrNone(m.CreateLocal());
+	test(m.CreateLocal()==KErrNone);
 
 	// Test RMutex::IsHeld()
 	test.Next(_L("IsHeld ?"));
@@ -466,7 +1528,7 @@
 void TestMutex()
 	{
 	test.Start(_L("Create"));
-	test_KErrNone(mutex.CreateLocal());
+	test(mutex.CreateLocal()==KErrNone);
 	
 	test.Next(_L("Threads writing to arrays test"));
 //
@@ -480,19 +1542,19 @@
 //
 	arrayIndex=0;
 	RThread thread1,thread2;	
-	test_KErrNone(thread1.Create(_L("Thread1"),MutexThreadEntryPoint1,KDefaultStackSize,0x2000,0x2000,NULL));
-	test_KErrNone(thread2.Create(_L("Thread2"),MutexThreadEntryPoint2,KDefaultStackSize,0x2000,0x2000,NULL));			 
+	test(thread1.Create(_L("Thread1"),MutexThreadEntryPoint1,KDefaultStackSize,0x2000,0x2000,NULL)==KErrNone);
+	test(thread2.Create(_L("Thread2"),MutexThreadEntryPoint2,KDefaultStackSize,0x2000,0x2000,NULL)==KErrNone);			 
 	TRequestStatus stat1,stat2;
 	thread1.Logon(stat1);
 	thread2.Logon(stat2);
-	test_Equal(KRequestPending, stat1.Int());
-	test_Equal(KRequestPending, stat2.Int());
+	test(stat1==KRequestPending);
+	test(stat2==KRequestPending);
 	thread1.Resume(); 
 	thread2.Resume();
 	User::WaitForRequest(stat1);
 	User::WaitForRequest(stat2);
-	test_KErrNone(stat1.Int());
-	test_KErrNone(stat2.Int()); 
+	test(stat1==KErrNone);
+	test(stat2==KErrNone); 
 	TInt thread1ActualCount=0; 
 	TInt thread2ActualCount=0;
 	TInt ii=0;
@@ -504,11 +1566,11 @@
 			thread2ActualCount++;
 		ii++;
 		}
-	test.Printf(_L("T1 %d T1ACT %d T2 %d T2ACT %d"),thread1Count,thread1ActualCount,thread2Count,thread2ActualCount);
-	test_Equal(thread1Count, thread1ActualCount);
-	test_Equal(thread2Count, thread2ActualCount);
-	test_Equal(thread2Count, thread1Count);
-	test_Equal((KMaxArraySize>>1), thread1Count);
+	test.Printf(_L("T1 %d T1ACT %d T2 %d T2ACT %d\n"),thread1Count,thread1ActualCount,thread2Count,thread2ActualCount);
+	test(thread1ActualCount==thread1Count);
+	test(thread2ActualCount==thread2Count);
+	test(thread1Count==thread2Count);
+	test(thread1Count==(KMaxArraySize>>1));
 	
 	test.Next(_L("Close"));
 	CLOSE_AND_WAIT(thread1);
@@ -524,7 +1586,7 @@
 	{
 	
 	test.Start(_L("Create"));
-	test_KErrNone(criticalSn.CreateLocal());
+	test(criticalSn.CreateLocal()==KErrNone);
 
 /***************** TO DO ***********************
 
@@ -553,20 +1615,21 @@
 // threads think.
 //
 	arrayIndex=0;
+
 	RThread thread1,thread2;	
-	test_KErrNone(thread1.Create(_L("Thread1"),CriticalSnThreadEntryPoint1,KDefaultStackSize,0x2000,0x2000,NULL));
-	test_KErrNone(thread2.Create(_L("Thread2"),CriticalSnThreadEntryPoint2,KDefaultStackSize,0x2000,0x2000,NULL));			 
+	test(thread1.Create(_L("Thread1"),CriticalSnThreadEntryPoint1,KDefaultStackSize,0x2000,0x2000,NULL)==KErrNone);
+	test(thread2.Create(_L("Thread2"),CriticalSnThreadEntryPoint2,KDefaultStackSize,0x2000,0x2000,NULL)==KErrNone);			 
 	TRequestStatus stat1,stat2;
 	thread1.Logon(stat1);
 	thread2.Logon(stat2);
-	test_Equal(KRequestPending, stat1.Int());
-	test_Equal(KRequestPending, stat2.Int());
+	test(stat1==KRequestPending);
+	test(stat2==KRequestPending);
 	thread1.Resume(); 
 	thread2.Resume();
 	User::WaitForRequest(stat1);
 	User::WaitForRequest(stat2);
-	test_KErrNone(stat1.Int());
-	test_KErrNone(stat2.Int()); 
+	test(stat1==KErrNone);
+	test(stat2==KErrNone); 
 	TInt thread1ActualCount=0; 
 	TInt thread2ActualCount=0;
 	TInt ii=0;
@@ -578,10 +1641,10 @@
 			thread2ActualCount++;
 		ii++;
 		}
-	test_Equal(thread1Count, thread1ActualCount);
-	test_Equal(thread2Count, thread2ActualCount);
-	test_Equal(thread2Count, thread1Count);
-	test_Equal((KMaxArraySize>>1), thread1Count);
+	test(thread1ActualCount==thread1Count);
+	test(thread2ActualCount==thread2Count);
+	test(thread1Count==thread2Count);
+	test(thread1Count==(KMaxArraySize>>1));
 
 	test.Next(_L("Close"));
 	CLOSE_AND_WAIT(thread1);
@@ -593,22 +1656,13 @@
 
 GLDEF_C TInt E32Main()
 	{	
-	TInt cpus = UserSvr::HalFunction(EHalGroupKernel, EKernelHalNumLogicalCpus, 0, 0);
-	if (cpus != 1)
-		{
-		test(cpus>1);
-		// This test will require compatibility mode (and probably other changes)
-		// to work on SMP - it depends on explicit scheduling order.
-		test.Printf(_L("T_SEMUTX skipped, does not work on SMP\n"));
-		return KErrNone;
-		}	
-	
 
 	test.Title();
  	__UHEAP_MARK;
+	TestMutualExclusion();
+	TestPollTimeout();
 	test.Start(_L("Test RSemaphore"));
 	TestSemaphore();
-	TestSemaphore2();
 	test.Next(_L("Test RMutex"));
 	TestMutex();
 	TestMutex2();