kerneltest/e32test/prime/t_semutx.cpp
changeset 9 96e5fb8b040d
child 28 5b5d147c7838
equal deleted inserted replaced
-1:000000000000 9:96e5fb8b040d
       
     1 // Copyright (c) 1995-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\prime\t_semutx.cpp
       
    15 // Tests the RSemaphore, RMutex and RCriticalSection classes
       
    16 // Overview:
       
    17 // Tests the RSemaphore, RMutex and RCriticalSection classes
       
    18 // API Information:
       
    19 // RSemaphore, RMutex, RCriticalSection
       
    20 // Details:
       
    21 // - Test RSemaphore and RMutex with the producer/consumer scenario.
       
    22 // Create two threads, use signal and wait to coordinate the
       
    23 // threads. Verify results are as expected.
       
    24 // - Calculate the time required to create, resume and close a thread.
       
    25 // - Test RSemaphore::Wait(timeout) in a variety ways and timeout 
       
    26 // values. Verify results are as expected.
       
    27 // - Test RMutex via two threads which write to an array. The writing
       
    28 // and updating of the index is wrapped within a mutex pair. Verify 
       
    29 // results are as expected.
       
    30 // - Test RCriticalSection via two threads which write to an array. The 
       
    31 // writing and updating of the index is wrapped within a critical section
       
    32 // pair. Verify results are as expected.
       
    33 // Platforms/Drives/Compatibility:
       
    34 // All.
       
    35 // Assumptions/Requirement/Pre-requisites:
       
    36 // Failures and causes:
       
    37 // Base Port information:
       
    38 // 
       
    39 //
       
    40 
       
    41 #include <e32test.h>
       
    42 
       
    43 const TInt KMaxBufferSize=10;
       
    44 const TInt KMaxArraySize=10;
       
    45 const TInt KNumProducerItems=100;
       
    46 
       
    47 enum {EThread1ID=1,EThread2ID};
       
    48 
       
    49 RTest test(_L("T_SEMUTX"));
       
    50 RMutex mutex;
       
    51 RCriticalSection criticalSn;	
       
    52 TInt thread1Count,thread2Count;
       
    53 TInt arrayIndex;
       
    54 TInt array[KMaxArraySize];  
       
    55 TInt consumerArray[KNumProducerItems];
       
    56 RSemaphore slotAvailable,itemAvailable;  
       
    57 			 
       
    58 class CStack
       
    59 	{
       
    60 public:	   
       
    61 	CStack() {iCount=0;};
       
    62 	void Push(TInt aItem) {iStack[iCount++]=aItem;};
       
    63 	TInt Pop(void) {return(iStack[--iCount]);};
       
    64 private:
       
    65 	TInt iStack[KMaxBufferSize];
       
    66 	TInt iCount;
       
    67 	};
       
    68 CStack stack;
       
    69 
       
    70 
       
    71 TInt Producer(TAny*)
       
    72 	{
       
    73 	for(TInt ii=0;ii<KNumProducerItems;ii++)
       
    74 		{
       
    75 		slotAvailable.Wait();
       
    76 		mutex.Wait();
       
    77 		stack.Push(ii);
       
    78 		mutex.Signal();
       
    79 		itemAvailable.Signal();
       
    80 		}
       
    81 	return(KErrNone);
       
    82 	}
       
    83 
       
    84 TInt Consumer(TAny*)
       
    85 	{
       
    86 	TInt item;
       
    87 	for(TInt ii=0;ii<KNumProducerItems;ii++)
       
    88 		{
       
    89 		itemAvailable.Wait();
       
    90 		mutex.Wait();
       
    91 		item=stack.Pop();
       
    92 		mutex.Signal();
       
    93 		slotAvailable.Signal();
       
    94 		consumerArray[item]=item;
       
    95 		}
       
    96 	return(KErrNone);
       
    97 	}
       
    98 
       
    99 void BusyWait(TInt aMicroseconds)
       
   100 	{
       
   101 	TTime begin;
       
   102 	begin.HomeTime();
       
   103 	FOREVER
       
   104 		{
       
   105 		TTime now;
       
   106 		now.HomeTime();
       
   107 		TTimeIntervalMicroSeconds iv=now.MicroSecondsFrom(begin);
       
   108 		if (iv.Int64()>=TInt64(aMicroseconds))
       
   109 			return;
       
   110 		}
       
   111 	}
       
   112 
       
   113 TInt MutexThreadEntryPoint1(TAny*)
       
   114 //
       
   115 // Mutex test thread 1
       
   116 //
       
   117 	{	
       
   118 
       
   119 	thread1Count=0;
       
   120 	TBool running=ETrue;
       
   121 	do
       
   122 		{
       
   123 		mutex.Wait();
       
   124 		BusyWait(100000);
       
   125 		if (arrayIndex<KMaxArraySize)
       
   126 			{
       
   127 			array[arrayIndex++]=EThread1ID;
       
   128 			thread1Count++;
       
   129 			}
       
   130 		else
       
   131 			running=EFalse;
       
   132 		mutex.Signal();
       
   133 		} while (running);
       
   134 	return(KErrNone);
       
   135 	}
       
   136 
       
   137 TInt MutexThreadEntryPoint2(TAny*)
       
   138 //
       
   139 // Mutex test thread 2
       
   140 //
       
   141 	{
       
   142 
       
   143 	thread2Count=0;
       
   144 	TBool running=ETrue;
       
   145 	do
       
   146 		{
       
   147 		mutex.Wait();
       
   148 		BusyWait(200000);
       
   149 		if (arrayIndex<KMaxArraySize)
       
   150 			{
       
   151 			array[arrayIndex++]=EThread2ID;
       
   152 			thread2Count++;
       
   153 			}
       
   154 		else
       
   155 			running=EFalse;
       
   156 		mutex.Signal();
       
   157 		} while (running);
       
   158 	return(KErrNone);
       
   159 	}
       
   160 
       
   161 TInt CriticalSnThreadEntryPoint1(TAny*)
       
   162 //
       
   163 // Critical Section test thread 1
       
   164 //
       
   165 	{	
       
   166 
       
   167 	thread1Count=0;
       
   168 	TBool running=ETrue;
       
   169 	do
       
   170 		{
       
   171 		criticalSn.Wait();
       
   172 		User::After(100000);
       
   173 		if (arrayIndex<KMaxArraySize)
       
   174 			{
       
   175 			array[arrayIndex++]=EThread1ID;
       
   176 			thread1Count++;
       
   177 			}
       
   178 		else
       
   179 			running=EFalse;
       
   180 		criticalSn.Signal();
       
   181 		} while (running);
       
   182 	return(KErrNone);
       
   183 	}
       
   184 
       
   185 TInt CriticalSnThreadEntryPoint2(TAny*)
       
   186 //
       
   187 // Critical Section test thread 2
       
   188 //
       
   189 	{
       
   190 
       
   191 	thread2Count=0;
       
   192 	TBool running=ETrue;
       
   193 	do
       
   194 		{
       
   195 		criticalSn.Wait();
       
   196 		User::After(200000);
       
   197 		if (arrayIndex<KMaxArraySize)
       
   198 			{
       
   199 			array[arrayIndex++]=EThread2ID;
       
   200 			thread2Count++;
       
   201 			}
       
   202 		else
       
   203 			running=EFalse;
       
   204 		criticalSn.Signal();
       
   205 		} while (running);
       
   206 	return(KErrNone);
       
   207 	}
       
   208 
       
   209 struct SWaitSem
       
   210 	{
       
   211 	RSemaphore iSem;
       
   212 	TInt iTimeout;
       
   213 	};
       
   214 
       
   215 TInt WaitSemThread(TAny* a)
       
   216 	{
       
   217 	SWaitSem& ws = *(SWaitSem*)a;
       
   218 	return ws.iSem.Wait(ws.iTimeout);
       
   219 	}
       
   220 
       
   221 void StartWaitSemThread(RThread& aT, SWaitSem& aW, TThreadPriority aP=EPriorityLess)
       
   222 	{
       
   223 	TInt r = aT.Create(KNullDesC, &WaitSemThread, 0x1000, 0x1000, 0x1000, &aW);
       
   224 	test(r==KErrNone);
       
   225 	aT.SetPriority(aP);
       
   226 	aT.Resume();
       
   227 	}
       
   228 
       
   229 void WaitForWaitSemThread(RThread& aT, TInt aResult)
       
   230 	{
       
   231 	TRequestStatus s;
       
   232 	aT.Logon(s);
       
   233 	User::WaitForRequest(s);
       
   234 	test(aT.ExitType()==EExitKill);
       
   235 	test(aT.ExitReason()==aResult);
       
   236 	test(s.Int()==aResult);
       
   237 	CLOSE_AND_WAIT(aT);
       
   238 	}
       
   239 
       
   240 TInt DummyThread(TAny*)
       
   241 	{
       
   242 	return 0;
       
   243 	}
       
   244 
       
   245 void TestSemaphore2()
       
   246 	{
       
   247 	test.Start(_L("Test semaphore wait with timeout"));
       
   248 	SWaitSem ws;
       
   249 	RThread t;
       
   250 	TTime initial;
       
   251 	TTime final;
       
   252 	TInt elapsed=0;
       
   253 	TInt r = ws.iSem.CreateLocal(0);
       
   254 	test(r==KErrNone);
       
   255 
       
   256 	RThread().SetPriority(EPriorityAbsoluteVeryLow);
       
   257 	TInt threadcount=0;
       
   258 	initial.HomeTime();
       
   259 	while (elapsed<1000000)
       
   260 		{
       
   261 		r = t.Create(KNullDesC, &DummyThread, 0x1000, NULL, NULL);
       
   262 		test(r==KErrNone);
       
   263 		t.SetPriority(EPriorityMore);
       
   264 		t.Resume();
       
   265 		t.Close();
       
   266 		++threadcount;
       
   267 		final.HomeTime();
       
   268 		elapsed = I64INT(final.Int64()-initial.Int64());
       
   269 		}
       
   270 	RThread().SetPriority(EPriorityNormal);
       
   271 	test.Printf(_L("%d threads in 1 sec\n"),threadcount);
       
   272 	TInt overhead = 1000000/threadcount;
       
   273 	test.Printf(_L("overhead = %dus\n"),overhead);
       
   274 
       
   275 	ws.iTimeout=1000000;
       
   276 	initial.HomeTime();
       
   277 	StartWaitSemThread(t, ws);
       
   278 	WaitForWaitSemThread(t, KErrTimedOut);
       
   279 	final.HomeTime();
       
   280 	elapsed = I64INT(final.Int64()-initial.Int64());
       
   281 	test.Printf(_L("Time taken = %dus\n"), elapsed);
       
   282 	test(elapsed>=900000+overhead && elapsed<1500000+overhead);
       
   283 
       
   284 	ws.iTimeout=-1;
       
   285 	initial.HomeTime();
       
   286 	StartWaitSemThread(t, ws);
       
   287 	WaitForWaitSemThread(t, KErrArgument);
       
   288 	final.HomeTime();
       
   289 	elapsed = I64INT(final.Int64()-initial.Int64());
       
   290 	test.Printf(_L("Time taken = %dus\n"), elapsed);
       
   291 
       
   292 	ws.iTimeout=2000000;
       
   293 	initial.HomeTime();
       
   294 	StartWaitSemThread(t, ws);
       
   295 	User::After(1000000);
       
   296 	ws.iSem.Signal();
       
   297 	WaitForWaitSemThread(t, KErrNone);
       
   298 	final.HomeTime();
       
   299 	elapsed = I64INT(final.Int64()-initial.Int64());
       
   300 	test.Printf(_L("Time taken = %dus\n"), elapsed);
       
   301 	test(elapsed>=900000+overhead && elapsed<1500000+overhead);
       
   302 
       
   303 	ws.iTimeout=100000;
       
   304 	StartWaitSemThread(t, ws, EPriorityMore);
       
   305 	t.Suspend();
       
   306 	ws.iSem.Signal();
       
   307 	User::After(200000);
       
   308 	t.Resume();
       
   309 	WaitForWaitSemThread(t, KErrTimedOut);
       
   310 	test(ws.iSem.Wait(1)==KErrNone);
       
   311 
       
   312 	ws.iTimeout=100000;
       
   313 	StartWaitSemThread(t, ws, EPriorityMore);
       
   314 	t.Suspend();
       
   315 	ws.iSem.Signal();
       
   316 	User::After(50000);
       
   317 	t.Resume();
       
   318 	WaitForWaitSemThread(t, KErrNone);
       
   319 	test(ws.iSem.Wait(1)==KErrTimedOut);
       
   320 
       
   321 	RThread t2;
       
   322 	ws.iTimeout=100000;
       
   323 	StartWaitSemThread(t, ws, EPriorityMuchMore);
       
   324 	StartWaitSemThread(t2, ws, EPriorityMore);
       
   325 	t.Suspend();
       
   326 	ws.iSem.Signal();
       
   327 	test(t2.ExitType()==EExitKill);
       
   328 	test(t.ExitType()==EExitPending);
       
   329 	t.Resume();
       
   330 	WaitForWaitSemThread(t, KErrTimedOut);
       
   331 	WaitForWaitSemThread(t2, KErrNone);
       
   332 	test(ws.iSem.Wait(1)==KErrTimedOut);
       
   333 
       
   334 	ws.iTimeout=1000000;
       
   335 	initial.HomeTime();
       
   336 	StartWaitSemThread(t2, ws, EPriorityMore);
       
   337 	StartWaitSemThread(t, ws, EPriorityMuchMore);
       
   338 	ws.iSem.Signal();
       
   339 	WaitForWaitSemThread(t, KErrNone);
       
   340 	final.HomeTime();
       
   341 	elapsed = I64INT(final.Int64()-initial.Int64());
       
   342 	test.Printf(_L("Time taken = %dus\n"), elapsed);
       
   343 	WaitForWaitSemThread(t2, KErrTimedOut);
       
   344 	final.HomeTime();
       
   345 	elapsed = I64INT(final.Int64()-initial.Int64());
       
   346 	test.Printf(_L("Time taken = %dus\n"), elapsed);
       
   347 	test(elapsed>=900000+2*overhead && elapsed<1500000+2*overhead);
       
   348 
       
   349 	ws.iTimeout=1000000;
       
   350 	initial.HomeTime();
       
   351 	StartWaitSemThread(t2, ws, EPriorityMore);
       
   352 	StartWaitSemThread(t, ws, EPriorityMuchMore);
       
   353 	WaitForWaitSemThread(t, KErrTimedOut);
       
   354 	final.HomeTime();
       
   355 	elapsed = I64INT(final.Int64()-initial.Int64());
       
   356 	test.Printf(_L("Time taken = %dus\n"), elapsed);
       
   357 	WaitForWaitSemThread(t2, KErrTimedOut);
       
   358 	final.HomeTime();
       
   359 	elapsed = I64INT(final.Int64()-initial.Int64());
       
   360 	test.Printf(_L("Time taken = %dus\n"), elapsed);
       
   361 	test(elapsed>=900000+2*overhead && elapsed<1500000+2*overhead);
       
   362 
       
   363 	ws.iTimeout=1000000;
       
   364 	initial.HomeTime();
       
   365 	StartWaitSemThread(t2, ws, EPriorityMore);
       
   366 	StartWaitSemThread(t, ws, EPriorityMuchMore);
       
   367 	t.Kill(299792458);
       
   368 	WaitForWaitSemThread(t2, KErrTimedOut);
       
   369 	WaitForWaitSemThread(t, 299792458);
       
   370 	final.HomeTime();
       
   371 	elapsed = I64INT(final.Int64()-initial.Int64());
       
   372 	test.Printf(_L("Time taken = %dus\n"), elapsed);
       
   373 	test(elapsed>=900000+2*overhead && elapsed<1500000+2*overhead);
       
   374 
       
   375 	ws.iTimeout=1000000;
       
   376 	initial.HomeTime();
       
   377 	StartWaitSemThread(t, ws, EPriorityMore);
       
   378 	StartWaitSemThread(t2, ws, EPriorityMuchMore);
       
   379 	test(t.ExitType()==EExitPending);
       
   380 	test(t2.ExitType()==EExitPending);
       
   381 	ws.iSem.Close();
       
   382 	test(t.ExitType()==EExitKill);
       
   383 	test(t2.ExitType()==EExitKill);
       
   384 	WaitForWaitSemThread(t2, KErrGeneral);
       
   385 	WaitForWaitSemThread(t, KErrGeneral);
       
   386 	final.HomeTime();
       
   387 	elapsed = I64INT(final.Int64()-initial.Int64());
       
   388 	test.Printf(_L("Time taken = %dus\n"), elapsed);
       
   389 	test(elapsed<=50000+3*overhead);
       
   390 
       
   391 	test.End();
       
   392 	}
       
   393 
       
   394 void TestSemaphore()
       
   395 	{
       
   396 /*********** TO DO ************/
       
   397 // Check it panics if the count <0
       
   398 
       
   399 	test.Start(_L("Create"));
       
   400 	RSemaphore semaphore;
       
   401 	RThread thread1, thread2;
       
   402 
       
   403 	semaphore.CreateLocal(0); 	// creates a DPlatSemaphore but casts it to a pointer to a DSemaphore
       
   404 								// sets semaphore count to the value of the parameter, 
       
   405 								// adds object to the K::Semaphores container, sets iHandle
       
   406 								// Local sets DSemaphore.iName to NULL & iOwner to Kern::CurrentProcess()
       
   407 								// Global sets iName to that passed and iOwner to NULL
       
   408 								// Adds a record into CObjectIx containing a pointer to the semaphore object
       
   409 /*	test.Next(_L("Find"));
       
   410 	fullName=semaphore.FullName();	
       
   411 	find.Find(fullName);	// sets iMatch to fullName	(misleadingly named method as it doesn't find anything)
       
   412 	test(find.Next(fullName)== KErrNone);	
       
   413 */
       
   414 	test.Next(_L("Producer/Consumer scenario"));
       
   415 	// Test Rsemaphore with the producer/consumer scenario	RThread thread1, thread2;
       
   416 	TRequestStatus stat1, stat2;
       
   417 	test(mutex.CreateLocal()==KErrNone);
       
   418 	test(slotAvailable.CreateLocal(KMaxBufferSize)==KErrNone);
       
   419 	test(itemAvailable.CreateLocal(0)==KErrNone);
       
   420 	test(thread1.Create(_L("Thread1"),Producer,KDefaultStackSize,0x200,0x200,NULL)==KErrNone);
       
   421 	test(thread2.Create(_L("Thread2"),Consumer,KDefaultStackSize,0x200,0x200,NULL)==KErrNone);
       
   422 	thread1.Logon(stat1);
       
   423 	thread2.Logon(stat2);
       
   424 	test(stat1==KRequestPending);
       
   425 	test(stat2==KRequestPending);
       
   426 	thread1.Resume(); 
       
   427 	thread2.Resume();
       
   428 	User::WaitForRequest(stat1);
       
   429 	User::WaitForRequest(stat2);
       
   430 	test(stat1==KErrNone);
       
   431 	test(stat2==KErrNone);
       
   432 	for(TInt jj=0;jj<KNumProducerItems;jj++)
       
   433 		test(consumerArray[jj]==jj);		
       
   434 	
       
   435 	test.Next(_L("Close"));
       
   436 	mutex.Close();
       
   437 	CLOSE_AND_WAIT(thread1);
       
   438 	CLOSE_AND_WAIT(thread2);
       
   439 	test.End();
       
   440 	}
       
   441 
       
   442 void TestMutex2()
       
   443 	{
       
   444 	RMutex m;
       
   445 	test.Start(_L("Create"));
       
   446 	test(m.CreateLocal()==KErrNone);
       
   447 
       
   448 	// Test RMutex::IsHeld()
       
   449 	test.Next(_L("IsHeld ?"));
       
   450 	test(!m.IsHeld());
       
   451 	test.Next(_L("Wait"));
       
   452 	m.Wait();
       
   453 	test.Next(_L("IsHeld ?"));
       
   454 	test(m.IsHeld());
       
   455 	test.Next(_L("Signal"));
       
   456 	m.Signal();
       
   457 	test.Next(_L("IsHeld ?"));
       
   458 	test(!m.IsHeld());
       
   459 
       
   460 	test.End();
       
   461 	}
       
   462 
       
   463 void TestMutex()
       
   464 	{
       
   465 	test.Start(_L("Create"));
       
   466 	test(mutex.CreateLocal()==KErrNone);
       
   467 	
       
   468 	test.Next(_L("Threads writing to arrays test"));
       
   469 //
       
   470 // Create two threads which write to two arrays. The arrays and indexs
       
   471 // are global and each thread writes an identifier to the arrays. For
       
   472 // one array the writing and updating of the index is wrapped in a mutex
       
   473 // pair. The other array is a control and is not wrapaped within mutex.
       
   474 // Each thread records the number of instances it "thinks" it wrote to
       
   475 // each array. For the mutex controlled array the actual instances
       
   476 // written to the array should always be the same as the threads think.
       
   477 //
       
   478 	arrayIndex=0;
       
   479 	RThread thread1,thread2;	
       
   480 	test(thread1.Create(_L("Thread1"),MutexThreadEntryPoint1,KDefaultStackSize,0x2000,0x2000,NULL)==KErrNone);
       
   481 	test(thread2.Create(_L("Thread2"),MutexThreadEntryPoint2,KDefaultStackSize,0x2000,0x2000,NULL)==KErrNone);			 
       
   482 	TRequestStatus stat1,stat2;
       
   483 	thread1.Logon(stat1);
       
   484 	thread2.Logon(stat2);
       
   485 	test(stat1==KRequestPending);
       
   486 	test(stat2==KRequestPending);
       
   487 	thread1.Resume(); 
       
   488 	thread2.Resume();
       
   489 	User::WaitForRequest(stat1);
       
   490 	User::WaitForRequest(stat2);
       
   491 	test(stat1==KErrNone);
       
   492 	test(stat2==KErrNone); 
       
   493 	TInt thread1ActualCount=0; 
       
   494 	TInt thread2ActualCount=0;
       
   495 	TInt ii=0;
       
   496 	while(ii<KMaxArraySize)
       
   497 		{
       
   498 		if (array[ii]==EThread1ID)
       
   499 			thread1ActualCount++;
       
   500 		if (array[ii]==EThread2ID)
       
   501 			thread2ActualCount++;
       
   502 		ii++;
       
   503 		}
       
   504 	test.Printf(_L("T1 %d T1ACT %d T2 %d T2ACT %d"),thread1Count,thread1ActualCount,thread2Count,thread2ActualCount);
       
   505 	test(thread1ActualCount==thread1Count);
       
   506 	test(thread2ActualCount==thread2Count);
       
   507 	test(thread1Count==thread2Count);
       
   508 	test(thread1Count==(KMaxArraySize>>1));
       
   509 	
       
   510 	test.Next(_L("Close"));
       
   511 	CLOSE_AND_WAIT(thread1);
       
   512 	CLOSE_AND_WAIT(thread2);
       
   513 	mutex.Close();
       
   514 	test.End();
       
   515 	}
       
   516 
       
   517 void TestCriticalSection()
       
   518 //
       
   519 //As TestMutex, but for RCriticalSection
       
   520 //
       
   521 	{
       
   522 	
       
   523 	test.Start(_L("Create"));
       
   524 	test(criticalSn.CreateLocal()==KErrNone);
       
   525 
       
   526 /***************** TO DO ***********************
       
   527 
       
   528 	test.Next(_L("Find"));
       
   529 //
       
   530 // Test finding the RCriticalSection
       
   531 //
       
   532 	TFindCriticalSection find;
       
   533 	TFullName fullName;
       
   534 	fullName=criticalSn.FullName();
       
   535 	find.Find(fullName);
       
   536 	test(find.Next(fullName)==KErrNone);
       
   537 	test(fullName==criticalSn.FullName());
       
   538 
       
   539 ************************************************/
       
   540 
       
   541 	test.Next(_L("Threads writing to arrays test"));
       
   542 //
       
   543 // Create two threads which write to two arrays. The arrays and indexs
       
   544 // are global and each thread writes an identifier to the arrays. For
       
   545 // one array the writing and updating of the index is wrapped in a critical
       
   546 // section pair. The other array is a control and is not wrapaped within
       
   547 // a critical section. Each thread records the number of instances it
       
   548 // "thinks" it wrote to each array. For the mutex controlled array the
       
   549 // actual instances written to the array should always be the same as the
       
   550 // threads think.
       
   551 //
       
   552 	arrayIndex=0;
       
   553 	RThread thread1,thread2;	
       
   554 	test(thread1.Create(_L("Thread1"),CriticalSnThreadEntryPoint1,KDefaultStackSize,0x2000,0x2000,NULL)==KErrNone);
       
   555 	test(thread2.Create(_L("Thread2"),CriticalSnThreadEntryPoint2,KDefaultStackSize,0x2000,0x2000,NULL)==KErrNone);			 
       
   556 	TRequestStatus stat1,stat2;
       
   557 	thread1.Logon(stat1);
       
   558 	thread2.Logon(stat2);
       
   559 	test(stat1==KRequestPending);
       
   560 	test(stat2==KRequestPending);
       
   561 	thread1.Resume(); 
       
   562 	thread2.Resume();
       
   563 	User::WaitForRequest(stat1);
       
   564 	User::WaitForRequest(stat2);
       
   565 	test(stat1==KErrNone);
       
   566 	test(stat2==KErrNone); 
       
   567 	TInt thread1ActualCount=0; 
       
   568 	TInt thread2ActualCount=0;
       
   569 	TInt ii=0;
       
   570 	while(ii<KMaxArraySize)
       
   571 		{
       
   572 		if (array[ii]==EThread1ID)
       
   573 			thread1ActualCount++;
       
   574 		if (array[ii]==EThread2ID)
       
   575 			thread2ActualCount++;
       
   576 		ii++;
       
   577 		}
       
   578 	test(thread1ActualCount==thread1Count);
       
   579 	test(thread2ActualCount==thread2Count);
       
   580 	test(thread1Count==thread2Count);
       
   581 	test(thread1Count==(KMaxArraySize>>1));
       
   582 
       
   583 	test.Next(_L("Close"));
       
   584 	CLOSE_AND_WAIT(thread1);
       
   585 	CLOSE_AND_WAIT(thread2);
       
   586 	criticalSn.Close();
       
   587 	test.End();
       
   588 	}
       
   589 
       
   590 
       
   591 GLDEF_C TInt E32Main()
       
   592 	{	
       
   593 
       
   594 	test.Title();
       
   595  	__UHEAP_MARK;
       
   596 	test.Start(_L("Test RSemaphore"));
       
   597 	TestSemaphore();
       
   598 	TestSemaphore2();
       
   599 	test.Next(_L("Test RMutex"));
       
   600 	TestMutex();
       
   601 	TestMutex2();
       
   602 	test.Next(_L("Test RCriticalSection"));
       
   603 	TestCriticalSection();
       
   604 	test.End();
       
   605 	__UHEAP_MARKEND;
       
   606 	return(KErrNone);
       
   607 	}
       
   608 
       
   609