kerneltest/e32test/nkernsa/fastsem.cpp
changeset 0 a41df078684a
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     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 	}