--- /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();
+ }