os/kernelhwsrv/kerneltest/e32test/prime/t_semutx2.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/kernelhwsrv/kerneltest/e32test/prime/t_semutx2.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,1414 @@
     1.4 +// Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +// All rights reserved.
     1.6 +// This component and the accompanying materials are made available
     1.7 +// under the terms of the License "Eclipse Public License v1.0"
     1.8 +// which accompanies this distribution, and is available
     1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +//
    1.11 +// Initial Contributors:
    1.12 +// Nokia Corporation - initial contribution.
    1.13 +//
    1.14 +// Contributors:
    1.15 +//
    1.16 +// Description:
    1.17 +// e32test\prime\t_semutx2.cpp
    1.18 +// Test RSemaphore and RMutex
    1.19 +// Overview:
    1.20 +// Tests the RSemaphore and RMutex
    1.21 +// API Information:
    1.22 +// RSemaphore, RMutex
    1.23 +// Details:
    1.24 +// - Test and verify that thread priorities work as expected.
    1.25 +// - Test and verify that signalling an RMutex from the wrong
    1.26 +// thread fails as expected.
    1.27 +// - Test and verify that mutex priority inheritance works as
    1.28 +// expected.
    1.29 +// - Perform an exhaustive state transition test using mutexs
    1.30 +// and up to ten threads. Verify priorities, order of execution, 
    1.31 +// mutex signalling, suspend, resume, kill and close. Verify 
    1.32 +// results are as expected.
    1.33 +// - Test semaphore speed by counting how many Wait/Signal 
    1.34 +// operations can be completed in one second.
    1.35 +// Platforms/Drives/Compatibility:
    1.36 +// All.
    1.37 +// Assumptions/Requirement/Pre-requisites:
    1.38 +// Failures and causes:
    1.39 +// Base Port information:
    1.40 +// 
    1.41 +//
    1.42 +
    1.43 +#include <e32test.h>
    1.44 +
    1.45 +RMutex M1;
    1.46 +RMutex M2;
    1.47 +RSemaphore S;
    1.48 +
    1.49 +const TInt KBufferSize=4096;
    1.50 +TUint ThreadId[KBufferSize];
    1.51 +TInt PutIx;
    1.52 +TInt GetIx;
    1.53 +TInt Count;
    1.54 +RThread Main;
    1.55 +
    1.56 +
    1.57 +RTest test(_L("T_SEMUTX2"));
    1.58 +
    1.59 +/*****************************************************************************
    1.60 + * Utility functions / macros
    1.61 + *****************************************************************************/
    1.62 +#define TRACE_ON	User::SetDebugMask(0xffdfffff);
    1.63 +#define TRACE_OFF	User::SetDebugMask(0x80000000);
    1.64 +
    1.65 +//#define MCOUNT(m,c)	test((m).Count() ==(c))
    1.66 +// mutex count value is not visible for user any more
    1.67 +#define MCOUNT(m,c) (void)(1)
    1.68 +#define IDCHECK(x) test(GetNextId()==(x))
    1.69 +#define NUMCHECK(x)	test(NumIdsPending()==(x))
    1.70 +
    1.71 +#define id0		id[0]
    1.72 +#define id1		id[1]
    1.73 +#define id2		id[2]
    1.74 +#define id3		id[3]
    1.75 +#define id4		id[4]
    1.76 +#define id5		id[5]
    1.77 +#define id6		id[6]
    1.78 +#define id7		id[7]
    1.79 +#define id8		id[8]
    1.80 +#define id9		id[9]
    1.81 +#define id10	id[10]
    1.82 +
    1.83 +TBool Exists(const TDesC& aName)
    1.84 +	{
    1.85 +	TFullName n(RProcess().Name());
    1.86 +	n+=_L("::");
    1.87 +	n+=aName;
    1.88 +	TFindThread ft(n);
    1.89 +	TFullName fn;
    1.90 +	return ft.Next(fn)==KErrNone;
    1.91 +	}
    1.92 +
    1.93 +TBool Exists(TInt aNum)
    1.94 +	{
    1.95 +	TBuf<4> b;
    1.96 +	b.Num(aNum);
    1.97 +	return Exists(b);
    1.98 +	}
    1.99 +
   1.100 +void BusyWait(TInt aMicroseconds)
   1.101 +	{
   1.102 +	TTime begin;
   1.103 +	begin.HomeTime();
   1.104 +	FOREVER
   1.105 +		{
   1.106 +		TTime now;
   1.107 +		now.HomeTime();
   1.108 +		TTimeIntervalMicroSeconds iv=now.MicroSecondsFrom(begin);
   1.109 +		if (iv.Int64()>=TInt64(aMicroseconds))
   1.110 +			return;
   1.111 +		}
   1.112 +	}
   1.113 +
   1.114 +void Kick(RThread& t)
   1.115 +	{
   1.116 +	TRequestStatus s;
   1.117 +	TRequestStatus* pS=&s;
   1.118 +	t.RequestComplete(pS,0);
   1.119 +	}
   1.120 +
   1.121 +TUint GetNextId()
   1.122 +	{
   1.123 +	if (GetIx<PutIx)
   1.124 +		return ThreadId[GetIx++];
   1.125 +	return 0;
   1.126 +	}
   1.127 +
   1.128 +TInt NumIdsPending()
   1.129 +	{
   1.130 +	return PutIx-GetIx;
   1.131 +	}
   1.132 +
   1.133 +/*****************************************************************************
   1.134 + * General tests
   1.135 + *****************************************************************************/
   1.136 +TInt Test0Thread(TAny* aPtr)
   1.137 +	{
   1.138 +	TInt& count=*(TInt*)aPtr;
   1.139 +	++count;
   1.140 +	Main.SetPriority(EPriorityMuchMore);
   1.141 +	++count;
   1.142 +	Main.SetPriority(EPriorityMuchMore);
   1.143 +	++count;
   1.144 +	RThread().SetPriority(EPriorityNormal);
   1.145 +	++count;
   1.146 +	return 0;
   1.147 +	}
   1.148 +
   1.149 +void Test0()
   1.150 +	{
   1.151 +	User::After(100000);	// Test fails intermittently on hardware unless we pause here 
   1.152 +	
   1.153 +	test.Start(_L("Test thread priorities work"));
   1.154 +	test.Next(_L("Create thread"));
   1.155 +	RThread t;
   1.156 +	TInt count=0;
   1.157 +	TRequestStatus s;
   1.158 +	TInt r=t.Create(_L("Test0"),Test0Thread,0x1000,NULL,&count);
   1.159 +	test(r==KErrNone);
   1.160 +	t.Logon(s);
   1.161 +	test(r==KErrNone);
   1.162 +	User::After(10000);		// make sure we have a full timeslice
   1.163 +	t.Resume();
   1.164 +
   1.165 +	test(count==0);			// t shouldn't have run yet
   1.166 +	RThread().SetPriority(EPriorityMuchMore);	// shouldn't reschedule (priority unchanged)
   1.167 +	test(count==0);
   1.168 +	RThread().SetPriority(EPriorityMore);	// shouldn't reschedule (priority decreasing, but not enough)
   1.169 +	test(count==0);
   1.170 +	RThread().SetPriority(EPriorityMuchMore);	// shouldn't reschedule (priority increasing)
   1.171 +	test(count==0);
   1.172 +	RThread().SetPriority(EPriorityNormal);	// should reschedule (we go behind t)
   1.173 +	test(count==1);
   1.174 +	RThread().SetPriority(EPriorityLess);	// should reschedule (priority decreasing to below t)
   1.175 +	test(count==2);
   1.176 +	t.SetPriority(EPriorityMuchMore);		// shouldn't reschedule (round-robin, timeslice not expired)
   1.177 +	test(count==2);
   1.178 +	t.SetPriority(EPriorityNormal);			// shouldn't reschedule (t's priority decreasing)
   1.179 +	test(count==2);
   1.180 +	t.SetPriority(EPriorityNormal);			// shouldn't reschedule (t's priority unchanged)
   1.181 +	test(count==2);
   1.182 +	BusyWait(100000);		// use up our timeslice
   1.183 +	t.SetPriority(EPriorityMuchMore);		// should reschedule (round-robin, timeslice expired)
   1.184 +	test(count==3);
   1.185 +	test(s==KRequestPending);
   1.186 +	test(t.ExitType()==EExitPending);
   1.187 +	t.SetPriority(EPriorityRealTime);		// should reschedule (t increases above current)
   1.188 +	test(count==4);
   1.189 +	test(s==KErrNone);						// t should have exited
   1.190 +	test(t.ExitType()==EExitKill);
   1.191 +	User::WaitForRequest(s);
   1.192 +	RThread().SetPriority(EPriorityMuchMore);
   1.193 +	t.Close();
   1.194 +	test.End();
   1.195 +	}
   1.196 +
   1.197 +TInt Test1Thread(TAny*)
   1.198 +	{
   1.199 +	M1.Signal();
   1.200 +	return 0;
   1.201 +	}
   1.202 +
   1.203 +void Test1()
   1.204 +	{
   1.205 +	test.Start(_L("Test signalling from wrong thread"));
   1.206 +	TInt r=M1.CreateLocal();
   1.207 +	test(r==KErrNone);
   1.208 +	M1.Wait();
   1.209 +	RThread t;
   1.210 +	r=t.Create(_L("Test1"),Test1Thread,0x1000,NULL,NULL);
   1.211 +	test(r==KErrNone);
   1.212 +	TRequestStatus s;
   1.213 +	t.Logon(s);
   1.214 +	t.Resume();
   1.215 +	TBool jit = User::JustInTime();
   1.216 +	User::SetJustInTime(EFalse);
   1.217 +	User::WaitForRequest(s);
   1.218 +	User::SetJustInTime(jit);
   1.219 +	test(s==EAccessDenied);
   1.220 +	test(t.ExitType()==EExitPanic);
   1.221 +	test(t.ExitReason()==EAccessDenied);
   1.222 +	test(t.ExitCategory()==_L("KERN-EXEC"));
   1.223 +	t.Close();
   1.224 +	M1.Close();
   1.225 +	test.End();
   1.226 +	}
   1.227 +
   1.228 +/*****************************************************************************
   1.229 + * Mutex priority inheritance
   1.230 + *****************************************************************************/
   1.231 +
   1.232 +const TInt KTestDelay = 1000000;
   1.233 +
   1.234 +TInt LowThread(TAny* aPtr)
   1.235 +	{
   1.236 +	TInt& count=*(TInt*)aPtr;
   1.237 +	FOREVER
   1.238 +		{
   1.239 +		M1.Wait();
   1.240 +		++count;
   1.241 +		BusyWait(KTestDelay);
   1.242 +		M1.Signal();
   1.243 +		User::WaitForAnyRequest();
   1.244 +		}
   1.245 +	}
   1.246 +
   1.247 +TInt MedThread(TAny* aPtr)
   1.248 +	{
   1.249 +	TInt& count=*(TInt*)aPtr;
   1.250 +	FOREVER
   1.251 +		{
   1.252 +		++count;
   1.253 +		User::WaitForAnyRequest();
   1.254 +		}
   1.255 +	}
   1.256 +
   1.257 +TInt HighThread(TAny* aPtr)
   1.258 +	{
   1.259 +	TInt& count=*(TInt*)aPtr;
   1.260 +	FOREVER
   1.261 +		{
   1.262 +		M2.Wait();
   1.263 +		++count;
   1.264 +		M1.Wait();
   1.265 +		++count;
   1.266 +		BusyWait(KTestDelay);
   1.267 +		M1.Signal();
   1.268 +		M2.Signal();
   1.269 +		User::WaitForAnyRequest();
   1.270 +		}
   1.271 +	}
   1.272 +
   1.273 +void TestMutex1()
   1.274 +	{
   1.275 +	test.Start(_L("Test mutex priority inheritance"));
   1.276 +
   1.277 +	test.Next(_L("Create mutex"));
   1.278 +	TInt r=M1.CreateLocal();
   1.279 +	test(r==KErrNone);
   1.280 +
   1.281 +	test.Next(_L("Create low priority thread"));
   1.282 +	TInt lowcount=0;
   1.283 +	RThread low;
   1.284 +	r=low.Create(_L("low"),LowThread,0x1000,NULL,&lowcount);
   1.285 +	test(r==KErrNone);
   1.286 +	low.SetPriority(EPriorityMuchLess);
   1.287 +	test(Exists(_L("low")));
   1.288 +
   1.289 +	test.Next(_L("Create medium priority thread"));
   1.290 +	TInt medcount=0;
   1.291 +	RThread med;
   1.292 +	r=med.Create(_L("med"),MedThread,0x1000,NULL,&medcount);
   1.293 +	test(r==KErrNone);
   1.294 +	med.SetPriority(EPriorityNormal);
   1.295 +	test(Exists(_L("med")));
   1.296 +
   1.297 +	test.Next(_L("Start low priority thread"));
   1.298 +	low.Resume();
   1.299 +	User::AfterHighRes(KTestDelay/10);
   1.300 +	test(lowcount==1);
   1.301 +//	MCOUNT(M1,0);
   1.302 +
   1.303 +	test.Next(_L("Start medium priority thread"));
   1.304 +	med.Resume();
   1.305 +	User::AfterHighRes(KTestDelay/10);
   1.306 +	test(medcount==1);
   1.307 +	Kick(med);
   1.308 +	User::AfterHighRes(KTestDelay/10);
   1.309 +	test(medcount==2);
   1.310 +	Kick(med);
   1.311 +
   1.312 +	M1.Wait();
   1.313 +	test(lowcount==1);
   1.314 +	test(medcount==2);
   1.315 +	test.Next(_L("Wait, check medium runs"));
   1.316 +	User::AfterHighRes(KTestDelay/10);
   1.317 +	test(medcount==3);
   1.318 +	M1.Signal();
   1.319 +
   1.320 +	test.Next(_L("Create mutex 2"));
   1.321 +	r=M2.CreateLocal();
   1.322 +	test(r==KErrNone);
   1.323 +
   1.324 +	test.Next(_L("Create high priority thread"));
   1.325 +	TInt highcount=0;
   1.326 +	RThread high;
   1.327 +	r=high.Create(_L("high"),HighThread,0x1000,NULL,&highcount);
   1.328 +	test(r==KErrNone);
   1.329 +	high.SetPriority(EPriorityMore);
   1.330 +	test(Exists(_L("high")));
   1.331 +
   1.332 +	Kick(low);
   1.333 +	User::AfterHighRes(KTestDelay/10);
   1.334 +//	MCOUNT(M1,0);
   1.335 +	Kick(med);
   1.336 +
   1.337 +//	MCOUNT(M2,1);
   1.338 +	high.Resume();
   1.339 +	User::AfterHighRes(KTestDelay/10);
   1.340 +//	MCOUNT(M2,0);
   1.341 +//	MCOUNT(M1,-1);
   1.342 +	test(highcount==1);
   1.343 +
   1.344 +	M2.Wait();
   1.345 +	test(lowcount==2);
   1.346 +	test(medcount==3);
   1.347 +	test(highcount==2);
   1.348 +	test.Next(_L("Wait, check medium runs"));
   1.349 +	User::AfterHighRes(KTestDelay/10);
   1.350 +	test(medcount==4);
   1.351 +	M2.Signal();
   1.352 +
   1.353 +	test.Next(_L("Kill threads"));
   1.354 +	low.Kill(0);
   1.355 +	med.Kill(0);
   1.356 +	high.Kill(0);
   1.357 +	low.Close();
   1.358 +	med.Close();
   1.359 +	high.Close();
   1.360 +	test(!Exists(_L("low")));
   1.361 +	test(!Exists(_L("med")));
   1.362 +	test(!Exists(_L("high")));
   1.363 +
   1.364 +	M1.Close();
   1.365 +	test.End();
   1.366 +	}
   1.367 +
   1.368 +/*****************************************************************************
   1.369 + * Utilities for mutex exhaustive state transition test
   1.370 + *****************************************************************************/
   1.371 +void MutexWait()
   1.372 +	{
   1.373 +	M1.Wait();
   1.374 +	++Count;
   1.375 +	ThreadId[PutIx++]=(TUint)RThread().Id();
   1.376 +	}
   1.377 +
   1.378 +void MutexSignal()
   1.379 +	{
   1.380 +	M1.Signal();
   1.381 +	}
   1.382 +
   1.383 +typedef void (*PFV)(void);
   1.384 +TInt ThreadFunction(TAny* aPtr)
   1.385 +	{
   1.386 +	PFV& f=*(PFV*)aPtr;
   1.387 +	FOREVER
   1.388 +		{
   1.389 +		MutexWait();
   1.390 +		if (f)
   1.391 +			f();
   1.392 +		MutexSignal();
   1.393 +		User::WaitForAnyRequest();
   1.394 +		}
   1.395 +	}
   1.396 +
   1.397 +void Exit()
   1.398 +	{
   1.399 +	User::Exit(0);
   1.400 +	}
   1.401 +
   1.402 +TUint CreateThread(RThread& t, TInt n, TAny* aPtr)
   1.403 +	{
   1.404 +	TBuf<4> b;
   1.405 +	b.Num(n);
   1.406 +	TInt r=t.Create(b,ThreadFunction,0x1000,NULL,aPtr);
   1.407 +	test(r==KErrNone);
   1.408 +	t.Resume();
   1.409 +	TUint id=t.Id();
   1.410 +	test.Printf(_L("id=%d\n"),id);
   1.411 +	return id;
   1.412 +	}
   1.413 +
   1.414 +/*
   1.415 +Possible thread relationships with mutex:
   1.416 +	Holding
   1.417 +	Waiting
   1.418 +	Waiting + suspended
   1.419 +	Hold Pending
   1.420 +
   1.421 +Need to verify correct behaviour when the following actions occur for each of these states:
   1.422 +	Suspend thread
   1.423 +	Resume thread
   1.424 +	Change thread priority
   1.425 +	Thread exits
   1.426 +	Thread is killed
   1.427 +	Mutex deleted
   1.428 +*/
   1.429 +
   1.430 +PFV HoldExtra;
   1.431 +void KickMain()
   1.432 +	{
   1.433 +	RThread me;
   1.434 +	Kick(Main);
   1.435 +	User::WaitForAnyRequest();
   1.436 +	me.SetPriority(EPriorityMuchMore);
   1.437 +	MutexSignal();						// this should wake up t8
   1.438 +	MutexWait();
   1.439 +	MutexSignal();						// this should wake up t9
   1.440 +	MutexWait();
   1.441 +	Kick(Main);
   1.442 +	User::WaitForAnyRequest();
   1.443 +	if (HoldExtra)
   1.444 +		HoldExtra();
   1.445 +	}
   1.446 +
   1.447 +void RackEmUp(RThread* t, PFV* f, TUint* id)
   1.448 +	{
   1.449 +	// set up t4 holding
   1.450 +	// t1, t2, t5, t10 waiting
   1.451 +	// t3, t6, t7 waiting+suspended
   1.452 +	// t8, t9 pending
   1.453 +	MCOUNT(M1,1);			// check mutex free
   1.454 +	Kick(t[4]);
   1.455 +	f[4]=&KickMain;
   1.456 +	User::WaitForAnyRequest();
   1.457 +	MCOUNT(M1,0);			// check mutex now held
   1.458 +	TInt i;
   1.459 +	for (i=1; i<=10; ++i)
   1.460 +		if (i!=4)
   1.461 +			Kick(t[i]);		// wake up threads
   1.462 +	User::After(50000);		// let threads wait
   1.463 +	MCOUNT(M1,-9);			// check 9 threads waiting
   1.464 +	Kick(t[4]);
   1.465 +	User::WaitForAnyRequest();
   1.466 +	MCOUNT(M1,-7);			// check 7 threads waiting
   1.467 +	NUMCHECK(3);
   1.468 +	IDCHECK(id4);			// from the initial wait
   1.469 +	IDCHECK(id4);			// now have t8, t9 pending, t4 holding, rest waiting
   1.470 +	IDCHECK(id4);			// now have t8, t9 pending, t4 holding, rest waiting
   1.471 +	t[4].SetPriority(EPriorityNormal);
   1.472 +	t[7].Resume();			// test resume when not suspended
   1.473 +	MCOUNT(M1,-7);			// check 7 threads waiting
   1.474 +	t[3].Suspend();
   1.475 +	t[6].Suspend();
   1.476 +	t[7].Suspend();			// now have required state
   1.477 +	t[3].Suspend();			// suspend and resume t3 again for good measure
   1.478 +	t[3].Resume();
   1.479 +	MCOUNT(M1,-7);			// check 7 threads waiting
   1.480 +	HoldExtra=NULL;
   1.481 +	}
   1.482 +
   1.483 +void SimpleCheck(TInt n, const TUint* id, ...)
   1.484 +	{
   1.485 +	VA_LIST list;
   1.486 +	VA_START(list,id);
   1.487 +	User::After(50000);		// let stuff happen
   1.488 +	NUMCHECK(n);
   1.489 +	TInt i;
   1.490 +	for (i=0; i<n; ++i)
   1.491 +		{
   1.492 +		TInt tn=VA_ARG(list,TInt);
   1.493 +		IDCHECK(id[tn]);
   1.494 +		}
   1.495 +	}
   1.496 +
   1.497 +void Resurrect(TInt n, TThreadPriority aPriority, RThread* t, PFV* f, TUint* id)
   1.498 +	{
   1.499 +	f[n]=NULL;
   1.500 +	id[n]=CreateThread(t[n],n,f+n);
   1.501 +	t[n].SetPriority(EPriorityRealTime);
   1.502 +	t[n].SetPriority(aPriority);
   1.503 +	NUMCHECK(1);
   1.504 +	IDCHECK(id[n]);
   1.505 +	}
   1.506 +
   1.507 +/*****************************************************************************
   1.508 + * Mutex exhaustive state transition test
   1.509 + *****************************************************************************/
   1.510 +void TestMutex2()
   1.511 +	{
   1.512 +	test.Start(_L("Test mutex state transitions"));
   1.513 +	RThread t[11];
   1.514 +	TUint id[11];
   1.515 +	PFV f[11]={NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
   1.516 +	id[0]=(TUint)RThread().Id();
   1.517 +	PutIx=0;
   1.518 +	GetIx=0;
   1.519 +	Count=0;
   1.520 +	test.Next(_L("Create mutex"));
   1.521 +	TInt r=M1.CreateLocal();
   1.522 +	test(r==KErrNone);
   1.523 +	MCOUNT(M1,1);
   1.524 +	MutexWait();
   1.525 +	MCOUNT(M1,0);
   1.526 +	IDCHECK(id[0]);
   1.527 +	test.Next(_L("Create threads"));
   1.528 +	TInt i;
   1.529 +	for (i=1; i<=5; ++i)
   1.530 +		id[i]=CreateThread(t[i],i,f+i);
   1.531 +	User::After(50000);		// let threads wait on mutex
   1.532 +	MCOUNT(M1,-5);			// check 5 threads waiting
   1.533 +	for (i=-4; i<=0; ++i)
   1.534 +		{
   1.535 +		MutexSignal(); // wake up next thread
   1.536 +		MutexWait();
   1.537 +		MCOUNT(M1,i);		// check right number of threads waiting
   1.538 +		IDCHECK(id0);		// check we got mutex back straight away
   1.539 +		}
   1.540 +	MutexSignal();
   1.541 +	User::After(50000);		// let threads claim mutex
   1.542 +	MutexWait();
   1.543 +	MCOUNT(M1,0);			// check no threads waiting
   1.544 +	for (i=1; i<=5; ++i)
   1.545 +		{
   1.546 +		IDCHECK(id[i]);		// check they ran in order t1...t5
   1.547 +		Kick(t[i]);			// wake up thread
   1.548 +		}
   1.549 +	IDCHECK(id0);			// check we got it back last
   1.550 +	t[4].SetPriority(EPriorityMore);	// make t4 higher priority
   1.551 +	User::After(50000);		// let threads wait on mutex
   1.552 +	MCOUNT(M1,-5);			// check 5 threads waiting
   1.553 +//	temp = M1.Count();
   1.554 +	MutexSignal();
   1.555 +//	temp = M1.Count();
   1.556 +	User::After(50000);		// let threads claim mutex
   1.557 +	MutexWait();
   1.558 +//	temp = M1.Count();
   1.559 +	MCOUNT(M1,0);			// check no threads waiting
   1.560 +	IDCHECK(id4);			// check they ran in order t4,t1,t2,t3,t5
   1.561 +	IDCHECK(id1);
   1.562 +	IDCHECK(id2);
   1.563 +	IDCHECK(id3);
   1.564 +	IDCHECK(id5);
   1.565 +	IDCHECK(id0);
   1.566 +	t[4].SetPriority(EPriorityNormal);	// make t4 normal priority
   1.567 +	for (i=1; i<=5; ++i)
   1.568 +		Kick(t[i]);			// wake up thread
   1.569 +	User::After(50000);		// let threads wait on mutex
   1.570 +	MCOUNT(M1,-5);			// check 5 threads waiting
   1.571 +
   1.572 +	t[3].SetPriority(EPriorityMore);	// make t3 higher priority
   1.573 +//	temp = M1.Count();
   1.574 +	MutexSignal();
   1.575 +//	temp = M1.Count();
   1.576 +	User::After(50000);		// let threads claim mutex
   1.577 +	MutexWait();
   1.578 +//	temp = M1.Count();
   1.579 +	MCOUNT(M1,0);			// check no threads waiting
   1.580 +	IDCHECK(id3);			// check they ran in order t3,t1,t2,t4,t5
   1.581 +	IDCHECK(id1);
   1.582 +	IDCHECK(id2);
   1.583 +	IDCHECK(id4);
   1.584 +	IDCHECK(id5);
   1.585 +	IDCHECK(id0);
   1.586 +	t[3].SetPriority(EPriorityNormal);	// make t4 normal priority
   1.587 +	for (i=1; i<=5; ++i)
   1.588 +		Kick(t[i]);			// wake up threads
   1.589 +	User::After(50000);		// let threads wait on mutex
   1.590 +	MCOUNT(M1,-5);			// check 5 threads waiting
   1.591 +
   1.592 +	t[2].SetPriority(EPriorityMore);	// make t2 higher priority
   1.593 +	t[1].SetPriority(EPriorityLess);	// make t1 lower priority
   1.594 +	MutexSignal();
   1.595 +	User::After(50000);		// let threads claim mutex
   1.596 +	MutexWait();
   1.597 +	MCOUNT(M1,0);			// check no threads waiting
   1.598 +	IDCHECK(id2);			// check they ran in order t2,t3,t4,t5,t1
   1.599 +	IDCHECK(id3);
   1.600 +	IDCHECK(id4);
   1.601 +	IDCHECK(id5);
   1.602 +	IDCHECK(id1);
   1.603 +	IDCHECK(id0);
   1.604 +
   1.605 +	for (i=1; i<=5; ++i)
   1.606 +		Kick(t[i]);			// wake up threads
   1.607 +	User::After(50000);		// let threads wait on mutex
   1.608 +	MCOUNT(M1,-5);			// check 5 threads waiting
   1.609 +	MutexSignal();
   1.610 +	User::After(50000);		// let threads claim mutex
   1.611 +	MutexWait();
   1.612 +	MCOUNT(M1,0);			// check no threads waiting
   1.613 +	IDCHECK(id2);			// check they ran in order t2,t3,t4,t5,t1
   1.614 +	IDCHECK(id3);
   1.615 +	IDCHECK(id4);
   1.616 +	IDCHECK(id5);
   1.617 +	IDCHECK(id1);
   1.618 +	IDCHECK(id0);
   1.619 +
   1.620 +	test(Exists(2));
   1.621 +	for (i=1; i<=5; ++i)
   1.622 +		Kick(t[i]);			// wake up threads
   1.623 +	User::After(50000);		// let threads wait on mutex
   1.624 +	MCOUNT(M1,-5);			// check 5 threads waiting
   1.625 +	f[2]=&Exit;				// make t2 exit while holding the mutex
   1.626 +	MutexSignal();
   1.627 +	User::After(50000);		// let threads claim mutex
   1.628 +	MutexWait();
   1.629 +	MCOUNT(M1,0);			// check no threads waiting
   1.630 +	test(t[2].ExitType()==EExitKill);	// check t2 has exited
   1.631 +	t[2].Close();
   1.632 +	test(!Exists(2));
   1.633 +	IDCHECK(id2);			// check they ran in order t2,t3,t4,t5,t1
   1.634 +	IDCHECK(id3);
   1.635 +	IDCHECK(id4);
   1.636 +	IDCHECK(id5);
   1.637 +	IDCHECK(id1);
   1.638 +	IDCHECK(id0);
   1.639 +	f[2]=NULL;
   1.640 +	id[2]=CreateThread(t[2],2,f+2);	// recreate t2
   1.641 +	User::After(50000);		// let new t2 wait on mutex
   1.642 +	MCOUNT(M1,-1);			// check 1 thread waiting
   1.643 +	MutexSignal();
   1.644 +	User::After(50000);		// let t2 claim mutex
   1.645 +	MutexWait();
   1.646 +	MCOUNT(M1,0);			// check no threads waiting
   1.647 +	IDCHECK(id2);
   1.648 +	IDCHECK(id0);
   1.649 +
   1.650 +	t[2].SetPriority(EPriorityLess);	// make t2 lower priority
   1.651 +	for (i=1; i<=5; ++i)
   1.652 +		Kick(t[i]);			// wake up threads
   1.653 +	User::After(50000);		// let threads wait on mutex
   1.654 +	MCOUNT(M1,-5);			// check 5 threads waiting
   1.655 +	MutexSignal();			// t3 now pending
   1.656 +	MCOUNT(M1,-3);			// check 4 threads waiting, mutex free
   1.657 +	t[3].Suspend();			// this should wake up t4
   1.658 +	MCOUNT(M1,-2);			// check 3 threads waiting, mutex free
   1.659 +	User::After(50000);		// let threads claim mutex
   1.660 +	MutexWait();
   1.661 +	MCOUNT(M1,0);			// check no threads still waiting
   1.662 +	IDCHECK(id4);			// check they ran in order t4,t5,t1,t2
   1.663 +	IDCHECK(id5);
   1.664 +	IDCHECK(id1);
   1.665 +	IDCHECK(id2);
   1.666 +	IDCHECK(id0);
   1.667 +	Kick(t[1]);				// wake up t1
   1.668 +	User::After(50000);		// let thread wait on mutex
   1.669 +	MCOUNT(M1,-1);			// check 1 thread waiting
   1.670 +	t[3].Resume();			// resume pending t3
   1.671 +	MutexSignal();
   1.672 +	User::After(50000);		// let t2 claim mutex
   1.673 +	MutexWait();
   1.674 +	MCOUNT(M1,0);			// check no threads waiting
   1.675 +	IDCHECK(id3);			// check order t3,t1
   1.676 +	IDCHECK(id1);
   1.677 +	IDCHECK(id0);
   1.678 +
   1.679 +	for (i=1; i<=5; ++i)
   1.680 +		Kick(t[i]);			// wake up threads
   1.681 +	User::After(50000);		// let threads wait on mutex
   1.682 +	MCOUNT(M1,-5);			// check 5 threads waiting
   1.683 +	t[4].Suspend();			// suspend t4
   1.684 +	MCOUNT(M1,-5);			// check 5 threads waiting
   1.685 +	t[4].Suspend();			// suspend t4 again
   1.686 +	MCOUNT(M1,-5);			// check 5 threads waiting
   1.687 +	MutexSignal();
   1.688 +	User::After(50000);		// let threads claim mutex
   1.689 +	MutexWait();
   1.690 +	MCOUNT(M1,-1);			// check 1 thread still waiting
   1.691 +	IDCHECK(id3);			// check they ran in order t3,t5,t1,t2
   1.692 +	IDCHECK(id5);
   1.693 +	IDCHECK(id1);
   1.694 +	IDCHECK(id2);
   1.695 +	IDCHECK(id0);
   1.696 +	MutexSignal();
   1.697 +	t[4].Resume();
   1.698 +	User::After(50000);		// let threads claim mutex
   1.699 +	MutexWait();
   1.700 +	IDCHECK(id0);			// check thread didn't get mutex (still suspended)
   1.701 +	MutexSignal();
   1.702 +	t[4].Resume();
   1.703 +	User::After(50000);		// let threads claim mutex
   1.704 +	MutexWait();
   1.705 +	IDCHECK(id4);			// check order t4 then this
   1.706 +	IDCHECK(id0);
   1.707 +
   1.708 +	for (i=1; i<=5; ++i)
   1.709 +		Kick(t[i]);			// wake up threads
   1.710 +	User::After(50000);		// let threads wait on mutex
   1.711 +	MCOUNT(M1,-5);			// check 5 threads waiting
   1.712 +	MutexWait();			// wait on mutex again
   1.713 +	IDCHECK(id0);
   1.714 +	MutexSignal();			// signal once
   1.715 +	MCOUNT(M1,-5);			// check 5 threads still waiting
   1.716 +	MutexSignal();			// signal again
   1.717 +	MCOUNT(M1,-3);			// check one thread has been woken up and mutex is now free
   1.718 +	User::After(50000);		// let threads claim mutex
   1.719 +	MutexWait();
   1.720 +	MCOUNT(M1,0);			// check no threads still waiting
   1.721 +	IDCHECK(id3);			// check they ran in order t3,t4,t5,t1,t2
   1.722 +	IDCHECK(id4);
   1.723 +	IDCHECK(id5);
   1.724 +	IDCHECK(id1);
   1.725 +	IDCHECK(id2);
   1.726 +	IDCHECK(id0);
   1.727 +
   1.728 +	test.Next(_L("Create more threads"));
   1.729 +	for (i=6; i<=10; ++i)
   1.730 +		id[i]=CreateThread(t[i],i,f+i);
   1.731 +	User::After(50000);		// let threads wait on mutex
   1.732 +	MCOUNT(M1,-5);			// check 5 threads waiting
   1.733 +	MutexSignal();
   1.734 +	User::After(50000);		// let threads claim mutex
   1.735 +	MCOUNT(M1,1);			// check no threads still waiting and mutex free
   1.736 +	IDCHECK(id6);			// check they ran in order t6,t7,t8,t9,t10
   1.737 +	IDCHECK(id7);
   1.738 +	IDCHECK(id8);
   1.739 +	IDCHECK(id9);
   1.740 +	IDCHECK(id10);
   1.741 +	t[8].SetPriority(EPriorityMore);	// t1-t3=less, t4-t7=normal, t8-t10 more, t0 much more
   1.742 +	t[9].SetPriority(EPriorityMore);
   1.743 +	t[10].SetPriority(EPriorityMore);
   1.744 +	t[2].SetPriority(EPriorityLess);
   1.745 +	t[3].SetPriority(EPriorityLess);
   1.746 +
   1.747 +	RackEmUp(t,f,id);
   1.748 +	SimpleCheck(0,NULL,NULL);	// holding thread still blocked
   1.749 +	Kick(t[4]);
   1.750 +	SimpleCheck(6,id,10,8,9,5,1,2);	// 3,6,7 suspended
   1.751 +	t[3].Resume();
   1.752 +	t[6].Resume();
   1.753 +	t[7].Resume();
   1.754 +	SimpleCheck(3,id,6,7,3);	// 3,6,7 resumed
   1.755 +
   1.756 +	RackEmUp(t,f,id);
   1.757 +	SimpleCheck(0,NULL,NULL);	// holding thread still blocked
   1.758 +	Kick(t[4]);
   1.759 +	t[4].Suspend();
   1.760 +	SimpleCheck(0,NULL,NULL);	// holding thread suspended
   1.761 +	t[4].Resume();
   1.762 +	SimpleCheck(6,id,10,8,9,5,1,2);	// 3,6,7 suspended
   1.763 +	t[3].Resume();
   1.764 +	t[6].Resume();
   1.765 +	t[7].Resume();
   1.766 +	SimpleCheck(3,id,6,7,3);	// 3,6,7 resumed
   1.767 +
   1.768 +	RackEmUp(t,f,id);
   1.769 +	Kick(t[4]);
   1.770 +	t[4].SetPriority(EPriorityRealTime);
   1.771 +	MCOUNT(M1,-5);			// should be 6 waiting, mutex free
   1.772 +	t[4].SetPriority(EPriorityNormal);
   1.773 +	t[8].SetPriority(EPriorityRealTime);	// change pending thread priority
   1.774 +	MCOUNT(M1,-4);			// should be 5 waiting, mutex free
   1.775 +	t[8].SetPriority(EPriorityMore);
   1.776 +	NUMCHECK(1);
   1.777 +	IDCHECK(id8);
   1.778 +	t[3].SetPriority(EPriorityRealTime);	// change suspended thread priority
   1.779 +	SimpleCheck(5,id,9,10,5,1,2);	// 3,6,7 suspended
   1.780 +	t[6].Resume();
   1.781 +	t[7].Resume();
   1.782 +	t[3].Resume();			// this should run right away
   1.783 +	NUMCHECK(1);
   1.784 +	IDCHECK(id3);
   1.785 +	SimpleCheck(2,id,6,7);	// 6,7 resumed
   1.786 +	t[3].SetPriority(EPriorityLess);
   1.787 +
   1.788 +	RackEmUp(t,f,id);
   1.789 +	Kick(t[4]);
   1.790 +	t[1].SetPriority(EPriorityRealTime);	// change waiting thread priority
   1.791 +											// this should run right away
   1.792 +	NUMCHECK(1);
   1.793 +	IDCHECK(id1);
   1.794 +	t[1].SetPriority(EPriorityLess);
   1.795 +	// t8,t9,t10 should now be pending
   1.796 +	MCOUNT(M1,1-5);
   1.797 +	t[8].Suspend();			// this should wake up t5
   1.798 +	t[9].Suspend();			// this should wake up t2
   1.799 +	MCOUNT(M1,1-3);
   1.800 +	t[8].Suspend();			// this should have no further effect
   1.801 +	t[8].Resume();			// this should have no further effect
   1.802 +	MCOUNT(M1,1-3);
   1.803 +	SimpleCheck(3,id,10,5,2);
   1.804 +	MCOUNT(M1,1-3);
   1.805 +	t[3].Resume();
   1.806 +	t[6].Resume();
   1.807 +	t[7].Resume();
   1.808 +	t[8].Resume();
   1.809 +	t[9].Resume();
   1.810 +	SimpleCheck(5,id,8,9,6,7,3);
   1.811 +
   1.812 +	RackEmUp(t,f,id);
   1.813 +	MCOUNT(M1,-7);
   1.814 +	t[8].Suspend();			// this shouldn't wake anything up
   1.815 +	t[9].Suspend();			// this shouldn't wake anything up
   1.816 +	MCOUNT(M1,-7);
   1.817 +	Kick(t[4]);
   1.818 +	t[4].SetPriority(EPriorityRealTime);
   1.819 +	MCOUNT(M1,1-6);				// should be 6 waiting, mutex free, t10 pending
   1.820 +	t[4].SetPriority(EPriorityNormal);
   1.821 +	t[10].SetPriority(EPriorityLess);	// this should wake up t5
   1.822 +	MCOUNT(M1,1-5);				// should be 5 waiting, mutex free, t10, t5 pending
   1.823 +	SimpleCheck(4,id,5,10,1,2);
   1.824 +	t[3].SetPriority(EPriorityRealTime);	// boost suspended+waiting thread
   1.825 +	MCOUNT(M1,1-3);			// should be 3 waiting+suspended, mutex free, t8, t9 pending+suspended
   1.826 +	t[6].Resume();
   1.827 +	t[7].Resume();
   1.828 +	t[8].Resume();
   1.829 +	t[9].Resume();
   1.830 +	t[3].Resume();			// this should run immediately
   1.831 +	MCOUNT(M1,1);			// t8,t9,t6,t7 pending, mutex free
   1.832 +	NUMCHECK(1);
   1.833 +	IDCHECK(id3);			// t3 should have run
   1.834 +	t[3].SetPriority(EPriorityLess);
   1.835 +	t[9].SetPriority(EPriorityMuchLess);	// lower pending thread priority
   1.836 +	SimpleCheck(4,id,8,6,7,9);
   1.837 +	t[9].SetPriority(EPriorityMore);
   1.838 +	t[10].SetPriority(EPriorityMore);
   1.839 +
   1.840 +	RackEmUp(t,f,id);
   1.841 +	MCOUNT(M1,-7);
   1.842 +	t[8].Suspend();			// this shouldn't wake anything up
   1.843 +	t[9].Suspend();			// this shouldn't wake anything up
   1.844 +	MCOUNT(M1,-7);
   1.845 +	Kick(t[4]);
   1.846 +	MCOUNT(M1,-7);
   1.847 +	t[4].SetPriority(EPriorityRealTime);
   1.848 +	MCOUNT(M1,1-6);			// should be 6 waiting, mutex free, t10 pending, t8,t9 pending+suspended
   1.849 +	t[4].SetPriority(EPriorityNormal);
   1.850 +	t[10].SetPriority(EPriorityMuchLess);	// lower pending thread priority
   1.851 +	MCOUNT(M1,1-5);			// should now be 5 waiting, mutex free, t10,t5 pending, t8,t9 pending+suspended
   1.852 +	t[6].Resume();
   1.853 +	t[7].Resume();
   1.854 +	t[3].Resume();			// this gets made READY straight away
   1.855 +	SimpleCheck(7,id,5,6,7,3,1,2,10);
   1.856 +	t[8].Resume();
   1.857 +	t[9].Resume();
   1.858 +	SimpleCheck(2,id,8,9);
   1.859 +	t[10].SetPriority(EPriorityMore);
   1.860 +
   1.861 +	RackEmUp(t,f,id);
   1.862 +	MCOUNT(M1,-7);
   1.863 +	Kick(t[4]);
   1.864 +	t[9].Kill(0);			// kill pending thread
   1.865 +	t[9].Close();
   1.866 +	test(!Exists(9));
   1.867 +	t[1].Kill(0);			// kill waiting thread
   1.868 +	t[1].Close();
   1.869 +	test(!Exists(1));
   1.870 +	t[6].Kill(0);			// kill suspended+waiting thread
   1.871 +	t[6].Close();
   1.872 +	t[7].Resume();
   1.873 +	t[3].Resume();
   1.874 +	test(!Exists(6));
   1.875 +	SimpleCheck(6,id,10,8,5,7,2,3);	// 8 runs first and gets blocked behind 10
   1.876 +	Resurrect(9,EPriorityMore,t,f,id);
   1.877 +	Resurrect(1,EPriorityLess,t,f,id);
   1.878 +	Resurrect(6,EPriorityNormal,t,f,id);
   1.879 +
   1.880 +	RackEmUp(t,f,id);
   1.881 +	MCOUNT(M1,-7);
   1.882 +	t[8].Suspend();			// this shouldn't wake anything up
   1.883 +	t[9].Suspend();			// this shouldn't wake anything up
   1.884 +	MCOUNT(M1,-7);
   1.885 +	Kick(t[4]);
   1.886 +	MCOUNT(M1,-7);
   1.887 +	t[4].SetPriority(EPriorityRealTime);
   1.888 +	MCOUNT(M1,1-6);			// should be 6 waiting, mutex free, t10 pending, t8,t9 pending+suspended
   1.889 +	t[4].SetPriority(EPriorityNormal);
   1.890 +	t[10].Kill(0);			// kill pending thread - this should wake up t5
   1.891 +	t[10].Close();
   1.892 +	test(!Exists(10));
   1.893 +	MCOUNT(M1,1-5);			// should be 5 waiting, mutex free, t5 pending, t8,t9 pending+suspended
   1.894 +	t[5].SetPriority(EPriorityRealTime);	// this should make t5 run
   1.895 +	MCOUNT(M1,1-4);			// should be 4 waiting, mutex free, t1 pending, t8,t9 pending+suspended
   1.896 +	t[5].SetPriority(EPriorityNormal);
   1.897 +	NUMCHECK(1);
   1.898 +	IDCHECK(id5);
   1.899 +	t[8].SetPriority(EPriorityRealTime);	// this shouldn't make anything happen
   1.900 +	MCOUNT(M1,1-4);			// mutex free, t1 pending, t8,t9 pending+suspended, t3,t6,t7 wait+susp, t2 waiting
   1.901 +	NUMCHECK(0);
   1.902 +	t[8].Resume();
   1.903 +	MCOUNT(M1,1-3);			// mutex free, t1,t2 pending, t9 pending+suspended, t3,t6,t7 wait+susp
   1.904 +	NUMCHECK(1);
   1.905 +	IDCHECK(id8);
   1.906 +	t[8].SetPriority(EPriorityMore);
   1.907 +	t[3].Resume();
   1.908 +	t[6].Resume();
   1.909 +	t[7].Resume();
   1.910 +	t[9].Resume();
   1.911 +	SimpleCheck(6,id,9,6,7,1,2,3);
   1.912 +	Resurrect(10,EPriorityMore,t,f,id);
   1.913 +
   1.914 +	RackEmUp(t,f,id);
   1.915 +	MCOUNT(M1,-7);
   1.916 +	t[8].Suspend();			// this shouldn't wake anything up
   1.917 +	t[9].Suspend();			// this shouldn't wake anything up
   1.918 +	MCOUNT(M1,-7);
   1.919 +	Kick(t[4]);
   1.920 +	MCOUNT(M1,-7);
   1.921 +	t[4].SetPriority(EPriorityRealTime);
   1.922 +	MCOUNT(M1,1-6);			// mutex free, t10 pending, t8,t9 pending+susp, t3,t6,t7 wait+susp, t1,t2,t5 wait
   1.923 +	t[4].SetPriority(EPriorityNormal);
   1.924 +	t[1].SetPriority(EPriorityRealTime);	// this should be able to run and claim the mutex
   1.925 +	NUMCHECK(1);
   1.926 +	IDCHECK(id1);
   1.927 +	MCOUNT(M1,1-4);			// mutex free, t10,t5 pending, t8,t9 pending+susp, t3,t6,t7 wait+susp, t2 wait
   1.928 +	t[1].SetPriority(EPriorityLess);
   1.929 +	t[3].Resume();
   1.930 +	t[6].Resume();
   1.931 +	t[7].Resume();
   1.932 +	t[9].Resume();
   1.933 +	t[8].Resume();
   1.934 +	SimpleCheck(8,id,10,9,8,5,6,7,3,2);
   1.935 +
   1.936 +	RackEmUp(t,f,id);
   1.937 +	MCOUNT(M1,-7);
   1.938 +	Kick(t[4]);
   1.939 +	M1.Close();				// close the mutex - non-suspended threads should all panic with KERN-EXEC 0
   1.940 +	TBool jit = User::JustInTime();
   1.941 +	User::SetJustInTime(EFalse);
   1.942 +	User::After(1000000);
   1.943 +	User::SetJustInTime(jit);
   1.944 +	for (i=1; i<=10; ++i)
   1.945 +		{
   1.946 +		if (i==3 || i==6 || i==7)
   1.947 +			{
   1.948 +			test(t[i].ExitType()==EExitPending);
   1.949 +			}
   1.950 +		else
   1.951 +			{
   1.952 +			test(t[i].ExitType()==EExitPanic);
   1.953 +			test(t[i].ExitReason()==EBadHandle);
   1.954 +			test(t[i].ExitCategory()==_L("KERN-EXEC"));
   1.955 +			t[i].Close();
   1.956 +			test(!Exists(i));
   1.957 +			}
   1.958 +		}
   1.959 +	t[3].Resume();
   1.960 +	t[6].Resume();
   1.961 +	t[7].Resume();
   1.962 +	User::SetJustInTime(EFalse);
   1.963 +	User::After(1000000);
   1.964 +	User::SetJustInTime(jit);
   1.965 +	for (i=1; i<=10; ++i)
   1.966 +		{
   1.967 +		if (i==3 || i==6 || i==7)
   1.968 +			{
   1.969 +			test(t[i].ExitType()==EExitPanic);
   1.970 +			test(t[i].ExitReason()==EBadHandle);
   1.971 +			test(t[i].ExitCategory()==_L("KERN-EXEC"));
   1.972 +			t[i].Close();
   1.973 +			test(!Exists(i));
   1.974 +			}
   1.975 +		}
   1.976 +
   1.977 +	test.End();
   1.978 +	}
   1.979 +
   1.980 +/*****************************************************************************
   1.981 + * Mutex benchmarks
   1.982 + *****************************************************************************/
   1.983 +TInt MutexSpeed(TAny* aPtr)
   1.984 +	{
   1.985 +	TInt& count=*(TInt*)aPtr;
   1.986 +	RThread().SetPriority(EPriorityMore);
   1.987 +	FOREVER
   1.988 +		{
   1.989 +		M1.Wait();
   1.990 +		M1.Signal();
   1.991 +		++count;
   1.992 +		}
   1.993 +	}
   1.994 +
   1.995 +TInt MutexSpeed2(TAny* aPtr)
   1.996 +	{
   1.997 +	TInt& count=*(TInt*)aPtr;
   1.998 +	RThread().SetPriority(EPriorityMore);
   1.999 +	FOREVER
  1.1000 +		{
  1.1001 +		M1.Wait();
  1.1002 +		M1.Wait();
  1.1003 +		M1.Signal();
  1.1004 +		M1.Signal();
  1.1005 +		++count;
  1.1006 +		}
  1.1007 +	}
  1.1008 +
  1.1009 +void TestMutexSpeed()
  1.1010 +	{
  1.1011 +	test.Start(_L("Test mutex speed"));
  1.1012 +	TInt count=0;
  1.1013 +	TInt r=M1.CreateLocal();
  1.1014 +	test(r==KErrNone);
  1.1015 +
  1.1016 +	RThread t;
  1.1017 +	r=t.Create(_L("Speed"),MutexSpeed,0x1000,NULL,&count);
  1.1018 +	test(r==KErrNone);
  1.1019 +	t.SetPriority(EPriorityRealTime);
  1.1020 +	t.Resume();
  1.1021 +	User::AfterHighRes(1000000);
  1.1022 +	t.Kill(0);
  1.1023 +	t.Close();
  1.1024 +	test(!Exists(_L("Speed")));
  1.1025 +	test.Printf(_L("%d wait/signal in 1 second\n"),count);
  1.1026 +
  1.1027 +	TInt count2=0;
  1.1028 +	r=t.Create(_L("Speed2"),MutexSpeed2,0x1000,NULL,&count2);
  1.1029 +	test(r==KErrNone);
  1.1030 +	t.SetPriority(EPriorityRealTime);
  1.1031 +	t.Resume();
  1.1032 +	User::AfterHighRes(1000000);
  1.1033 +	t.Kill(0);
  1.1034 +	t.Close();
  1.1035 +	test(!Exists(_L("Speed2")));
  1.1036 +	test.Printf(_L("%d double wait/signal in 1 second\n"),count2);
  1.1037 +
  1.1038 +	M1.Close();
  1.1039 +	test.End();
  1.1040 +	}
  1.1041 +
  1.1042 +/*****************************************************************************
  1.1043 + * Utilities for semaphore test
  1.1044 + *****************************************************************************/
  1.1045 +void SemWait()
  1.1046 +	{
  1.1047 +	S.Wait();
  1.1048 +	++Count;
  1.1049 +	ThreadId[PutIx++]=(TUint)RThread().Id();
  1.1050 +	}
  1.1051 +
  1.1052 +void SemSignal()
  1.1053 +	{
  1.1054 +	S.Signal();
  1.1055 +	}
  1.1056 +
  1.1057 +TInt SemThreadFunction(TAny* aPtr)
  1.1058 +	{
  1.1059 +	PFV& f=*(PFV*)aPtr;
  1.1060 +	FOREVER
  1.1061 +		{
  1.1062 +		SemWait();
  1.1063 +		if (f)
  1.1064 +			f();
  1.1065 +		SemSignal();
  1.1066 +		User::WaitForAnyRequest();
  1.1067 +		}
  1.1068 +	}
  1.1069 +
  1.1070 +void Wait()
  1.1071 +	{
  1.1072 +	User::WaitForAnyRequest();
  1.1073 +	}
  1.1074 +
  1.1075 +TUint CreateSemThread(RThread& t, TInt n, TAny* aPtr)
  1.1076 +	{
  1.1077 +	TBuf<4> b;
  1.1078 +	b.Num(n);
  1.1079 +	TInt r=t.Create(b,SemThreadFunction,0x1000,NULL,aPtr);
  1.1080 +	test(r==KErrNone);
  1.1081 +	t.Resume();
  1.1082 +	TUint id=t.Id();
  1.1083 +	return id;
  1.1084 +	}
  1.1085 +
  1.1086 +/*
  1.1087 +Possible thread relationships with semaphore:
  1.1088 +	Waiting
  1.1089 +	Waiting + suspended
  1.1090 +
  1.1091 +Need to verify correct behaviour when the following actions occur for each of these states:
  1.1092 +	Suspend thread
  1.1093 +	Resume thread
  1.1094 +	Change thread priority
  1.1095 +	Thread exits
  1.1096 +	Thread is killed
  1.1097 +	Semaphore deleted
  1.1098 +*/
  1.1099 +
  1.1100 +void RackEmUp2(RThread* t, PFV* f, TUint* id)
  1.1101 +	{
  1.1102 +	// set up
  1.1103 +	// t1, t2, t4, t5, t6, t8, t9 waiting
  1.1104 +	// t3, t7, t10 waiting+suspended
  1.1105 +	(void)f;
  1.1106 +	MCOUNT(S,2);			// check semaphore level = 2
  1.1107 +	SemWait();
  1.1108 +	SemWait();
  1.1109 +	MCOUNT(S,0);			// check semaphore level = 0
  1.1110 +	NUMCHECK(2);
  1.1111 +	IDCHECK(id0);
  1.1112 +	IDCHECK(id0);
  1.1113 +	TInt i;
  1.1114 +	for (i=1; i<=10; ++i)
  1.1115 +		Kick(t[i]);			// wake up threads
  1.1116 +	User::After(50000);		// let threads wait
  1.1117 +	MCOUNT(S,-10);			// check 10 threads waiting
  1.1118 +	t[7].Resume();			// test resume when not suspended
  1.1119 +	MCOUNT(S,-10);			// check 7 threads waiting
  1.1120 +	t[3].Suspend();
  1.1121 +	t[7].Suspend();
  1.1122 +	t[10].Suspend();		// now have required state
  1.1123 +	t[3].Suspend();			// suspend and resume t3 again for good measure
  1.1124 +	t[3].Resume();
  1.1125 +	MCOUNT(S,-7);			// check 7 threads waiting
  1.1126 +	}
  1.1127 +
  1.1128 +void Resurrect2(TInt n, TThreadPriority aPriority, RThread* t, PFV* f, TUint* id)
  1.1129 +	{
  1.1130 +	f[n]=NULL;
  1.1131 +	id[n]=CreateSemThread(t[n],n,f+n);
  1.1132 +	t[n].SetPriority(EPriorityRealTime);
  1.1133 +	t[n].SetPriority(aPriority);
  1.1134 +	NUMCHECK(1);
  1.1135 +	IDCHECK(id[n]);
  1.1136 +	}
  1.1137 +
  1.1138 +/*****************************************************************************
  1.1139 + * Semaphore exhaustive state transition test
  1.1140 + *****************************************************************************/
  1.1141 +void TestSemaphore()
  1.1142 +	{
  1.1143 +	test.Start(_L("Test semaphore state transitions"));
  1.1144 +	RThread t[11];
  1.1145 +	TUint id[11];
  1.1146 +	PFV f[11]={NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
  1.1147 +	id[0]=(TUint)RThread().Id();
  1.1148 +	PutIx=0;
  1.1149 +	GetIx=0;
  1.1150 +	Count=0;
  1.1151 +	test.Next(_L("Create semaphore"));
  1.1152 +	TInt r=S.CreateLocal(2);
  1.1153 +	test(r==KErrNone);
  1.1154 +	MCOUNT(S,2);
  1.1155 +	SemWait();
  1.1156 +	MCOUNT(S,1);
  1.1157 +	SemSignal();
  1.1158 +	MCOUNT(S,2);
  1.1159 +	SemWait();
  1.1160 +	SemWait();
  1.1161 +	MCOUNT(S,0);
  1.1162 +	S.Signal(2);
  1.1163 +	MCOUNT(S,2);
  1.1164 +	NUMCHECK(3);
  1.1165 +	IDCHECK(id0);
  1.1166 +	IDCHECK(id0);
  1.1167 +	IDCHECK(id0);
  1.1168 +	test.Next(_L("Create threads"));
  1.1169 +	TInt i;
  1.1170 +	for (i=1; i<=10; ++i)
  1.1171 +		{
  1.1172 +		id[i]=CreateSemThread(t[i],i,f+i);
  1.1173 +		f[i]=&Wait;
  1.1174 +		}
  1.1175 +	t[8].SetPriority(EPriorityMore);	// t1-t3=less, t4-t7=normal, t8-t10 more, t0 much more
  1.1176 +	t[9].SetPriority(EPriorityMore);
  1.1177 +	t[10].SetPriority(EPriorityMore);
  1.1178 +	t[1].SetPriority(EPriorityLess);
  1.1179 +	t[2].SetPriority(EPriorityLess);
  1.1180 +	t[3].SetPriority(EPriorityLess);
  1.1181 +	User::After(50000);
  1.1182 +	MCOUNT(S,-8);			// check 8 waiting
  1.1183 +	NUMCHECK(2);
  1.1184 +	IDCHECK(id8);
  1.1185 +	IDCHECK(id9);			// check t8,t9 got through
  1.1186 +	t[8].SetPriority(EPriorityRealTime);
  1.1187 +	Kick(t[8]);				// let t8 run and signal
  1.1188 +	t[8].SetPriority(EPriorityMore);
  1.1189 +	MCOUNT(S,-7);			// check 7 waiting
  1.1190 +	User::After(50000);		// let next thread obtain semaphore
  1.1191 +	MCOUNT(S,-7);			// check 7 waiting
  1.1192 +	NUMCHECK(1);
  1.1193 +	IDCHECK(id10);			// check t10 got it
  1.1194 +	Kick(t[10]);			// let t10 run and signal
  1.1195 +	User::After(50000);		// let next thread obtain semaphore
  1.1196 +	MCOUNT(S,-6);			// check 6 waiting
  1.1197 +	NUMCHECK(1);
  1.1198 +	IDCHECK(id4);			// check t4 got it
  1.1199 +	t[1].SetPriority(EPriorityRealTime);	// boost t1
  1.1200 +	MCOUNT(S,-6);			// check 6 still waiting
  1.1201 +	User::After(50000);		// let next thread obtain semaphore
  1.1202 +	MCOUNT(S,-6);			// check 6 still waiting
  1.1203 +	NUMCHECK(0);
  1.1204 +	Kick(t[9]);				// make t9 ready to run and signal
  1.1205 +	MCOUNT(S,-6);			// check 6 still waiting
  1.1206 +	User::After(50000);		// let next thread obtain semaphore
  1.1207 +	MCOUNT(S,-5);			// check 5 waiting
  1.1208 +	NUMCHECK(1);
  1.1209 +	IDCHECK(id1);			// check t1 got it
  1.1210 +	t[1].SetPriority(EPriorityLess);
  1.1211 +	Kick(t[1]);				// kick all remaining threads
  1.1212 +	Kick(t[2]);
  1.1213 +	Kick(t[3]);
  1.1214 +	Kick(t[4]);
  1.1215 +	Kick(t[5]);
  1.1216 +	Kick(t[6]);
  1.1217 +	Kick(t[7]);
  1.1218 +	User::After(50000);		// let them run and obtain/signal the semaphore
  1.1219 +	MCOUNT(S,2);			// check semaphore now back to initial level
  1.1220 +	SimpleCheck(5,id,5,6,7,2,3);
  1.1221 +
  1.1222 +	for (i=1; i<=10; ++i)
  1.1223 +		f[i]=NULL;
  1.1224 +	RackEmUp2(t,f,id);		// set up threads waiting on semaphore again
  1.1225 +	S.Signal();
  1.1226 +	SimpleCheck(7,id,8,9,4,5,6,1,2);	// let them go
  1.1227 +	MCOUNT(S,1);
  1.1228 +	S.Wait();
  1.1229 +	t[3].SetPriority(EPriorityRealTime);	// change suspended thread priority
  1.1230 +	t[7].Resume();
  1.1231 +	SimpleCheck(0,id);		// t7 should wait for signal
  1.1232 +	S.Signal();
  1.1233 +	SimpleCheck(1,id,7);
  1.1234 +	MCOUNT(S,1);
  1.1235 +	t[3].Resume();
  1.1236 +	t[10].Resume();
  1.1237 +	NUMCHECK(1);
  1.1238 +	IDCHECK(id3);			// t3 should have grabbed semaphore as soon as we resumed it
  1.1239 +	SimpleCheck(1,id,10);
  1.1240 +	t[3].SetPriority(EPriorityLess);
  1.1241 +	S.Signal();				// put level back to 2
  1.1242 +
  1.1243 +	RackEmUp2(t,f,id);		// set up threads waiting on semaphore again
  1.1244 +	S.Signal();
  1.1245 +	SimpleCheck(7,id,8,9,4,5,6,1,2);	// let them go
  1.1246 +	MCOUNT(S,1);
  1.1247 +	S.Wait();
  1.1248 +	t[3].SetPriority(EPriorityRealTime);	// change suspended thread priority
  1.1249 +	t[7].Resume();
  1.1250 +	SimpleCheck(0,id);		// t7 should wait for signal
  1.1251 +	S.Signal();
  1.1252 +	SimpleCheck(1,id,7);
  1.1253 +	MCOUNT(S,1);
  1.1254 +	t[10].Resume();
  1.1255 +	t[3].Resume();			// t3 not woken up here since t10 has already been given the semaphore
  1.1256 +	NUMCHECK(0);
  1.1257 +	SimpleCheck(2,id,10,3);
  1.1258 +	t[3].SetPriority(EPriorityLess);
  1.1259 +	S.Signal();				// put level back to 2
  1.1260 +
  1.1261 +	RackEmUp2(t,f,id);		// set up threads waiting on semaphore again
  1.1262 +	S.Signal();
  1.1263 +	SimpleCheck(7,id,8,9,4,5,6,1,2);	// let them go
  1.1264 +	MCOUNT(S,1);
  1.1265 +	S.Wait();
  1.1266 +	t[3].SetPriority(EPriorityRealTime);	// change suspended thread priority
  1.1267 +	t[7].Resume();
  1.1268 +	SimpleCheck(0,id);		// t7 should wait for signal
  1.1269 +	S.Signal();
  1.1270 +	S.Signal();				// put level back to 2
  1.1271 +	SimpleCheck(1,id,7);
  1.1272 +	MCOUNT(S,2);
  1.1273 +	t[10].Resume();
  1.1274 +	t[3].Resume();			// t3 and t10 both woken up here, t3 should run and signal
  1.1275 +	MCOUNT(S,1);
  1.1276 +	NUMCHECK(1);
  1.1277 +	IDCHECK(id3);
  1.1278 +	SimpleCheck(1,id,10);
  1.1279 +	t[3].SetPriority(EPriorityLess);
  1.1280 +
  1.1281 +	RackEmUp2(t,f,id);		// set up threads waiting on semaphore again
  1.1282 +	t[9].Kill(0);			// kill waiting thread
  1.1283 +	t[9].Close();
  1.1284 +	test(!Exists(9));
  1.1285 +	t[10].Kill(0);			// kill suspended thread
  1.1286 +	t[10].Close();
  1.1287 +	test(!Exists(10));
  1.1288 +	MCOUNT(S,-6);
  1.1289 +	f[5]=&Exit;				// get t5 to exit after acquiring semaphore
  1.1290 +	S.Signal();
  1.1291 +	SimpleCheck(3,id,8,4,5);	// let them go
  1.1292 +	MCOUNT(S,-3);			// check one signal has been lost due to t5 exiting
  1.1293 +	t[5].Close();
  1.1294 +	test(!Exists(5));
  1.1295 +	t[3].Resume();
  1.1296 +	t[7].Resume();
  1.1297 +	MCOUNT(S,-5);
  1.1298 +	S.Signal();
  1.1299 +	SimpleCheck(5,id,6,7,1,2,3);	// let them go
  1.1300 +	MCOUNT(S,1);
  1.1301 +	Resurrect2(9,EPriorityMore,t,f,id);
  1.1302 +	Resurrect2(10,EPriorityMore,t,f,id);
  1.1303 +	Resurrect2(5,EPriorityNormal,t,f,id);
  1.1304 +	S.Signal();
  1.1305 +
  1.1306 +	RackEmUp2(t,f,id);		// set up threads waiting on semaphore again
  1.1307 +	f[5]=&Exit;				// get t5 to exit after acquiring semaphore
  1.1308 +	S.Close();				// close semaphore - threads should panic except for 5
  1.1309 +
  1.1310 +	TBool jit = User::JustInTime();
  1.1311 +	User::SetJustInTime(EFalse);
  1.1312 +	User::After(1000000);
  1.1313 +	User::SetJustInTime(jit);
  1.1314 +	for (i=1; i<=10; ++i)
  1.1315 +		{
  1.1316 +		if (i==3 || i==7 || i==10)
  1.1317 +			{
  1.1318 +			test(t[i].ExitType()==EExitPending);
  1.1319 +			}
  1.1320 +		else if (i!=5)
  1.1321 +			{
  1.1322 +			test(t[i].ExitType()==EExitPanic);
  1.1323 +			test(t[i].ExitReason()==EBadHandle);
  1.1324 +			test(t[i].ExitCategory()==_L("KERN-EXEC"));
  1.1325 +			t[i].Close();
  1.1326 +			test(!Exists(i));
  1.1327 +			}
  1.1328 +		else
  1.1329 +			{
  1.1330 +			test(t[i].ExitType()==EExitKill);
  1.1331 +			test(t[i].ExitReason()==0);
  1.1332 +			t[i].Close();
  1.1333 +			test(!Exists(i));
  1.1334 +			}
  1.1335 +		}
  1.1336 +	t[3].Resume();
  1.1337 +	t[7].Resume();
  1.1338 +	t[10].Resume();
  1.1339 +	User::SetJustInTime(EFalse);
  1.1340 +	User::After(1000000);
  1.1341 +	User::SetJustInTime(jit);
  1.1342 +	for (i=1; i<=10; ++i)
  1.1343 +		{
  1.1344 +		if (i==3 || i==7 || i==10)
  1.1345 +			{
  1.1346 +			test(t[i].ExitType()==EExitPanic);
  1.1347 +			test(t[i].ExitReason()==EBadHandle);
  1.1348 +			test(t[i].ExitCategory()==_L("KERN-EXEC"));
  1.1349 +			t[i].Close();
  1.1350 +			test(!Exists(i));
  1.1351 +			}
  1.1352 +		}
  1.1353 +
  1.1354 +	test.End();
  1.1355 +	}
  1.1356 +
  1.1357 +/*****************************************************************************
  1.1358 + * Semaphore benchmarks
  1.1359 + *****************************************************************************/
  1.1360 +TInt SemSpeed(TAny* aPtr)
  1.1361 +	{
  1.1362 +	TInt& count=*(TInt*)aPtr;
  1.1363 +	RThread().SetPriority(EPriorityMore);
  1.1364 +	FOREVER
  1.1365 +		{
  1.1366 +		S.Wait();
  1.1367 +		S.Signal();
  1.1368 +		++count;
  1.1369 +		}
  1.1370 +	}
  1.1371 +
  1.1372 +void TestSemSpeed()
  1.1373 +	{
  1.1374 +	test.Start(_L("Test semaphore speed"));
  1.1375 +	TInt count=0;
  1.1376 +	TInt r=S.CreateLocal(1);
  1.1377 +	test(r==KErrNone);
  1.1378 +
  1.1379 +	RThread t;
  1.1380 +	r=t.Create(_L("SemSpeed"),SemSpeed,0x1000,NULL,&count);
  1.1381 +	test(r==KErrNone);
  1.1382 +	t.SetPriority(EPriorityRealTime);
  1.1383 +	t.Resume();
  1.1384 +	User::AfterHighRes(1000000);
  1.1385 +	t.Kill(0);
  1.1386 +	t.Close();
  1.1387 +	test(!Exists(_L("SemSpeed")));
  1.1388 +	test.Printf(_L("%d wait/signal in 1 second\n"),count);
  1.1389 +
  1.1390 +	S.Close();
  1.1391 +	test.End();
  1.1392 +	}
  1.1393 +
  1.1394 +
  1.1395 +GLDEF_C TInt E32Main()
  1.1396 +	{
  1.1397 +	test.Title();
  1.1398 +
  1.1399 +	test.Start(_L("Test mutexes and semaphores"));
  1.1400 +	RThread().SetPriority(EPriorityMuchMore);
  1.1401 +	TInt r=Main.Duplicate(RThread());
  1.1402 +	test(r==KErrNone);
  1.1403 +
  1.1404 +	Test0();
  1.1405 +	Test1();
  1.1406 +	TestMutex1();
  1.1407 +	TestMutex2();
  1.1408 +	TestSemaphore();
  1.1409 +	
  1.1410 +	TestMutexSpeed();
  1.1411 +	TestSemSpeed();
  1.1412 +
  1.1413 +	Main.Close();
  1.1414 +	test.End();
  1.1415 +	return KErrNone;
  1.1416 +	}
  1.1417 +