os/kernelhwsrv/kerneltest/e32test/nkernsa/fastsem.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of the License "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 // e32test\nkernsa\fastsem.cpp
    15 // 
    16 //
    17 
    18 #define __INCLUDE_NTHREADBASE_DEFINES__
    19 
    20 #include <nktest/nkutils.h>
    21 
    22 void CheckSemaphoreCount(NFastSemaphore* aS, TInt aExpected)
    23 	{
    24 	TInt w = 0;
    25 	TInt r;
    26 	do	{
    27 		r = WaitWithTimeout(aS, KMinTimeout);
    28 		TEST_RESULT1(r==KErrNone || r==KErrTimedOut, "Invalid return code %d", r);
    29 		if (r == KErrNone)
    30 			++w;
    31 		} while(r == KErrNone);
    32 	TEST_RESULT2(w==aExpected, "Signalled %d, Waited %d", aExpected, w);
    33 	}
    34 
    35 void FSTest1(TAny* a)
    36 	{
    37 	TInt n = (TInt)a;
    38 	NFastSemaphore s(0);
    39 
    40 	TInt i;
    41 	for (i=0; i<n; ++i) NKern::FSSignal(&s);
    42 	CheckSemaphoreCount(&s, n);
    43 	NKern::FSSignalN(&s, n);
    44 	CheckSemaphoreCount(&s, n);
    45 	}
    46 
    47 #define DO_FS_TEST1(n,a)	CreateThreadAndWaitForExit("FSTest1", &FSTest1, 12, (TAny*)(n), 0, -1, (a))
    48 
    49 struct SFSTest2Info
    50 	{
    51 	NFastSemaphore iSem;
    52 	volatile TInt iBlockCount;
    53 	volatile TInt iSignals;
    54 	volatile TInt iWaits;
    55 	volatile TBool iStart;
    56 	volatile TBool iStop;
    57 	};
    58 
    59 void FSTest2Signaller0(TAny* a)
    60 	{
    61 	SFSTest2Info& info = *(SFSTest2Info*)a;
    62 	while (!info.iStart)
    63 		{
    64 		}
    65 //	NThreadBase* t = info.iSem.iOwningThread;
    66 	while (!info.iStop)
    67 		{
    68 		++info.iBlockCount;
    69 		__e32_atomic_add_ord32(&info.iSignals, 1);
    70 		NKern::FSSignal(&info.iSem);
    71 		}
    72 	TEST_PRINT1("Ran %d times", info.iBlockCount);
    73 	}
    74 
    75 #ifdef __SMP__
    76 class NKTest
    77 	{
    78 public:
    79 	static TBool ThreadIsBlocked(NThreadBase* aT)
    80 		{ return aT->iWaitState.ThreadIsBlocked(); }
    81 	};
    82 #endif
    83 
    84 void FSTest2Signaller(TAny* a)
    85 	{
    86 	SFSTest2Info& info = *(SFSTest2Info*)a;
    87 	while (!info.iStart)
    88 		{
    89 		}
    90 	NThreadBase* t = info.iSem.iOwningThread;
    91 	TInt count0=0;
    92 	TInt countneg=0;
    93 	TInt blocked=0;
    94 	TInt prev_block_count = info.iBlockCount;
    95 	TInt tries = 1;
    96 	TUint32 seed[2];
    97 	seed[0] = NKern::CurrentCpu()+1;
    98 	seed[1] = 0;
    99 	while (!info.iStop)
   100 		{
   101 		TInt c = info.iSem.iCount;
   102 		if (c>=1)
   103 			continue;
   104 		if (--tries==0)
   105 			{
   106 			TInt bc;
   107 			do	{
   108 				bc = info.iBlockCount;
   109 				} while (bc<=prev_block_count);
   110 			prev_block_count = bc;
   111 			tries = random(seed) & 127;
   112 			tries += 71;
   113 			}
   114 		TUint32 x = random(seed) & 63;
   115 		while (x)
   116 			--x;
   117 		c = info.iSem.iCount;
   118 		NKern::FSSignal(&info.iSem);
   119 		__e32_atomic_add_ord32(&info.iSignals, 1);
   120 		if (c==0) ++count0;
   121 		if (c<0) ++countneg;
   122 #ifdef __SMP__
   123 		if (NKTest::ThreadIsBlocked(t)) ++blocked;
   124 #else
   125 		if (t->iNState == NThread::EWaitFastSemaphore) ++blocked;
   126 #endif
   127 		}
   128 	TEST_PRINT1("Count =0 %d times", count0);
   129 	TEST_PRINT1("Count <0 %d times", countneg);
   130 	TEST_PRINT1("Blocked  %d times", blocked);
   131 	}
   132 
   133 void FSTest2(TAny* a)
   134 	{
   135 	SFSTest2Info& info = *(SFSTest2Info*)a;
   136 	NFastSemaphore exitSem(0);
   137 	NKern::FSSetOwner(&info.iSem, 0);
   138 	info.iBlockCount = 0;
   139 	info.iWaits = 0;
   140 	info.iSignals = 0;
   141 	info.iStart = FALSE;
   142 	info.iStop = FALSE;
   143 	TInt cpu;
   144 	TInt threads = 0;
   145 	TInt this_cpu = NKern::CurrentCpu();
   146 	for_each_cpu(cpu)
   147 		{
   148 		if (cpu==this_cpu)
   149 			CreateThreadSignalOnExit("FSTest2Sig0", &FSTest2Signaller0, 11, a, 0, KSmallTimeslice, &exitSem, cpu);
   150 		else
   151 			CreateThreadSignalOnExit("FSTest2Sig", &FSTest2Signaller, 12, a, 0, KSmallTimeslice, &exitSem, cpu);
   152 		++threads;
   153 		}
   154 
   155 	info.iStart = TRUE;
   156 	while(info.iWaits < 1048576)
   157 		{
   158 		NKern::FSWait(&info.iSem);
   159 		++info.iWaits;
   160 		}
   161 
   162 	info.iStop = TRUE;
   163 	while (threads--)
   164 		NKern::FSWait(&exitSem);
   165 	TEST_PRINT1("Leftover signals %d", info.iSignals-info.iWaits);
   166 	TInt r;
   167 	do	{
   168 		r = WaitWithTimeout(&info.iSem, KMinTimeout);
   169 		TEST_RESULT1(r==KErrNone || r==KErrTimedOut, "Invalid return code %d", r);
   170 		if (r == KErrNone)
   171 			++info.iWaits;
   172 		} while(r == KErrNone);
   173 	TEST_PRINT2("Signalled %d, Waited %d", info.iSignals, info.iWaits);
   174 	TEST_RESULT(info.iWaits==info.iSignals, "MISMATCH!");
   175 	}
   176 
   177 void DoFsTest2()
   178 	{
   179 	SFSTest2Info info;
   180 	CreateThreadAndWaitForExit("FSTest2", &FSTest2, 12, (TAny*)&info, 0, KSmallTimeslice, 0);
   181 	}
   182 
   183 
   184 void TestFastSemaphore()
   185 	{
   186 	TEST_PRINT("Testing Fast Semaphores...");
   187 
   188 	TInt cpu;
   189 	for_each_cpu(cpu)
   190 		{
   191 		DO_FS_TEST1(0,cpu);
   192 		DO_FS_TEST1(1,cpu);
   193 		DO_FS_TEST1(2,cpu);
   194 		DO_FS_TEST1(13,cpu);
   195 		}
   196 
   197 	DoFsTest2();
   198 	}