kerneltest/e32test/nkernsa/fastsem.cpp
changeset 0 a41df078684a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/nkernsa/fastsem.cpp	Mon Oct 19 15:55:17 2009 +0100
@@ -0,0 +1,198 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32test\nkernsa\fastsem.cpp
+// 
+//
+
+#define __INCLUDE_NTHREADBASE_DEFINES__
+
+#include <nktest/nkutils.h>
+
+void CheckSemaphoreCount(NFastSemaphore* aS, TInt aExpected)
+	{
+	TInt w = 0;
+	TInt r;
+	do	{
+		r = WaitWithTimeout(aS, KMinTimeout);
+		TEST_RESULT1(r==KErrNone || r==KErrTimedOut, "Invalid return code %d", r);
+		if (r == KErrNone)
+			++w;
+		} while(r == KErrNone);
+	TEST_RESULT2(w==aExpected, "Signalled %d, Waited %d", aExpected, w);
+	}
+
+void FSTest1(TAny* a)
+	{
+	TInt n = (TInt)a;
+	NFastSemaphore s(0);
+
+	TInt i;
+	for (i=0; i<n; ++i) NKern::FSSignal(&s);
+	CheckSemaphoreCount(&s, n);
+	NKern::FSSignalN(&s, n);
+	CheckSemaphoreCount(&s, n);
+	}
+
+#define DO_FS_TEST1(n,a)	CreateThreadAndWaitForExit("FSTest1", &FSTest1, 12, (TAny*)(n), 0, -1, (a))
+
+struct SFSTest2Info
+	{
+	NFastSemaphore iSem;
+	volatile TInt iBlockCount;
+	volatile TInt iSignals;
+	volatile TInt iWaits;
+	volatile TBool iStart;
+	volatile TBool iStop;
+	};
+
+void FSTest2Signaller0(TAny* a)
+	{
+	SFSTest2Info& info = *(SFSTest2Info*)a;
+	while (!info.iStart)
+		{
+		}
+//	NThreadBase* t = info.iSem.iOwningThread;
+	while (!info.iStop)
+		{
+		++info.iBlockCount;
+		__e32_atomic_add_ord32(&info.iSignals, 1);
+		NKern::FSSignal(&info.iSem);
+		}
+	TEST_PRINT1("Ran %d times", info.iBlockCount);
+	}
+
+#ifdef __SMP__
+class NKTest
+	{
+public:
+	static TBool ThreadIsBlocked(NThreadBase* aT)
+		{ return aT->iWaitState.ThreadIsBlocked(); }
+	};
+#endif
+
+void FSTest2Signaller(TAny* a)
+	{
+	SFSTest2Info& info = *(SFSTest2Info*)a;
+	while (!info.iStart)
+		{
+		}
+	NThreadBase* t = info.iSem.iOwningThread;
+	TInt count0=0;
+	TInt countneg=0;
+	TInt blocked=0;
+	TInt prev_block_count = info.iBlockCount;
+	TInt tries = 1;
+	TUint32 seed[2];
+	seed[0] = NKern::CurrentCpu()+1;
+	seed[1] = 0;
+	while (!info.iStop)
+		{
+		TInt c = info.iSem.iCount;
+		if (c>=1)
+			continue;
+		if (--tries==0)
+			{
+			TInt bc;
+			do	{
+				bc = info.iBlockCount;
+				} while (bc<=prev_block_count);
+			prev_block_count = bc;
+			tries = random(seed) & 127;
+			tries += 71;
+			}
+		TUint32 x = random(seed) & 63;
+		while (x)
+			--x;
+		c = info.iSem.iCount;
+		NKern::FSSignal(&info.iSem);
+		__e32_atomic_add_ord32(&info.iSignals, 1);
+		if (c==0) ++count0;
+		if (c<0) ++countneg;
+#ifdef __SMP__
+		if (NKTest::ThreadIsBlocked(t)) ++blocked;
+#else
+		if (t->iNState == NThread::EWaitFastSemaphore) ++blocked;
+#endif
+		}
+	TEST_PRINT1("Count =0 %d times", count0);
+	TEST_PRINT1("Count <0 %d times", countneg);
+	TEST_PRINT1("Blocked  %d times", blocked);
+	}
+
+void FSTest2(TAny* a)
+	{
+	SFSTest2Info& info = *(SFSTest2Info*)a;
+	NFastSemaphore exitSem(0);
+	NKern::FSSetOwner(&info.iSem, 0);
+	info.iBlockCount = 0;
+	info.iWaits = 0;
+	info.iSignals = 0;
+	info.iStart = FALSE;
+	info.iStop = FALSE;
+	TInt cpu;
+	TInt threads = 0;
+	TInt this_cpu = NKern::CurrentCpu();
+	for_each_cpu(cpu)
+		{
+		if (cpu==this_cpu)
+			CreateThreadSignalOnExit("FSTest2Sig0", &FSTest2Signaller0, 11, a, 0, KSmallTimeslice, &exitSem, cpu);
+		else
+			CreateThreadSignalOnExit("FSTest2Sig", &FSTest2Signaller, 12, a, 0, KSmallTimeslice, &exitSem, cpu);
+		++threads;
+		}
+
+	info.iStart = TRUE;
+	while(info.iWaits < 1048576)
+		{
+		NKern::FSWait(&info.iSem);
+		++info.iWaits;
+		}
+
+	info.iStop = TRUE;
+	while (threads--)
+		NKern::FSWait(&exitSem);
+	TEST_PRINT1("Leftover signals %d", info.iSignals-info.iWaits);
+	TInt r;
+	do	{
+		r = WaitWithTimeout(&info.iSem, KMinTimeout);
+		TEST_RESULT1(r==KErrNone || r==KErrTimedOut, "Invalid return code %d", r);
+		if (r == KErrNone)
+			++info.iWaits;
+		} while(r == KErrNone);
+	TEST_PRINT2("Signalled %d, Waited %d", info.iSignals, info.iWaits);
+	TEST_RESULT(info.iWaits==info.iSignals, "MISMATCH!");
+	}
+
+void DoFsTest2()
+	{
+	SFSTest2Info info;
+	CreateThreadAndWaitForExit("FSTest2", &FSTest2, 12, (TAny*)&info, 0, KSmallTimeslice, 0);
+	}
+
+
+void TestFastSemaphore()
+	{
+	TEST_PRINT("Testing Fast Semaphores...");
+
+	TInt cpu;
+	for_each_cpu(cpu)
+		{
+		DO_FS_TEST1(0,cpu);
+		DO_FS_TEST1(1,cpu);
+		DO_FS_TEST1(2,cpu);
+		DO_FS_TEST1(13,cpu);
+		}
+
+	DoFsTest2();
+	}