os/kernelhwsrv/kerneltest/e32test/prime/t_semutx2.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
// Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of the License "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
// e32test\prime\t_semutx2.cpp
sl@0
    15
// Test RSemaphore and RMutex
sl@0
    16
// Overview:
sl@0
    17
// Tests the RSemaphore and RMutex
sl@0
    18
// API Information:
sl@0
    19
// RSemaphore, RMutex
sl@0
    20
// Details:
sl@0
    21
// - Test and verify that thread priorities work as expected.
sl@0
    22
// - Test and verify that signalling an RMutex from the wrong
sl@0
    23
// thread fails as expected.
sl@0
    24
// - Test and verify that mutex priority inheritance works as
sl@0
    25
// expected.
sl@0
    26
// - Perform an exhaustive state transition test using mutexs
sl@0
    27
// and up to ten threads. Verify priorities, order of execution, 
sl@0
    28
// mutex signalling, suspend, resume, kill and close. Verify 
sl@0
    29
// results are as expected.
sl@0
    30
// - Test semaphore speed by counting how many Wait/Signal 
sl@0
    31
// operations can be completed in one second.
sl@0
    32
// Platforms/Drives/Compatibility:
sl@0
    33
// All.
sl@0
    34
// Assumptions/Requirement/Pre-requisites:
sl@0
    35
// Failures and causes:
sl@0
    36
// Base Port information:
sl@0
    37
// 
sl@0
    38
//
sl@0
    39
sl@0
    40
#include <e32test.h>
sl@0
    41
sl@0
    42
RMutex M1;
sl@0
    43
RMutex M2;
sl@0
    44
RSemaphore S;
sl@0
    45
sl@0
    46
const TInt KBufferSize=4096;
sl@0
    47
TUint ThreadId[KBufferSize];
sl@0
    48
TInt PutIx;
sl@0
    49
TInt GetIx;
sl@0
    50
TInt Count;
sl@0
    51
RThread Main;
sl@0
    52
sl@0
    53
sl@0
    54
RTest test(_L("T_SEMUTX2"));
sl@0
    55
sl@0
    56
/*****************************************************************************
sl@0
    57
 * Utility functions / macros
sl@0
    58
 *****************************************************************************/
sl@0
    59
#define TRACE_ON	User::SetDebugMask(0xffdfffff);
sl@0
    60
#define TRACE_OFF	User::SetDebugMask(0x80000000);
sl@0
    61
sl@0
    62
//#define MCOUNT(m,c)	test((m).Count() ==(c))
sl@0
    63
// mutex count value is not visible for user any more
sl@0
    64
#define MCOUNT(m,c) (void)(1)
sl@0
    65
#define IDCHECK(x) test(GetNextId()==(x))
sl@0
    66
#define NUMCHECK(x)	test(NumIdsPending()==(x))
sl@0
    67
sl@0
    68
#define id0		id[0]
sl@0
    69
#define id1		id[1]
sl@0
    70
#define id2		id[2]
sl@0
    71
#define id3		id[3]
sl@0
    72
#define id4		id[4]
sl@0
    73
#define id5		id[5]
sl@0
    74
#define id6		id[6]
sl@0
    75
#define id7		id[7]
sl@0
    76
#define id8		id[8]
sl@0
    77
#define id9		id[9]
sl@0
    78
#define id10	id[10]
sl@0
    79
sl@0
    80
TBool Exists(const TDesC& aName)
sl@0
    81
	{
sl@0
    82
	TFullName n(RProcess().Name());
sl@0
    83
	n+=_L("::");
sl@0
    84
	n+=aName;
sl@0
    85
	TFindThread ft(n);
sl@0
    86
	TFullName fn;
sl@0
    87
	return ft.Next(fn)==KErrNone;
sl@0
    88
	}
sl@0
    89
sl@0
    90
TBool Exists(TInt aNum)
sl@0
    91
	{
sl@0
    92
	TBuf<4> b;
sl@0
    93
	b.Num(aNum);
sl@0
    94
	return Exists(b);
sl@0
    95
	}
sl@0
    96
sl@0
    97
void BusyWait(TInt aMicroseconds)
sl@0
    98
	{
sl@0
    99
	TTime begin;
sl@0
   100
	begin.HomeTime();
sl@0
   101
	FOREVER
sl@0
   102
		{
sl@0
   103
		TTime now;
sl@0
   104
		now.HomeTime();
sl@0
   105
		TTimeIntervalMicroSeconds iv=now.MicroSecondsFrom(begin);
sl@0
   106
		if (iv.Int64()>=TInt64(aMicroseconds))
sl@0
   107
			return;
sl@0
   108
		}
sl@0
   109
	}
sl@0
   110
sl@0
   111
void Kick(RThread& t)
sl@0
   112
	{
sl@0
   113
	TRequestStatus s;
sl@0
   114
	TRequestStatus* pS=&s;
sl@0
   115
	t.RequestComplete(pS,0);
sl@0
   116
	}
sl@0
   117
sl@0
   118
TUint GetNextId()
sl@0
   119
	{
sl@0
   120
	if (GetIx<PutIx)
sl@0
   121
		return ThreadId[GetIx++];
sl@0
   122
	return 0;
sl@0
   123
	}
sl@0
   124
sl@0
   125
TInt NumIdsPending()
sl@0
   126
	{
sl@0
   127
	return PutIx-GetIx;
sl@0
   128
	}
sl@0
   129
sl@0
   130
/*****************************************************************************
sl@0
   131
 * General tests
sl@0
   132
 *****************************************************************************/
sl@0
   133
TInt Test0Thread(TAny* aPtr)
sl@0
   134
	{
sl@0
   135
	TInt& count=*(TInt*)aPtr;
sl@0
   136
	++count;
sl@0
   137
	Main.SetPriority(EPriorityMuchMore);
sl@0
   138
	++count;
sl@0
   139
	Main.SetPriority(EPriorityMuchMore);
sl@0
   140
	++count;
sl@0
   141
	RThread().SetPriority(EPriorityNormal);
sl@0
   142
	++count;
sl@0
   143
	return 0;
sl@0
   144
	}
sl@0
   145
sl@0
   146
void Test0()
sl@0
   147
	{
sl@0
   148
	User::After(100000);	// Test fails intermittently on hardware unless we pause here 
sl@0
   149
	
sl@0
   150
	test.Start(_L("Test thread priorities work"));
sl@0
   151
	test.Next(_L("Create thread"));
sl@0
   152
	RThread t;
sl@0
   153
	TInt count=0;
sl@0
   154
	TRequestStatus s;
sl@0
   155
	TInt r=t.Create(_L("Test0"),Test0Thread,0x1000,NULL,&count);
sl@0
   156
	test(r==KErrNone);
sl@0
   157
	t.Logon(s);
sl@0
   158
	test(r==KErrNone);
sl@0
   159
	User::After(10000);		// make sure we have a full timeslice
sl@0
   160
	t.Resume();
sl@0
   161
sl@0
   162
	test(count==0);			// t shouldn't have run yet
sl@0
   163
	RThread().SetPriority(EPriorityMuchMore);	// shouldn't reschedule (priority unchanged)
sl@0
   164
	test(count==0);
sl@0
   165
	RThread().SetPriority(EPriorityMore);	// shouldn't reschedule (priority decreasing, but not enough)
sl@0
   166
	test(count==0);
sl@0
   167
	RThread().SetPriority(EPriorityMuchMore);	// shouldn't reschedule (priority increasing)
sl@0
   168
	test(count==0);
sl@0
   169
	RThread().SetPriority(EPriorityNormal);	// should reschedule (we go behind t)
sl@0
   170
	test(count==1);
sl@0
   171
	RThread().SetPriority(EPriorityLess);	// should reschedule (priority decreasing to below t)
sl@0
   172
	test(count==2);
sl@0
   173
	t.SetPriority(EPriorityMuchMore);		// shouldn't reschedule (round-robin, timeslice not expired)
sl@0
   174
	test(count==2);
sl@0
   175
	t.SetPriority(EPriorityNormal);			// shouldn't reschedule (t's priority decreasing)
sl@0
   176
	test(count==2);
sl@0
   177
	t.SetPriority(EPriorityNormal);			// shouldn't reschedule (t's priority unchanged)
sl@0
   178
	test(count==2);
sl@0
   179
	BusyWait(100000);		// use up our timeslice
sl@0
   180
	t.SetPriority(EPriorityMuchMore);		// should reschedule (round-robin, timeslice expired)
sl@0
   181
	test(count==3);
sl@0
   182
	test(s==KRequestPending);
sl@0
   183
	test(t.ExitType()==EExitPending);
sl@0
   184
	t.SetPriority(EPriorityRealTime);		// should reschedule (t increases above current)
sl@0
   185
	test(count==4);
sl@0
   186
	test(s==KErrNone);						// t should have exited
sl@0
   187
	test(t.ExitType()==EExitKill);
sl@0
   188
	User::WaitForRequest(s);
sl@0
   189
	RThread().SetPriority(EPriorityMuchMore);
sl@0
   190
	t.Close();
sl@0
   191
	test.End();
sl@0
   192
	}
sl@0
   193
sl@0
   194
TInt Test1Thread(TAny*)
sl@0
   195
	{
sl@0
   196
	M1.Signal();
sl@0
   197
	return 0;
sl@0
   198
	}
sl@0
   199
sl@0
   200
void Test1()
sl@0
   201
	{
sl@0
   202
	test.Start(_L("Test signalling from wrong thread"));
sl@0
   203
	TInt r=M1.CreateLocal();
sl@0
   204
	test(r==KErrNone);
sl@0
   205
	M1.Wait();
sl@0
   206
	RThread t;
sl@0
   207
	r=t.Create(_L("Test1"),Test1Thread,0x1000,NULL,NULL);
sl@0
   208
	test(r==KErrNone);
sl@0
   209
	TRequestStatus s;
sl@0
   210
	t.Logon(s);
sl@0
   211
	t.Resume();
sl@0
   212
	TBool jit = User::JustInTime();
sl@0
   213
	User::SetJustInTime(EFalse);
sl@0
   214
	User::WaitForRequest(s);
sl@0
   215
	User::SetJustInTime(jit);
sl@0
   216
	test(s==EAccessDenied);
sl@0
   217
	test(t.ExitType()==EExitPanic);
sl@0
   218
	test(t.ExitReason()==EAccessDenied);
sl@0
   219
	test(t.ExitCategory()==_L("KERN-EXEC"));
sl@0
   220
	t.Close();
sl@0
   221
	M1.Close();
sl@0
   222
	test.End();
sl@0
   223
	}
sl@0
   224
sl@0
   225
/*****************************************************************************
sl@0
   226
 * Mutex priority inheritance
sl@0
   227
 *****************************************************************************/
sl@0
   228
sl@0
   229
const TInt KTestDelay = 1000000;
sl@0
   230
sl@0
   231
TInt LowThread(TAny* aPtr)
sl@0
   232
	{
sl@0
   233
	TInt& count=*(TInt*)aPtr;
sl@0
   234
	FOREVER
sl@0
   235
		{
sl@0
   236
		M1.Wait();
sl@0
   237
		++count;
sl@0
   238
		BusyWait(KTestDelay);
sl@0
   239
		M1.Signal();
sl@0
   240
		User::WaitForAnyRequest();
sl@0
   241
		}
sl@0
   242
	}
sl@0
   243
sl@0
   244
TInt MedThread(TAny* aPtr)
sl@0
   245
	{
sl@0
   246
	TInt& count=*(TInt*)aPtr;
sl@0
   247
	FOREVER
sl@0
   248
		{
sl@0
   249
		++count;
sl@0
   250
		User::WaitForAnyRequest();
sl@0
   251
		}
sl@0
   252
	}
sl@0
   253
sl@0
   254
TInt HighThread(TAny* aPtr)
sl@0
   255
	{
sl@0
   256
	TInt& count=*(TInt*)aPtr;
sl@0
   257
	FOREVER
sl@0
   258
		{
sl@0
   259
		M2.Wait();
sl@0
   260
		++count;
sl@0
   261
		M1.Wait();
sl@0
   262
		++count;
sl@0
   263
		BusyWait(KTestDelay);
sl@0
   264
		M1.Signal();
sl@0
   265
		M2.Signal();
sl@0
   266
		User::WaitForAnyRequest();
sl@0
   267
		}
sl@0
   268
	}
sl@0
   269
sl@0
   270
void TestMutex1()
sl@0
   271
	{
sl@0
   272
	test.Start(_L("Test mutex priority inheritance"));
sl@0
   273
sl@0
   274
	test.Next(_L("Create mutex"));
sl@0
   275
	TInt r=M1.CreateLocal();
sl@0
   276
	test(r==KErrNone);
sl@0
   277
sl@0
   278
	test.Next(_L("Create low priority thread"));
sl@0
   279
	TInt lowcount=0;
sl@0
   280
	RThread low;
sl@0
   281
	r=low.Create(_L("low"),LowThread,0x1000,NULL,&lowcount);
sl@0
   282
	test(r==KErrNone);
sl@0
   283
	low.SetPriority(EPriorityMuchLess);
sl@0
   284
	test(Exists(_L("low")));
sl@0
   285
sl@0
   286
	test.Next(_L("Create medium priority thread"));
sl@0
   287
	TInt medcount=0;
sl@0
   288
	RThread med;
sl@0
   289
	r=med.Create(_L("med"),MedThread,0x1000,NULL,&medcount);
sl@0
   290
	test(r==KErrNone);
sl@0
   291
	med.SetPriority(EPriorityNormal);
sl@0
   292
	test(Exists(_L("med")));
sl@0
   293
sl@0
   294
	test.Next(_L("Start low priority thread"));
sl@0
   295
	low.Resume();
sl@0
   296
	User::AfterHighRes(KTestDelay/10);
sl@0
   297
	test(lowcount==1);
sl@0
   298
//	MCOUNT(M1,0);
sl@0
   299
sl@0
   300
	test.Next(_L("Start medium priority thread"));
sl@0
   301
	med.Resume();
sl@0
   302
	User::AfterHighRes(KTestDelay/10);
sl@0
   303
	test(medcount==1);
sl@0
   304
	Kick(med);
sl@0
   305
	User::AfterHighRes(KTestDelay/10);
sl@0
   306
	test(medcount==2);
sl@0
   307
	Kick(med);
sl@0
   308
sl@0
   309
	M1.Wait();
sl@0
   310
	test(lowcount==1);
sl@0
   311
	test(medcount==2);
sl@0
   312
	test.Next(_L("Wait, check medium runs"));
sl@0
   313
	User::AfterHighRes(KTestDelay/10);
sl@0
   314
	test(medcount==3);
sl@0
   315
	M1.Signal();
sl@0
   316
sl@0
   317
	test.Next(_L("Create mutex 2"));
sl@0
   318
	r=M2.CreateLocal();
sl@0
   319
	test(r==KErrNone);
sl@0
   320
sl@0
   321
	test.Next(_L("Create high priority thread"));
sl@0
   322
	TInt highcount=0;
sl@0
   323
	RThread high;
sl@0
   324
	r=high.Create(_L("high"),HighThread,0x1000,NULL,&highcount);
sl@0
   325
	test(r==KErrNone);
sl@0
   326
	high.SetPriority(EPriorityMore);
sl@0
   327
	test(Exists(_L("high")));
sl@0
   328
sl@0
   329
	Kick(low);
sl@0
   330
	User::AfterHighRes(KTestDelay/10);
sl@0
   331
//	MCOUNT(M1,0);
sl@0
   332
	Kick(med);
sl@0
   333
sl@0
   334
//	MCOUNT(M2,1);
sl@0
   335
	high.Resume();
sl@0
   336
	User::AfterHighRes(KTestDelay/10);
sl@0
   337
//	MCOUNT(M2,0);
sl@0
   338
//	MCOUNT(M1,-1);
sl@0
   339
	test(highcount==1);
sl@0
   340
sl@0
   341
	M2.Wait();
sl@0
   342
	test(lowcount==2);
sl@0
   343
	test(medcount==3);
sl@0
   344
	test(highcount==2);
sl@0
   345
	test.Next(_L("Wait, check medium runs"));
sl@0
   346
	User::AfterHighRes(KTestDelay/10);
sl@0
   347
	test(medcount==4);
sl@0
   348
	M2.Signal();
sl@0
   349
sl@0
   350
	test.Next(_L("Kill threads"));
sl@0
   351
	low.Kill(0);
sl@0
   352
	med.Kill(0);
sl@0
   353
	high.Kill(0);
sl@0
   354
	low.Close();
sl@0
   355
	med.Close();
sl@0
   356
	high.Close();
sl@0
   357
	test(!Exists(_L("low")));
sl@0
   358
	test(!Exists(_L("med")));
sl@0
   359
	test(!Exists(_L("high")));
sl@0
   360
sl@0
   361
	M1.Close();
sl@0
   362
	test.End();
sl@0
   363
	}
sl@0
   364
sl@0
   365
/*****************************************************************************
sl@0
   366
 * Utilities for mutex exhaustive state transition test
sl@0
   367
 *****************************************************************************/
sl@0
   368
void MutexWait()
sl@0
   369
	{
sl@0
   370
	M1.Wait();
sl@0
   371
	++Count;
sl@0
   372
	ThreadId[PutIx++]=(TUint)RThread().Id();
sl@0
   373
	}
sl@0
   374
sl@0
   375
void MutexSignal()
sl@0
   376
	{
sl@0
   377
	M1.Signal();
sl@0
   378
	}
sl@0
   379
sl@0
   380
typedef void (*PFV)(void);
sl@0
   381
TInt ThreadFunction(TAny* aPtr)
sl@0
   382
	{
sl@0
   383
	PFV& f=*(PFV*)aPtr;
sl@0
   384
	FOREVER
sl@0
   385
		{
sl@0
   386
		MutexWait();
sl@0
   387
		if (f)
sl@0
   388
			f();
sl@0
   389
		MutexSignal();
sl@0
   390
		User::WaitForAnyRequest();
sl@0
   391
		}
sl@0
   392
	}
sl@0
   393
sl@0
   394
void Exit()
sl@0
   395
	{
sl@0
   396
	User::Exit(0);
sl@0
   397
	}
sl@0
   398
sl@0
   399
TUint CreateThread(RThread& t, TInt n, TAny* aPtr)
sl@0
   400
	{
sl@0
   401
	TBuf<4> b;
sl@0
   402
	b.Num(n);
sl@0
   403
	TInt r=t.Create(b,ThreadFunction,0x1000,NULL,aPtr);
sl@0
   404
	test(r==KErrNone);
sl@0
   405
	t.Resume();
sl@0
   406
	TUint id=t.Id();
sl@0
   407
	test.Printf(_L("id=%d\n"),id);
sl@0
   408
	return id;
sl@0
   409
	}
sl@0
   410
sl@0
   411
/*
sl@0
   412
Possible thread relationships with mutex:
sl@0
   413
	Holding
sl@0
   414
	Waiting
sl@0
   415
	Waiting + suspended
sl@0
   416
	Hold Pending
sl@0
   417
sl@0
   418
Need to verify correct behaviour when the following actions occur for each of these states:
sl@0
   419
	Suspend thread
sl@0
   420
	Resume thread
sl@0
   421
	Change thread priority
sl@0
   422
	Thread exits
sl@0
   423
	Thread is killed
sl@0
   424
	Mutex deleted
sl@0
   425
*/
sl@0
   426
sl@0
   427
PFV HoldExtra;
sl@0
   428
void KickMain()
sl@0
   429
	{
sl@0
   430
	RThread me;
sl@0
   431
	Kick(Main);
sl@0
   432
	User::WaitForAnyRequest();
sl@0
   433
	me.SetPriority(EPriorityMuchMore);
sl@0
   434
	MutexSignal();						// this should wake up t8
sl@0
   435
	MutexWait();
sl@0
   436
	MutexSignal();						// this should wake up t9
sl@0
   437
	MutexWait();
sl@0
   438
	Kick(Main);
sl@0
   439
	User::WaitForAnyRequest();
sl@0
   440
	if (HoldExtra)
sl@0
   441
		HoldExtra();
sl@0
   442
	}
sl@0
   443
sl@0
   444
void RackEmUp(RThread* t, PFV* f, TUint* id)
sl@0
   445
	{
sl@0
   446
	// set up t4 holding
sl@0
   447
	// t1, t2, t5, t10 waiting
sl@0
   448
	// t3, t6, t7 waiting+suspended
sl@0
   449
	// t8, t9 pending
sl@0
   450
	MCOUNT(M1,1);			// check mutex free
sl@0
   451
	Kick(t[4]);
sl@0
   452
	f[4]=&KickMain;
sl@0
   453
	User::WaitForAnyRequest();
sl@0
   454
	MCOUNT(M1,0);			// check mutex now held
sl@0
   455
	TInt i;
sl@0
   456
	for (i=1; i<=10; ++i)
sl@0
   457
		if (i!=4)
sl@0
   458
			Kick(t[i]);		// wake up threads
sl@0
   459
	User::After(50000);		// let threads wait
sl@0
   460
	MCOUNT(M1,-9);			// check 9 threads waiting
sl@0
   461
	Kick(t[4]);
sl@0
   462
	User::WaitForAnyRequest();
sl@0
   463
	MCOUNT(M1,-7);			// check 7 threads waiting
sl@0
   464
	NUMCHECK(3);
sl@0
   465
	IDCHECK(id4);			// from the initial wait
sl@0
   466
	IDCHECK(id4);			// now have t8, t9 pending, t4 holding, rest waiting
sl@0
   467
	IDCHECK(id4);			// now have t8, t9 pending, t4 holding, rest waiting
sl@0
   468
	t[4].SetPriority(EPriorityNormal);
sl@0
   469
	t[7].Resume();			// test resume when not suspended
sl@0
   470
	MCOUNT(M1,-7);			// check 7 threads waiting
sl@0
   471
	t[3].Suspend();
sl@0
   472
	t[6].Suspend();
sl@0
   473
	t[7].Suspend();			// now have required state
sl@0
   474
	t[3].Suspend();			// suspend and resume t3 again for good measure
sl@0
   475
	t[3].Resume();
sl@0
   476
	MCOUNT(M1,-7);			// check 7 threads waiting
sl@0
   477
	HoldExtra=NULL;
sl@0
   478
	}
sl@0
   479
sl@0
   480
void SimpleCheck(TInt n, const TUint* id, ...)
sl@0
   481
	{
sl@0
   482
	VA_LIST list;
sl@0
   483
	VA_START(list,id);
sl@0
   484
	User::After(50000);		// let stuff happen
sl@0
   485
	NUMCHECK(n);
sl@0
   486
	TInt i;
sl@0
   487
	for (i=0; i<n; ++i)
sl@0
   488
		{
sl@0
   489
		TInt tn=VA_ARG(list,TInt);
sl@0
   490
		IDCHECK(id[tn]);
sl@0
   491
		}
sl@0
   492
	}
sl@0
   493
sl@0
   494
void Resurrect(TInt n, TThreadPriority aPriority, RThread* t, PFV* f, TUint* id)
sl@0
   495
	{
sl@0
   496
	f[n]=NULL;
sl@0
   497
	id[n]=CreateThread(t[n],n,f+n);
sl@0
   498
	t[n].SetPriority(EPriorityRealTime);
sl@0
   499
	t[n].SetPriority(aPriority);
sl@0
   500
	NUMCHECK(1);
sl@0
   501
	IDCHECK(id[n]);
sl@0
   502
	}
sl@0
   503
sl@0
   504
/*****************************************************************************
sl@0
   505
 * Mutex exhaustive state transition test
sl@0
   506
 *****************************************************************************/
sl@0
   507
void TestMutex2()
sl@0
   508
	{
sl@0
   509
	test.Start(_L("Test mutex state transitions"));
sl@0
   510
	RThread t[11];
sl@0
   511
	TUint id[11];
sl@0
   512
	PFV f[11]={NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
sl@0
   513
	id[0]=(TUint)RThread().Id();
sl@0
   514
	PutIx=0;
sl@0
   515
	GetIx=0;
sl@0
   516
	Count=0;
sl@0
   517
	test.Next(_L("Create mutex"));
sl@0
   518
	TInt r=M1.CreateLocal();
sl@0
   519
	test(r==KErrNone);
sl@0
   520
	MCOUNT(M1,1);
sl@0
   521
	MutexWait();
sl@0
   522
	MCOUNT(M1,0);
sl@0
   523
	IDCHECK(id[0]);
sl@0
   524
	test.Next(_L("Create threads"));
sl@0
   525
	TInt i;
sl@0
   526
	for (i=1; i<=5; ++i)
sl@0
   527
		id[i]=CreateThread(t[i],i,f+i);
sl@0
   528
	User::After(50000);		// let threads wait on mutex
sl@0
   529
	MCOUNT(M1,-5);			// check 5 threads waiting
sl@0
   530
	for (i=-4; i<=0; ++i)
sl@0
   531
		{
sl@0
   532
		MutexSignal(); // wake up next thread
sl@0
   533
		MutexWait();
sl@0
   534
		MCOUNT(M1,i);		// check right number of threads waiting
sl@0
   535
		IDCHECK(id0);		// check we got mutex back straight away
sl@0
   536
		}
sl@0
   537
	MutexSignal();
sl@0
   538
	User::After(50000);		// let threads claim mutex
sl@0
   539
	MutexWait();
sl@0
   540
	MCOUNT(M1,0);			// check no threads waiting
sl@0
   541
	for (i=1; i<=5; ++i)
sl@0
   542
		{
sl@0
   543
		IDCHECK(id[i]);		// check they ran in order t1...t5
sl@0
   544
		Kick(t[i]);			// wake up thread
sl@0
   545
		}
sl@0
   546
	IDCHECK(id0);			// check we got it back last
sl@0
   547
	t[4].SetPriority(EPriorityMore);	// make t4 higher priority
sl@0
   548
	User::After(50000);		// let threads wait on mutex
sl@0
   549
	MCOUNT(M1,-5);			// check 5 threads waiting
sl@0
   550
//	temp = M1.Count();
sl@0
   551
	MutexSignal();
sl@0
   552
//	temp = M1.Count();
sl@0
   553
	User::After(50000);		// let threads claim mutex
sl@0
   554
	MutexWait();
sl@0
   555
//	temp = M1.Count();
sl@0
   556
	MCOUNT(M1,0);			// check no threads waiting
sl@0
   557
	IDCHECK(id4);			// check they ran in order t4,t1,t2,t3,t5
sl@0
   558
	IDCHECK(id1);
sl@0
   559
	IDCHECK(id2);
sl@0
   560
	IDCHECK(id3);
sl@0
   561
	IDCHECK(id5);
sl@0
   562
	IDCHECK(id0);
sl@0
   563
	t[4].SetPriority(EPriorityNormal);	// make t4 normal priority
sl@0
   564
	for (i=1; i<=5; ++i)
sl@0
   565
		Kick(t[i]);			// wake up thread
sl@0
   566
	User::After(50000);		// let threads wait on mutex
sl@0
   567
	MCOUNT(M1,-5);			// check 5 threads waiting
sl@0
   568
sl@0
   569
	t[3].SetPriority(EPriorityMore);	// make t3 higher priority
sl@0
   570
//	temp = M1.Count();
sl@0
   571
	MutexSignal();
sl@0
   572
//	temp = M1.Count();
sl@0
   573
	User::After(50000);		// let threads claim mutex
sl@0
   574
	MutexWait();
sl@0
   575
//	temp = M1.Count();
sl@0
   576
	MCOUNT(M1,0);			// check no threads waiting
sl@0
   577
	IDCHECK(id3);			// check they ran in order t3,t1,t2,t4,t5
sl@0
   578
	IDCHECK(id1);
sl@0
   579
	IDCHECK(id2);
sl@0
   580
	IDCHECK(id4);
sl@0
   581
	IDCHECK(id5);
sl@0
   582
	IDCHECK(id0);
sl@0
   583
	t[3].SetPriority(EPriorityNormal);	// make t4 normal priority
sl@0
   584
	for (i=1; i<=5; ++i)
sl@0
   585
		Kick(t[i]);			// wake up threads
sl@0
   586
	User::After(50000);		// let threads wait on mutex
sl@0
   587
	MCOUNT(M1,-5);			// check 5 threads waiting
sl@0
   588
sl@0
   589
	t[2].SetPriority(EPriorityMore);	// make t2 higher priority
sl@0
   590
	t[1].SetPriority(EPriorityLess);	// make t1 lower priority
sl@0
   591
	MutexSignal();
sl@0
   592
	User::After(50000);		// let threads claim mutex
sl@0
   593
	MutexWait();
sl@0
   594
	MCOUNT(M1,0);			// check no threads waiting
sl@0
   595
	IDCHECK(id2);			// check they ran in order t2,t3,t4,t5,t1
sl@0
   596
	IDCHECK(id3);
sl@0
   597
	IDCHECK(id4);
sl@0
   598
	IDCHECK(id5);
sl@0
   599
	IDCHECK(id1);
sl@0
   600
	IDCHECK(id0);
sl@0
   601
sl@0
   602
	for (i=1; i<=5; ++i)
sl@0
   603
		Kick(t[i]);			// wake up threads
sl@0
   604
	User::After(50000);		// let threads wait on mutex
sl@0
   605
	MCOUNT(M1,-5);			// check 5 threads waiting
sl@0
   606
	MutexSignal();
sl@0
   607
	User::After(50000);		// let threads claim mutex
sl@0
   608
	MutexWait();
sl@0
   609
	MCOUNT(M1,0);			// check no threads waiting
sl@0
   610
	IDCHECK(id2);			// check they ran in order t2,t3,t4,t5,t1
sl@0
   611
	IDCHECK(id3);
sl@0
   612
	IDCHECK(id4);
sl@0
   613
	IDCHECK(id5);
sl@0
   614
	IDCHECK(id1);
sl@0
   615
	IDCHECK(id0);
sl@0
   616
sl@0
   617
	test(Exists(2));
sl@0
   618
	for (i=1; i<=5; ++i)
sl@0
   619
		Kick(t[i]);			// wake up threads
sl@0
   620
	User::After(50000);		// let threads wait on mutex
sl@0
   621
	MCOUNT(M1,-5);			// check 5 threads waiting
sl@0
   622
	f[2]=&Exit;				// make t2 exit while holding the mutex
sl@0
   623
	MutexSignal();
sl@0
   624
	User::After(50000);		// let threads claim mutex
sl@0
   625
	MutexWait();
sl@0
   626
	MCOUNT(M1,0);			// check no threads waiting
sl@0
   627
	test(t[2].ExitType()==EExitKill);	// check t2 has exited
sl@0
   628
	t[2].Close();
sl@0
   629
	test(!Exists(2));
sl@0
   630
	IDCHECK(id2);			// check they ran in order t2,t3,t4,t5,t1
sl@0
   631
	IDCHECK(id3);
sl@0
   632
	IDCHECK(id4);
sl@0
   633
	IDCHECK(id5);
sl@0
   634
	IDCHECK(id1);
sl@0
   635
	IDCHECK(id0);
sl@0
   636
	f[2]=NULL;
sl@0
   637
	id[2]=CreateThread(t[2],2,f+2);	// recreate t2
sl@0
   638
	User::After(50000);		// let new t2 wait on mutex
sl@0
   639
	MCOUNT(M1,-1);			// check 1 thread waiting
sl@0
   640
	MutexSignal();
sl@0
   641
	User::After(50000);		// let t2 claim mutex
sl@0
   642
	MutexWait();
sl@0
   643
	MCOUNT(M1,0);			// check no threads waiting
sl@0
   644
	IDCHECK(id2);
sl@0
   645
	IDCHECK(id0);
sl@0
   646
sl@0
   647
	t[2].SetPriority(EPriorityLess);	// make t2 lower priority
sl@0
   648
	for (i=1; i<=5; ++i)
sl@0
   649
		Kick(t[i]);			// wake up threads
sl@0
   650
	User::After(50000);		// let threads wait on mutex
sl@0
   651
	MCOUNT(M1,-5);			// check 5 threads waiting
sl@0
   652
	MutexSignal();			// t3 now pending
sl@0
   653
	MCOUNT(M1,-3);			// check 4 threads waiting, mutex free
sl@0
   654
	t[3].Suspend();			// this should wake up t4
sl@0
   655
	MCOUNT(M1,-2);			// check 3 threads waiting, mutex free
sl@0
   656
	User::After(50000);		// let threads claim mutex
sl@0
   657
	MutexWait();
sl@0
   658
	MCOUNT(M1,0);			// check no threads still waiting
sl@0
   659
	IDCHECK(id4);			// check they ran in order t4,t5,t1,t2
sl@0
   660
	IDCHECK(id5);
sl@0
   661
	IDCHECK(id1);
sl@0
   662
	IDCHECK(id2);
sl@0
   663
	IDCHECK(id0);
sl@0
   664
	Kick(t[1]);				// wake up t1
sl@0
   665
	User::After(50000);		// let thread wait on mutex
sl@0
   666
	MCOUNT(M1,-1);			// check 1 thread waiting
sl@0
   667
	t[3].Resume();			// resume pending t3
sl@0
   668
	MutexSignal();
sl@0
   669
	User::After(50000);		// let t2 claim mutex
sl@0
   670
	MutexWait();
sl@0
   671
	MCOUNT(M1,0);			// check no threads waiting
sl@0
   672
	IDCHECK(id3);			// check order t3,t1
sl@0
   673
	IDCHECK(id1);
sl@0
   674
	IDCHECK(id0);
sl@0
   675
sl@0
   676
	for (i=1; i<=5; ++i)
sl@0
   677
		Kick(t[i]);			// wake up threads
sl@0
   678
	User::After(50000);		// let threads wait on mutex
sl@0
   679
	MCOUNT(M1,-5);			// check 5 threads waiting
sl@0
   680
	t[4].Suspend();			// suspend t4
sl@0
   681
	MCOUNT(M1,-5);			// check 5 threads waiting
sl@0
   682
	t[4].Suspend();			// suspend t4 again
sl@0
   683
	MCOUNT(M1,-5);			// check 5 threads waiting
sl@0
   684
	MutexSignal();
sl@0
   685
	User::After(50000);		// let threads claim mutex
sl@0
   686
	MutexWait();
sl@0
   687
	MCOUNT(M1,-1);			// check 1 thread still waiting
sl@0
   688
	IDCHECK(id3);			// check they ran in order t3,t5,t1,t2
sl@0
   689
	IDCHECK(id5);
sl@0
   690
	IDCHECK(id1);
sl@0
   691
	IDCHECK(id2);
sl@0
   692
	IDCHECK(id0);
sl@0
   693
	MutexSignal();
sl@0
   694
	t[4].Resume();
sl@0
   695
	User::After(50000);		// let threads claim mutex
sl@0
   696
	MutexWait();
sl@0
   697
	IDCHECK(id0);			// check thread didn't get mutex (still suspended)
sl@0
   698
	MutexSignal();
sl@0
   699
	t[4].Resume();
sl@0
   700
	User::After(50000);		// let threads claim mutex
sl@0
   701
	MutexWait();
sl@0
   702
	IDCHECK(id4);			// check order t4 then this
sl@0
   703
	IDCHECK(id0);
sl@0
   704
sl@0
   705
	for (i=1; i<=5; ++i)
sl@0
   706
		Kick(t[i]);			// wake up threads
sl@0
   707
	User::After(50000);		// let threads wait on mutex
sl@0
   708
	MCOUNT(M1,-5);			// check 5 threads waiting
sl@0
   709
	MutexWait();			// wait on mutex again
sl@0
   710
	IDCHECK(id0);
sl@0
   711
	MutexSignal();			// signal once
sl@0
   712
	MCOUNT(M1,-5);			// check 5 threads still waiting
sl@0
   713
	MutexSignal();			// signal again
sl@0
   714
	MCOUNT(M1,-3);			// check one thread has been woken up and mutex is now free
sl@0
   715
	User::After(50000);		// let threads claim mutex
sl@0
   716
	MutexWait();
sl@0
   717
	MCOUNT(M1,0);			// check no threads still waiting
sl@0
   718
	IDCHECK(id3);			// check they ran in order t3,t4,t5,t1,t2
sl@0
   719
	IDCHECK(id4);
sl@0
   720
	IDCHECK(id5);
sl@0
   721
	IDCHECK(id1);
sl@0
   722
	IDCHECK(id2);
sl@0
   723
	IDCHECK(id0);
sl@0
   724
sl@0
   725
	test.Next(_L("Create more threads"));
sl@0
   726
	for (i=6; i<=10; ++i)
sl@0
   727
		id[i]=CreateThread(t[i],i,f+i);
sl@0
   728
	User::After(50000);		// let threads wait on mutex
sl@0
   729
	MCOUNT(M1,-5);			// check 5 threads waiting
sl@0
   730
	MutexSignal();
sl@0
   731
	User::After(50000);		// let threads claim mutex
sl@0
   732
	MCOUNT(M1,1);			// check no threads still waiting and mutex free
sl@0
   733
	IDCHECK(id6);			// check they ran in order t6,t7,t8,t9,t10
sl@0
   734
	IDCHECK(id7);
sl@0
   735
	IDCHECK(id8);
sl@0
   736
	IDCHECK(id9);
sl@0
   737
	IDCHECK(id10);
sl@0
   738
	t[8].SetPriority(EPriorityMore);	// t1-t3=less, t4-t7=normal, t8-t10 more, t0 much more
sl@0
   739
	t[9].SetPriority(EPriorityMore);
sl@0
   740
	t[10].SetPriority(EPriorityMore);
sl@0
   741
	t[2].SetPriority(EPriorityLess);
sl@0
   742
	t[3].SetPriority(EPriorityLess);
sl@0
   743
sl@0
   744
	RackEmUp(t,f,id);
sl@0
   745
	SimpleCheck(0,NULL,NULL);	// holding thread still blocked
sl@0
   746
	Kick(t[4]);
sl@0
   747
	SimpleCheck(6,id,10,8,9,5,1,2);	// 3,6,7 suspended
sl@0
   748
	t[3].Resume();
sl@0
   749
	t[6].Resume();
sl@0
   750
	t[7].Resume();
sl@0
   751
	SimpleCheck(3,id,6,7,3);	// 3,6,7 resumed
sl@0
   752
sl@0
   753
	RackEmUp(t,f,id);
sl@0
   754
	SimpleCheck(0,NULL,NULL);	// holding thread still blocked
sl@0
   755
	Kick(t[4]);
sl@0
   756
	t[4].Suspend();
sl@0
   757
	SimpleCheck(0,NULL,NULL);	// holding thread suspended
sl@0
   758
	t[4].Resume();
sl@0
   759
	SimpleCheck(6,id,10,8,9,5,1,2);	// 3,6,7 suspended
sl@0
   760
	t[3].Resume();
sl@0
   761
	t[6].Resume();
sl@0
   762
	t[7].Resume();
sl@0
   763
	SimpleCheck(3,id,6,7,3);	// 3,6,7 resumed
sl@0
   764
sl@0
   765
	RackEmUp(t,f,id);
sl@0
   766
	Kick(t[4]);
sl@0
   767
	t[4].SetPriority(EPriorityRealTime);
sl@0
   768
	MCOUNT(M1,-5);			// should be 6 waiting, mutex free
sl@0
   769
	t[4].SetPriority(EPriorityNormal);
sl@0
   770
	t[8].SetPriority(EPriorityRealTime);	// change pending thread priority
sl@0
   771
	MCOUNT(M1,-4);			// should be 5 waiting, mutex free
sl@0
   772
	t[8].SetPriority(EPriorityMore);
sl@0
   773
	NUMCHECK(1);
sl@0
   774
	IDCHECK(id8);
sl@0
   775
	t[3].SetPriority(EPriorityRealTime);	// change suspended thread priority
sl@0
   776
	SimpleCheck(5,id,9,10,5,1,2);	// 3,6,7 suspended
sl@0
   777
	t[6].Resume();
sl@0
   778
	t[7].Resume();
sl@0
   779
	t[3].Resume();			// this should run right away
sl@0
   780
	NUMCHECK(1);
sl@0
   781
	IDCHECK(id3);
sl@0
   782
	SimpleCheck(2,id,6,7);	// 6,7 resumed
sl@0
   783
	t[3].SetPriority(EPriorityLess);
sl@0
   784
sl@0
   785
	RackEmUp(t,f,id);
sl@0
   786
	Kick(t[4]);
sl@0
   787
	t[1].SetPriority(EPriorityRealTime);	// change waiting thread priority
sl@0
   788
											// this should run right away
sl@0
   789
	NUMCHECK(1);
sl@0
   790
	IDCHECK(id1);
sl@0
   791
	t[1].SetPriority(EPriorityLess);
sl@0
   792
	// t8,t9,t10 should now be pending
sl@0
   793
	MCOUNT(M1,1-5);
sl@0
   794
	t[8].Suspend();			// this should wake up t5
sl@0
   795
	t[9].Suspend();			// this should wake up t2
sl@0
   796
	MCOUNT(M1,1-3);
sl@0
   797
	t[8].Suspend();			// this should have no further effect
sl@0
   798
	t[8].Resume();			// this should have no further effect
sl@0
   799
	MCOUNT(M1,1-3);
sl@0
   800
	SimpleCheck(3,id,10,5,2);
sl@0
   801
	MCOUNT(M1,1-3);
sl@0
   802
	t[3].Resume();
sl@0
   803
	t[6].Resume();
sl@0
   804
	t[7].Resume();
sl@0
   805
	t[8].Resume();
sl@0
   806
	t[9].Resume();
sl@0
   807
	SimpleCheck(5,id,8,9,6,7,3);
sl@0
   808
sl@0
   809
	RackEmUp(t,f,id);
sl@0
   810
	MCOUNT(M1,-7);
sl@0
   811
	t[8].Suspend();			// this shouldn't wake anything up
sl@0
   812
	t[9].Suspend();			// this shouldn't wake anything up
sl@0
   813
	MCOUNT(M1,-7);
sl@0
   814
	Kick(t[4]);
sl@0
   815
	t[4].SetPriority(EPriorityRealTime);
sl@0
   816
	MCOUNT(M1,1-6);				// should be 6 waiting, mutex free, t10 pending
sl@0
   817
	t[4].SetPriority(EPriorityNormal);
sl@0
   818
	t[10].SetPriority(EPriorityLess);	// this should wake up t5
sl@0
   819
	MCOUNT(M1,1-5);				// should be 5 waiting, mutex free, t10, t5 pending
sl@0
   820
	SimpleCheck(4,id,5,10,1,2);
sl@0
   821
	t[3].SetPriority(EPriorityRealTime);	// boost suspended+waiting thread
sl@0
   822
	MCOUNT(M1,1-3);			// should be 3 waiting+suspended, mutex free, t8, t9 pending+suspended
sl@0
   823
	t[6].Resume();
sl@0
   824
	t[7].Resume();
sl@0
   825
	t[8].Resume();
sl@0
   826
	t[9].Resume();
sl@0
   827
	t[3].Resume();			// this should run immediately
sl@0
   828
	MCOUNT(M1,1);			// t8,t9,t6,t7 pending, mutex free
sl@0
   829
	NUMCHECK(1);
sl@0
   830
	IDCHECK(id3);			// t3 should have run
sl@0
   831
	t[3].SetPriority(EPriorityLess);
sl@0
   832
	t[9].SetPriority(EPriorityMuchLess);	// lower pending thread priority
sl@0
   833
	SimpleCheck(4,id,8,6,7,9);
sl@0
   834
	t[9].SetPriority(EPriorityMore);
sl@0
   835
	t[10].SetPriority(EPriorityMore);
sl@0
   836
sl@0
   837
	RackEmUp(t,f,id);
sl@0
   838
	MCOUNT(M1,-7);
sl@0
   839
	t[8].Suspend();			// this shouldn't wake anything up
sl@0
   840
	t[9].Suspend();			// this shouldn't wake anything up
sl@0
   841
	MCOUNT(M1,-7);
sl@0
   842
	Kick(t[4]);
sl@0
   843
	MCOUNT(M1,-7);
sl@0
   844
	t[4].SetPriority(EPriorityRealTime);
sl@0
   845
	MCOUNT(M1,1-6);			// should be 6 waiting, mutex free, t10 pending, t8,t9 pending+suspended
sl@0
   846
	t[4].SetPriority(EPriorityNormal);
sl@0
   847
	t[10].SetPriority(EPriorityMuchLess);	// lower pending thread priority
sl@0
   848
	MCOUNT(M1,1-5);			// should now be 5 waiting, mutex free, t10,t5 pending, t8,t9 pending+suspended
sl@0
   849
	t[6].Resume();
sl@0
   850
	t[7].Resume();
sl@0
   851
	t[3].Resume();			// this gets made READY straight away
sl@0
   852
	SimpleCheck(7,id,5,6,7,3,1,2,10);
sl@0
   853
	t[8].Resume();
sl@0
   854
	t[9].Resume();
sl@0
   855
	SimpleCheck(2,id,8,9);
sl@0
   856
	t[10].SetPriority(EPriorityMore);
sl@0
   857
sl@0
   858
	RackEmUp(t,f,id);
sl@0
   859
	MCOUNT(M1,-7);
sl@0
   860
	Kick(t[4]);
sl@0
   861
	t[9].Kill(0);			// kill pending thread
sl@0
   862
	t[9].Close();
sl@0
   863
	test(!Exists(9));
sl@0
   864
	t[1].Kill(0);			// kill waiting thread
sl@0
   865
	t[1].Close();
sl@0
   866
	test(!Exists(1));
sl@0
   867
	t[6].Kill(0);			// kill suspended+waiting thread
sl@0
   868
	t[6].Close();
sl@0
   869
	t[7].Resume();
sl@0
   870
	t[3].Resume();
sl@0
   871
	test(!Exists(6));
sl@0
   872
	SimpleCheck(6,id,10,8,5,7,2,3);	// 8 runs first and gets blocked behind 10
sl@0
   873
	Resurrect(9,EPriorityMore,t,f,id);
sl@0
   874
	Resurrect(1,EPriorityLess,t,f,id);
sl@0
   875
	Resurrect(6,EPriorityNormal,t,f,id);
sl@0
   876
sl@0
   877
	RackEmUp(t,f,id);
sl@0
   878
	MCOUNT(M1,-7);
sl@0
   879
	t[8].Suspend();			// this shouldn't wake anything up
sl@0
   880
	t[9].Suspend();			// this shouldn't wake anything up
sl@0
   881
	MCOUNT(M1,-7);
sl@0
   882
	Kick(t[4]);
sl@0
   883
	MCOUNT(M1,-7);
sl@0
   884
	t[4].SetPriority(EPriorityRealTime);
sl@0
   885
	MCOUNT(M1,1-6);			// should be 6 waiting, mutex free, t10 pending, t8,t9 pending+suspended
sl@0
   886
	t[4].SetPriority(EPriorityNormal);
sl@0
   887
	t[10].Kill(0);			// kill pending thread - this should wake up t5
sl@0
   888
	t[10].Close();
sl@0
   889
	test(!Exists(10));
sl@0
   890
	MCOUNT(M1,1-5);			// should be 5 waiting, mutex free, t5 pending, t8,t9 pending+suspended
sl@0
   891
	t[5].SetPriority(EPriorityRealTime);	// this should make t5 run
sl@0
   892
	MCOUNT(M1,1-4);			// should be 4 waiting, mutex free, t1 pending, t8,t9 pending+suspended
sl@0
   893
	t[5].SetPriority(EPriorityNormal);
sl@0
   894
	NUMCHECK(1);
sl@0
   895
	IDCHECK(id5);
sl@0
   896
	t[8].SetPriority(EPriorityRealTime);	// this shouldn't make anything happen
sl@0
   897
	MCOUNT(M1,1-4);			// mutex free, t1 pending, t8,t9 pending+suspended, t3,t6,t7 wait+susp, t2 waiting
sl@0
   898
	NUMCHECK(0);
sl@0
   899
	t[8].Resume();
sl@0
   900
	MCOUNT(M1,1-3);			// mutex free, t1,t2 pending, t9 pending+suspended, t3,t6,t7 wait+susp
sl@0
   901
	NUMCHECK(1);
sl@0
   902
	IDCHECK(id8);
sl@0
   903
	t[8].SetPriority(EPriorityMore);
sl@0
   904
	t[3].Resume();
sl@0
   905
	t[6].Resume();
sl@0
   906
	t[7].Resume();
sl@0
   907
	t[9].Resume();
sl@0
   908
	SimpleCheck(6,id,9,6,7,1,2,3);
sl@0
   909
	Resurrect(10,EPriorityMore,t,f,id);
sl@0
   910
sl@0
   911
	RackEmUp(t,f,id);
sl@0
   912
	MCOUNT(M1,-7);
sl@0
   913
	t[8].Suspend();			// this shouldn't wake anything up
sl@0
   914
	t[9].Suspend();			// this shouldn't wake anything up
sl@0
   915
	MCOUNT(M1,-7);
sl@0
   916
	Kick(t[4]);
sl@0
   917
	MCOUNT(M1,-7);
sl@0
   918
	t[4].SetPriority(EPriorityRealTime);
sl@0
   919
	MCOUNT(M1,1-6);			// mutex free, t10 pending, t8,t9 pending+susp, t3,t6,t7 wait+susp, t1,t2,t5 wait
sl@0
   920
	t[4].SetPriority(EPriorityNormal);
sl@0
   921
	t[1].SetPriority(EPriorityRealTime);	// this should be able to run and claim the mutex
sl@0
   922
	NUMCHECK(1);
sl@0
   923
	IDCHECK(id1);
sl@0
   924
	MCOUNT(M1,1-4);			// mutex free, t10,t5 pending, t8,t9 pending+susp, t3,t6,t7 wait+susp, t2 wait
sl@0
   925
	t[1].SetPriority(EPriorityLess);
sl@0
   926
	t[3].Resume();
sl@0
   927
	t[6].Resume();
sl@0
   928
	t[7].Resume();
sl@0
   929
	t[9].Resume();
sl@0
   930
	t[8].Resume();
sl@0
   931
	SimpleCheck(8,id,10,9,8,5,6,7,3,2);
sl@0
   932
sl@0
   933
	RackEmUp(t,f,id);
sl@0
   934
	MCOUNT(M1,-7);
sl@0
   935
	Kick(t[4]);
sl@0
   936
	M1.Close();				// close the mutex - non-suspended threads should all panic with KERN-EXEC 0
sl@0
   937
	TBool jit = User::JustInTime();
sl@0
   938
	User::SetJustInTime(EFalse);
sl@0
   939
	User::After(1000000);
sl@0
   940
	User::SetJustInTime(jit);
sl@0
   941
	for (i=1; i<=10; ++i)
sl@0
   942
		{
sl@0
   943
		if (i==3 || i==6 || i==7)
sl@0
   944
			{
sl@0
   945
			test(t[i].ExitType()==EExitPending);
sl@0
   946
			}
sl@0
   947
		else
sl@0
   948
			{
sl@0
   949
			test(t[i].ExitType()==EExitPanic);
sl@0
   950
			test(t[i].ExitReason()==EBadHandle);
sl@0
   951
			test(t[i].ExitCategory()==_L("KERN-EXEC"));
sl@0
   952
			t[i].Close();
sl@0
   953
			test(!Exists(i));
sl@0
   954
			}
sl@0
   955
		}
sl@0
   956
	t[3].Resume();
sl@0
   957
	t[6].Resume();
sl@0
   958
	t[7].Resume();
sl@0
   959
	User::SetJustInTime(EFalse);
sl@0
   960
	User::After(1000000);
sl@0
   961
	User::SetJustInTime(jit);
sl@0
   962
	for (i=1; i<=10; ++i)
sl@0
   963
		{
sl@0
   964
		if (i==3 || i==6 || i==7)
sl@0
   965
			{
sl@0
   966
			test(t[i].ExitType()==EExitPanic);
sl@0
   967
			test(t[i].ExitReason()==EBadHandle);
sl@0
   968
			test(t[i].ExitCategory()==_L("KERN-EXEC"));
sl@0
   969
			t[i].Close();
sl@0
   970
			test(!Exists(i));
sl@0
   971
			}
sl@0
   972
		}
sl@0
   973
sl@0
   974
	test.End();
sl@0
   975
	}
sl@0
   976
sl@0
   977
/*****************************************************************************
sl@0
   978
 * Mutex benchmarks
sl@0
   979
 *****************************************************************************/
sl@0
   980
TInt MutexSpeed(TAny* aPtr)
sl@0
   981
	{
sl@0
   982
	TInt& count=*(TInt*)aPtr;
sl@0
   983
	RThread().SetPriority(EPriorityMore);
sl@0
   984
	FOREVER
sl@0
   985
		{
sl@0
   986
		M1.Wait();
sl@0
   987
		M1.Signal();
sl@0
   988
		++count;
sl@0
   989
		}
sl@0
   990
	}
sl@0
   991
sl@0
   992
TInt MutexSpeed2(TAny* aPtr)
sl@0
   993
	{
sl@0
   994
	TInt& count=*(TInt*)aPtr;
sl@0
   995
	RThread().SetPriority(EPriorityMore);
sl@0
   996
	FOREVER
sl@0
   997
		{
sl@0
   998
		M1.Wait();
sl@0
   999
		M1.Wait();
sl@0
  1000
		M1.Signal();
sl@0
  1001
		M1.Signal();
sl@0
  1002
		++count;
sl@0
  1003
		}
sl@0
  1004
	}
sl@0
  1005
sl@0
  1006
void TestMutexSpeed()
sl@0
  1007
	{
sl@0
  1008
	test.Start(_L("Test mutex speed"));
sl@0
  1009
	TInt count=0;
sl@0
  1010
	TInt r=M1.CreateLocal();
sl@0
  1011
	test(r==KErrNone);
sl@0
  1012
sl@0
  1013
	RThread t;
sl@0
  1014
	r=t.Create(_L("Speed"),MutexSpeed,0x1000,NULL,&count);
sl@0
  1015
	test(r==KErrNone);
sl@0
  1016
	t.SetPriority(EPriorityRealTime);
sl@0
  1017
	t.Resume();
sl@0
  1018
	User::AfterHighRes(1000000);
sl@0
  1019
	t.Kill(0);
sl@0
  1020
	t.Close();
sl@0
  1021
	test(!Exists(_L("Speed")));
sl@0
  1022
	test.Printf(_L("%d wait/signal in 1 second\n"),count);
sl@0
  1023
sl@0
  1024
	TInt count2=0;
sl@0
  1025
	r=t.Create(_L("Speed2"),MutexSpeed2,0x1000,NULL,&count2);
sl@0
  1026
	test(r==KErrNone);
sl@0
  1027
	t.SetPriority(EPriorityRealTime);
sl@0
  1028
	t.Resume();
sl@0
  1029
	User::AfterHighRes(1000000);
sl@0
  1030
	t.Kill(0);
sl@0
  1031
	t.Close();
sl@0
  1032
	test(!Exists(_L("Speed2")));
sl@0
  1033
	test.Printf(_L("%d double wait/signal in 1 second\n"),count2);
sl@0
  1034
sl@0
  1035
	M1.Close();
sl@0
  1036
	test.End();
sl@0
  1037
	}
sl@0
  1038
sl@0
  1039
/*****************************************************************************
sl@0
  1040
 * Utilities for semaphore test
sl@0
  1041
 *****************************************************************************/
sl@0
  1042
void SemWait()
sl@0
  1043
	{
sl@0
  1044
	S.Wait();
sl@0
  1045
	++Count;
sl@0
  1046
	ThreadId[PutIx++]=(TUint)RThread().Id();
sl@0
  1047
	}
sl@0
  1048
sl@0
  1049
void SemSignal()
sl@0
  1050
	{
sl@0
  1051
	S.Signal();
sl@0
  1052
	}
sl@0
  1053
sl@0
  1054
TInt SemThreadFunction(TAny* aPtr)
sl@0
  1055
	{
sl@0
  1056
	PFV& f=*(PFV*)aPtr;
sl@0
  1057
	FOREVER
sl@0
  1058
		{
sl@0
  1059
		SemWait();
sl@0
  1060
		if (f)
sl@0
  1061
			f();
sl@0
  1062
		SemSignal();
sl@0
  1063
		User::WaitForAnyRequest();
sl@0
  1064
		}
sl@0
  1065
	}
sl@0
  1066
sl@0
  1067
void Wait()
sl@0
  1068
	{
sl@0
  1069
	User::WaitForAnyRequest();
sl@0
  1070
	}
sl@0
  1071
sl@0
  1072
TUint CreateSemThread(RThread& t, TInt n, TAny* aPtr)
sl@0
  1073
	{
sl@0
  1074
	TBuf<4> b;
sl@0
  1075
	b.Num(n);
sl@0
  1076
	TInt r=t.Create(b,SemThreadFunction,0x1000,NULL,aPtr);
sl@0
  1077
	test(r==KErrNone);
sl@0
  1078
	t.Resume();
sl@0
  1079
	TUint id=t.Id();
sl@0
  1080
	return id;
sl@0
  1081
	}
sl@0
  1082
sl@0
  1083
/*
sl@0
  1084
Possible thread relationships with semaphore:
sl@0
  1085
	Waiting
sl@0
  1086
	Waiting + suspended
sl@0
  1087
sl@0
  1088
Need to verify correct behaviour when the following actions occur for each of these states:
sl@0
  1089
	Suspend thread
sl@0
  1090
	Resume thread
sl@0
  1091
	Change thread priority
sl@0
  1092
	Thread exits
sl@0
  1093
	Thread is killed
sl@0
  1094
	Semaphore deleted
sl@0
  1095
*/
sl@0
  1096
sl@0
  1097
void RackEmUp2(RThread* t, PFV* f, TUint* id)
sl@0
  1098
	{
sl@0
  1099
	// set up
sl@0
  1100
	// t1, t2, t4, t5, t6, t8, t9 waiting
sl@0
  1101
	// t3, t7, t10 waiting+suspended
sl@0
  1102
	(void)f;
sl@0
  1103
	MCOUNT(S,2);			// check semaphore level = 2
sl@0
  1104
	SemWait();
sl@0
  1105
	SemWait();
sl@0
  1106
	MCOUNT(S,0);			// check semaphore level = 0
sl@0
  1107
	NUMCHECK(2);
sl@0
  1108
	IDCHECK(id0);
sl@0
  1109
	IDCHECK(id0);
sl@0
  1110
	TInt i;
sl@0
  1111
	for (i=1; i<=10; ++i)
sl@0
  1112
		Kick(t[i]);			// wake up threads
sl@0
  1113
	User::After(50000);		// let threads wait
sl@0
  1114
	MCOUNT(S,-10);			// check 10 threads waiting
sl@0
  1115
	t[7].Resume();			// test resume when not suspended
sl@0
  1116
	MCOUNT(S,-10);			// check 7 threads waiting
sl@0
  1117
	t[3].Suspend();
sl@0
  1118
	t[7].Suspend();
sl@0
  1119
	t[10].Suspend();		// now have required state
sl@0
  1120
	t[3].Suspend();			// suspend and resume t3 again for good measure
sl@0
  1121
	t[3].Resume();
sl@0
  1122
	MCOUNT(S,-7);			// check 7 threads waiting
sl@0
  1123
	}
sl@0
  1124
sl@0
  1125
void Resurrect2(TInt n, TThreadPriority aPriority, RThread* t, PFV* f, TUint* id)
sl@0
  1126
	{
sl@0
  1127
	f[n]=NULL;
sl@0
  1128
	id[n]=CreateSemThread(t[n],n,f+n);
sl@0
  1129
	t[n].SetPriority(EPriorityRealTime);
sl@0
  1130
	t[n].SetPriority(aPriority);
sl@0
  1131
	NUMCHECK(1);
sl@0
  1132
	IDCHECK(id[n]);
sl@0
  1133
	}
sl@0
  1134
sl@0
  1135
/*****************************************************************************
sl@0
  1136
 * Semaphore exhaustive state transition test
sl@0
  1137
 *****************************************************************************/
sl@0
  1138
void TestSemaphore()
sl@0
  1139
	{
sl@0
  1140
	test.Start(_L("Test semaphore state transitions"));
sl@0
  1141
	RThread t[11];
sl@0
  1142
	TUint id[11];
sl@0
  1143
	PFV f[11]={NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
sl@0
  1144
	id[0]=(TUint)RThread().Id();
sl@0
  1145
	PutIx=0;
sl@0
  1146
	GetIx=0;
sl@0
  1147
	Count=0;
sl@0
  1148
	test.Next(_L("Create semaphore"));
sl@0
  1149
	TInt r=S.CreateLocal(2);
sl@0
  1150
	test(r==KErrNone);
sl@0
  1151
	MCOUNT(S,2);
sl@0
  1152
	SemWait();
sl@0
  1153
	MCOUNT(S,1);
sl@0
  1154
	SemSignal();
sl@0
  1155
	MCOUNT(S,2);
sl@0
  1156
	SemWait();
sl@0
  1157
	SemWait();
sl@0
  1158
	MCOUNT(S,0);
sl@0
  1159
	S.Signal(2);
sl@0
  1160
	MCOUNT(S,2);
sl@0
  1161
	NUMCHECK(3);
sl@0
  1162
	IDCHECK(id0);
sl@0
  1163
	IDCHECK(id0);
sl@0
  1164
	IDCHECK(id0);
sl@0
  1165
	test.Next(_L("Create threads"));
sl@0
  1166
	TInt i;
sl@0
  1167
	for (i=1; i<=10; ++i)
sl@0
  1168
		{
sl@0
  1169
		id[i]=CreateSemThread(t[i],i,f+i);
sl@0
  1170
		f[i]=&Wait;
sl@0
  1171
		}
sl@0
  1172
	t[8].SetPriority(EPriorityMore);	// t1-t3=less, t4-t7=normal, t8-t10 more, t0 much more
sl@0
  1173
	t[9].SetPriority(EPriorityMore);
sl@0
  1174
	t[10].SetPriority(EPriorityMore);
sl@0
  1175
	t[1].SetPriority(EPriorityLess);
sl@0
  1176
	t[2].SetPriority(EPriorityLess);
sl@0
  1177
	t[3].SetPriority(EPriorityLess);
sl@0
  1178
	User::After(50000);
sl@0
  1179
	MCOUNT(S,-8);			// check 8 waiting
sl@0
  1180
	NUMCHECK(2);
sl@0
  1181
	IDCHECK(id8);
sl@0
  1182
	IDCHECK(id9);			// check t8,t9 got through
sl@0
  1183
	t[8].SetPriority(EPriorityRealTime);
sl@0
  1184
	Kick(t[8]);				// let t8 run and signal
sl@0
  1185
	t[8].SetPriority(EPriorityMore);
sl@0
  1186
	MCOUNT(S,-7);			// check 7 waiting
sl@0
  1187
	User::After(50000);		// let next thread obtain semaphore
sl@0
  1188
	MCOUNT(S,-7);			// check 7 waiting
sl@0
  1189
	NUMCHECK(1);
sl@0
  1190
	IDCHECK(id10);			// check t10 got it
sl@0
  1191
	Kick(t[10]);			// let t10 run and signal
sl@0
  1192
	User::After(50000);		// let next thread obtain semaphore
sl@0
  1193
	MCOUNT(S,-6);			// check 6 waiting
sl@0
  1194
	NUMCHECK(1);
sl@0
  1195
	IDCHECK(id4);			// check t4 got it
sl@0
  1196
	t[1].SetPriority(EPriorityRealTime);	// boost t1
sl@0
  1197
	MCOUNT(S,-6);			// check 6 still waiting
sl@0
  1198
	User::After(50000);		// let next thread obtain semaphore
sl@0
  1199
	MCOUNT(S,-6);			// check 6 still waiting
sl@0
  1200
	NUMCHECK(0);
sl@0
  1201
	Kick(t[9]);				// make t9 ready to run and signal
sl@0
  1202
	MCOUNT(S,-6);			// check 6 still waiting
sl@0
  1203
	User::After(50000);		// let next thread obtain semaphore
sl@0
  1204
	MCOUNT(S,-5);			// check 5 waiting
sl@0
  1205
	NUMCHECK(1);
sl@0
  1206
	IDCHECK(id1);			// check t1 got it
sl@0
  1207
	t[1].SetPriority(EPriorityLess);
sl@0
  1208
	Kick(t[1]);				// kick all remaining threads
sl@0
  1209
	Kick(t[2]);
sl@0
  1210
	Kick(t[3]);
sl@0
  1211
	Kick(t[4]);
sl@0
  1212
	Kick(t[5]);
sl@0
  1213
	Kick(t[6]);
sl@0
  1214
	Kick(t[7]);
sl@0
  1215
	User::After(50000);		// let them run and obtain/signal the semaphore
sl@0
  1216
	MCOUNT(S,2);			// check semaphore now back to initial level
sl@0
  1217
	SimpleCheck(5,id,5,6,7,2,3);
sl@0
  1218
sl@0
  1219
	for (i=1; i<=10; ++i)
sl@0
  1220
		f[i]=NULL;
sl@0
  1221
	RackEmUp2(t,f,id);		// set up threads waiting on semaphore again
sl@0
  1222
	S.Signal();
sl@0
  1223
	SimpleCheck(7,id,8,9,4,5,6,1,2);	// let them go
sl@0
  1224
	MCOUNT(S,1);
sl@0
  1225
	S.Wait();
sl@0
  1226
	t[3].SetPriority(EPriorityRealTime);	// change suspended thread priority
sl@0
  1227
	t[7].Resume();
sl@0
  1228
	SimpleCheck(0,id);		// t7 should wait for signal
sl@0
  1229
	S.Signal();
sl@0
  1230
	SimpleCheck(1,id,7);
sl@0
  1231
	MCOUNT(S,1);
sl@0
  1232
	t[3].Resume();
sl@0
  1233
	t[10].Resume();
sl@0
  1234
	NUMCHECK(1);
sl@0
  1235
	IDCHECK(id3);			// t3 should have grabbed semaphore as soon as we resumed it
sl@0
  1236
	SimpleCheck(1,id,10);
sl@0
  1237
	t[3].SetPriority(EPriorityLess);
sl@0
  1238
	S.Signal();				// put level back to 2
sl@0
  1239
sl@0
  1240
	RackEmUp2(t,f,id);		// set up threads waiting on semaphore again
sl@0
  1241
	S.Signal();
sl@0
  1242
	SimpleCheck(7,id,8,9,4,5,6,1,2);	// let them go
sl@0
  1243
	MCOUNT(S,1);
sl@0
  1244
	S.Wait();
sl@0
  1245
	t[3].SetPriority(EPriorityRealTime);	// change suspended thread priority
sl@0
  1246
	t[7].Resume();
sl@0
  1247
	SimpleCheck(0,id);		// t7 should wait for signal
sl@0
  1248
	S.Signal();
sl@0
  1249
	SimpleCheck(1,id,7);
sl@0
  1250
	MCOUNT(S,1);
sl@0
  1251
	t[10].Resume();
sl@0
  1252
	t[3].Resume();			// t3 not woken up here since t10 has already been given the semaphore
sl@0
  1253
	NUMCHECK(0);
sl@0
  1254
	SimpleCheck(2,id,10,3);
sl@0
  1255
	t[3].SetPriority(EPriorityLess);
sl@0
  1256
	S.Signal();				// put level back to 2
sl@0
  1257
sl@0
  1258
	RackEmUp2(t,f,id);		// set up threads waiting on semaphore again
sl@0
  1259
	S.Signal();
sl@0
  1260
	SimpleCheck(7,id,8,9,4,5,6,1,2);	// let them go
sl@0
  1261
	MCOUNT(S,1);
sl@0
  1262
	S.Wait();
sl@0
  1263
	t[3].SetPriority(EPriorityRealTime);	// change suspended thread priority
sl@0
  1264
	t[7].Resume();
sl@0
  1265
	SimpleCheck(0,id);		// t7 should wait for signal
sl@0
  1266
	S.Signal();
sl@0
  1267
	S.Signal();				// put level back to 2
sl@0
  1268
	SimpleCheck(1,id,7);
sl@0
  1269
	MCOUNT(S,2);
sl@0
  1270
	t[10].Resume();
sl@0
  1271
	t[3].Resume();			// t3 and t10 both woken up here, t3 should run and signal
sl@0
  1272
	MCOUNT(S,1);
sl@0
  1273
	NUMCHECK(1);
sl@0
  1274
	IDCHECK(id3);
sl@0
  1275
	SimpleCheck(1,id,10);
sl@0
  1276
	t[3].SetPriority(EPriorityLess);
sl@0
  1277
sl@0
  1278
	RackEmUp2(t,f,id);		// set up threads waiting on semaphore again
sl@0
  1279
	t[9].Kill(0);			// kill waiting thread
sl@0
  1280
	t[9].Close();
sl@0
  1281
	test(!Exists(9));
sl@0
  1282
	t[10].Kill(0);			// kill suspended thread
sl@0
  1283
	t[10].Close();
sl@0
  1284
	test(!Exists(10));
sl@0
  1285
	MCOUNT(S,-6);
sl@0
  1286
	f[5]=&Exit;				// get t5 to exit after acquiring semaphore
sl@0
  1287
	S.Signal();
sl@0
  1288
	SimpleCheck(3,id,8,4,5);	// let them go
sl@0
  1289
	MCOUNT(S,-3);			// check one signal has been lost due to t5 exiting
sl@0
  1290
	t[5].Close();
sl@0
  1291
	test(!Exists(5));
sl@0
  1292
	t[3].Resume();
sl@0
  1293
	t[7].Resume();
sl@0
  1294
	MCOUNT(S,-5);
sl@0
  1295
	S.Signal();
sl@0
  1296
	SimpleCheck(5,id,6,7,1,2,3);	// let them go
sl@0
  1297
	MCOUNT(S,1);
sl@0
  1298
	Resurrect2(9,EPriorityMore,t,f,id);
sl@0
  1299
	Resurrect2(10,EPriorityMore,t,f,id);
sl@0
  1300
	Resurrect2(5,EPriorityNormal,t,f,id);
sl@0
  1301
	S.Signal();
sl@0
  1302
sl@0
  1303
	RackEmUp2(t,f,id);		// set up threads waiting on semaphore again
sl@0
  1304
	f[5]=&Exit;				// get t5 to exit after acquiring semaphore
sl@0
  1305
	S.Close();				// close semaphore - threads should panic except for 5
sl@0
  1306
sl@0
  1307
	TBool jit = User::JustInTime();
sl@0
  1308
	User::SetJustInTime(EFalse);
sl@0
  1309
	User::After(1000000);
sl@0
  1310
	User::SetJustInTime(jit);
sl@0
  1311
	for (i=1; i<=10; ++i)
sl@0
  1312
		{
sl@0
  1313
		if (i==3 || i==7 || i==10)
sl@0
  1314
			{
sl@0
  1315
			test(t[i].ExitType()==EExitPending);
sl@0
  1316
			}
sl@0
  1317
		else if (i!=5)
sl@0
  1318
			{
sl@0
  1319
			test(t[i].ExitType()==EExitPanic);
sl@0
  1320
			test(t[i].ExitReason()==EBadHandle);
sl@0
  1321
			test(t[i].ExitCategory()==_L("KERN-EXEC"));
sl@0
  1322
			t[i].Close();
sl@0
  1323
			test(!Exists(i));
sl@0
  1324
			}
sl@0
  1325
		else
sl@0
  1326
			{
sl@0
  1327
			test(t[i].ExitType()==EExitKill);
sl@0
  1328
			test(t[i].ExitReason()==0);
sl@0
  1329
			t[i].Close();
sl@0
  1330
			test(!Exists(i));
sl@0
  1331
			}
sl@0
  1332
		}
sl@0
  1333
	t[3].Resume();
sl@0
  1334
	t[7].Resume();
sl@0
  1335
	t[10].Resume();
sl@0
  1336
	User::SetJustInTime(EFalse);
sl@0
  1337
	User::After(1000000);
sl@0
  1338
	User::SetJustInTime(jit);
sl@0
  1339
	for (i=1; i<=10; ++i)
sl@0
  1340
		{
sl@0
  1341
		if (i==3 || i==7 || i==10)
sl@0
  1342
			{
sl@0
  1343
			test(t[i].ExitType()==EExitPanic);
sl@0
  1344
			test(t[i].ExitReason()==EBadHandle);
sl@0
  1345
			test(t[i].ExitCategory()==_L("KERN-EXEC"));
sl@0
  1346
			t[i].Close();
sl@0
  1347
			test(!Exists(i));
sl@0
  1348
			}
sl@0
  1349
		}
sl@0
  1350
sl@0
  1351
	test.End();
sl@0
  1352
	}
sl@0
  1353
sl@0
  1354
/*****************************************************************************
sl@0
  1355
 * Semaphore benchmarks
sl@0
  1356
 *****************************************************************************/
sl@0
  1357
TInt SemSpeed(TAny* aPtr)
sl@0
  1358
	{
sl@0
  1359
	TInt& count=*(TInt*)aPtr;
sl@0
  1360
	RThread().SetPriority(EPriorityMore);
sl@0
  1361
	FOREVER
sl@0
  1362
		{
sl@0
  1363
		S.Wait();
sl@0
  1364
		S.Signal();
sl@0
  1365
		++count;
sl@0
  1366
		}
sl@0
  1367
	}
sl@0
  1368
sl@0
  1369
void TestSemSpeed()
sl@0
  1370
	{
sl@0
  1371
	test.Start(_L("Test semaphore speed"));
sl@0
  1372
	TInt count=0;
sl@0
  1373
	TInt r=S.CreateLocal(1);
sl@0
  1374
	test(r==KErrNone);
sl@0
  1375
sl@0
  1376
	RThread t;
sl@0
  1377
	r=t.Create(_L("SemSpeed"),SemSpeed,0x1000,NULL,&count);
sl@0
  1378
	test(r==KErrNone);
sl@0
  1379
	t.SetPriority(EPriorityRealTime);
sl@0
  1380
	t.Resume();
sl@0
  1381
	User::AfterHighRes(1000000);
sl@0
  1382
	t.Kill(0);
sl@0
  1383
	t.Close();
sl@0
  1384
	test(!Exists(_L("SemSpeed")));
sl@0
  1385
	test.Printf(_L("%d wait/signal in 1 second\n"),count);
sl@0
  1386
sl@0
  1387
	S.Close();
sl@0
  1388
	test.End();
sl@0
  1389
	}
sl@0
  1390
sl@0
  1391
sl@0
  1392
GLDEF_C TInt E32Main()
sl@0
  1393
	{
sl@0
  1394
	test.Title();
sl@0
  1395
sl@0
  1396
	test.Start(_L("Test mutexes and semaphores"));
sl@0
  1397
	RThread().SetPriority(EPriorityMuchMore);
sl@0
  1398
	TInt r=Main.Duplicate(RThread());
sl@0
  1399
	test(r==KErrNone);
sl@0
  1400
sl@0
  1401
	Test0();
sl@0
  1402
	Test1();
sl@0
  1403
	TestMutex1();
sl@0
  1404
	TestMutex2();
sl@0
  1405
	TestSemaphore();
sl@0
  1406
	
sl@0
  1407
	TestMutexSpeed();
sl@0
  1408
	TestSemSpeed();
sl@0
  1409
sl@0
  1410
	Main.Close();
sl@0
  1411
	test.End();
sl@0
  1412
	return KErrNone;
sl@0
  1413
	}
sl@0
  1414