os/kernelhwsrv/kerneltest/e32test/smp_demo/smp_demo.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) 2006-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\smp_demo\smp_demo.cpp
sl@0
    15
// Demonstration for SMP
sl@0
    16
// 
sl@0
    17
//
sl@0
    18
sl@0
    19
#include <e32test.h>
sl@0
    20
#include <u32hal.h>
sl@0
    21
#include <e32svr.h>
sl@0
    22
#include <f32file.h>
sl@0
    23
#include <hal.h>
sl@0
    24
#include <e32math.h>
sl@0
    25
sl@0
    26
RTest test(_L("SMP_DEMO"));
sl@0
    27
sl@0
    28
#define DEBUG_PRINT(__args)		test.Printf __args ;
sl@0
    29
sl@0
    30
TBool   TestThreadsExit = EFalse;
sl@0
    31
_LIT(KTestBlank, "");
sl@0
    32
sl@0
    33
sl@0
    34
//#define LOCK_TYPE	RMutex
sl@0
    35
//#define LOCK_TYPE_CREATE_PARAM	
sl@0
    36
#define LOCK_TYPE	RFastLock
sl@0
    37
#define LOCK_TYPE_CREATE_PARAM	
sl@0
    38
//#define LOCK_TYPE	RSemaphore
sl@0
    39
//#define LOCK_TYPE_CREATE_PARAM	0
sl@0
    40
sl@0
    41
#define MAX_THREADS		8		
sl@0
    42
#define MAX_CHAPTERS	28
sl@0
    43
sl@0
    44
TUint8		TestGuess[MAX_THREADS];
sl@0
    45
TInt		TestGuessReady[MAX_THREADS];
sl@0
    46
LOCK_TYPE	TestGuessLock[MAX_THREADS];
sl@0
    47
sl@0
    48
TInt		TestGuessChanged[MAX_THREADS];
sl@0
    49
LOCK_TYPE	TestChangedLock[MAX_THREADS];
sl@0
    50
TUint8		TestNext[MAX_THREADS];
sl@0
    51
sl@0
    52
TUint		TestGuessMisses[MAX_THREADS];
sl@0
    53
TUint		TestGuessCorrect[MAX_THREADS];
sl@0
    54
TUint		TestGuessIncorrect[MAX_THREADS];
sl@0
    55
TUint		TestGuessCollision[MAX_THREADS];
sl@0
    56
TInt		TestCpuCount = 0;
sl@0
    57
sl@0
    58
TBool		TestUseMathRandom = ETrue;
sl@0
    59
TBool		TestSingleCpu = EFalse;
sl@0
    60
TBool		TestDualCpu = EFalse;
sl@0
    61
TBool		TestNoPrint = EFalse;
sl@0
    62
TBool		TestSingleThread = EFalse;
sl@0
    63
TBool		TestUseAffinity = ETrue;
sl@0
    64
sl@0
    65
TInt LoadChapter(TInt chapterIndex, HBufC8 **aChapterPtrPtr)
sl@0
    66
	{
sl@0
    67
	RFile file;
sl@0
    68
	RFs fs;
sl@0
    69
	if (KErrNone != fs.Connect())
sl@0
    70
		{
sl@0
    71
		DEBUG_PRINT(_L("LoadChapter : Can't connect to the FS\n"));
sl@0
    72
		return KErrGeneral;
sl@0
    73
		}
sl@0
    74
sl@0
    75
	TBuf<32>	filename;
sl@0
    76
	filename.Format(_L("z:\\Test\\war_and_peace_ch%d.txt"), chapterIndex);
sl@0
    77
sl@0
    78
	TInt ret = file.Open(fs,filename,EFileRead);
sl@0
    79
	if (ret == KErrNone)
sl@0
    80
		{
sl@0
    81
		TInt fileSize = 0;
sl@0
    82
		ret = file.Size(fileSize);
sl@0
    83
		if (ret == KErrNone)
sl@0
    84
			{
sl@0
    85
			HBufC8 *theBuf = HBufC8::New(fileSize + 10);
sl@0
    86
			if (theBuf != NULL)
sl@0
    87
				{
sl@0
    88
				TPtr8 des2=theBuf->Des();
sl@0
    89
				ret = file.Read((TInt)0, des2,fileSize);
sl@0
    90
				if (ret == KErrNone)
sl@0
    91
					{
sl@0
    92
					*aChapterPtrPtr = theBuf;
sl@0
    93
					}
sl@0
    94
				else
sl@0
    95
					{
sl@0
    96
					DEBUG_PRINT((_L("LoadChapter : Read Failed for %S of %d\n"), &filename, fileSize));
sl@0
    97
					}
sl@0
    98
				}
sl@0
    99
			else
sl@0
   100
				{
sl@0
   101
				DEBUG_PRINT((_L("LoadChapter : Buffer Alloc Failed for %S\n"), &filename));
sl@0
   102
				}
sl@0
   103
			}
sl@0
   104
		else
sl@0
   105
			{
sl@0
   106
			DEBUG_PRINT((_L("LoadChapter : Size Failed for %S\n"), &filename));
sl@0
   107
			}
sl@0
   108
		file.Close();
sl@0
   109
		}
sl@0
   110
	else
sl@0
   111
		{
sl@0
   112
		DEBUG_PRINT((_L("LoadChapter : Open Failed for %S\n"), &filename));
sl@0
   113
		}
sl@0
   114
	
sl@0
   115
	return ret;
sl@0
   116
	}	
sl@0
   117
sl@0
   118
TInt SetCpuAffinity(TInt aThreadId)
sl@0
   119
	{
sl@0
   120
	if (TestUseAffinity)
sl@0
   121
		{
sl@0
   122
		TUint32 cpu;
sl@0
   123
sl@0
   124
		if (TestCpuCount == 4)
sl@0
   125
			cpu = (TUint32)(aThreadId % 3) + 1;
sl@0
   126
		else if (TestCpuCount == 2)
sl@0
   127
			cpu = (TUint32)1;
sl@0
   128
		else
sl@0
   129
			cpu = 0;
sl@0
   130
sl@0
   131
		TInt r = UserSvr::HalFunction(EHalGroupKernel, EKernelHalLockThreadToCpu, (TAny *)cpu, 0);
sl@0
   132
		test(r==KErrNone);	
sl@0
   133
		return r;
sl@0
   134
		}
sl@0
   135
	return KErrNone;
sl@0
   136
	}
sl@0
   137
sl@0
   138
sl@0
   139
LOCAL_C TInt DemoThread(TAny* aUseTb)
sl@0
   140
	{
sl@0
   141
	TInt	threadId = (TInt)aUseTb;
sl@0
   142
	
sl@0
   143
	SetCpuAffinity(threadId);
sl@0
   144
	User::After(100);
sl@0
   145
sl@0
   146
	TestGuessChanged[threadId] = EFalse;
sl@0
   147
	TestGuessReady[threadId] = EFalse;
sl@0
   148
	TestGuessMisses[threadId] = 0;
sl@0
   149
	TestGuessCorrect[threadId] = 0;
sl@0
   150
	TestGuessIncorrect[threadId] = 0;
sl@0
   151
	TestGuessCollision[threadId] = 0;
sl@0
   152
sl@0
   153
	TUint8	guess = 0;
sl@0
   154
	TUint8	nextChar = TestNext[threadId];
sl@0
   155
	TBool	correct = EFalse;
sl@0
   156
sl@0
   157
	while (!TestThreadsExit)
sl@0
   158
		{
sl@0
   159
		correct = EFalse;
sl@0
   160
sl@0
   161
		if (TestUseMathRandom)
sl@0
   162
			guess = (TUint8)Math::Random();
sl@0
   163
		else
sl@0
   164
			guess ++;
sl@0
   165
sl@0
   166
		if (TestGuessChanged[threadId])
sl@0
   167
			{
sl@0
   168
			TestChangedLock[threadId].Wait();
sl@0
   169
			nextChar = TestNext[threadId];
sl@0
   170
			TestGuessChanged[threadId] = EFalse;
sl@0
   171
			TestChangedLock[threadId].Signal();			
sl@0
   172
			}
sl@0
   173
		correct = (nextChar == guess);
sl@0
   174
sl@0
   175
		if (correct)
sl@0
   176
			{
sl@0
   177
			if (TestGuessReady[threadId] == EFalse)
sl@0
   178
				{
sl@0
   179
				TestGuessLock[threadId].Wait();
sl@0
   180
				TestGuess[threadId] = guess;
sl@0
   181
				TestGuessReady[threadId] = ETrue;
sl@0
   182
				TestGuessLock[threadId].Signal();
sl@0
   183
				TestGuessCorrect[threadId] ++;
sl@0
   184
				}
sl@0
   185
			else
sl@0
   186
				{
sl@0
   187
				TestGuessMisses[threadId] ++;
sl@0
   188
				}
sl@0
   189
			}
sl@0
   190
		else
sl@0
   191
			{
sl@0
   192
			TestGuessIncorrect[threadId] ++;
sl@0
   193
			}
sl@0
   194
		if (TestCpuCount == 1)
sl@0
   195
			{
sl@0
   196
			User::After(0);
sl@0
   197
			}
sl@0
   198
		}
sl@0
   199
	return KErrNone;
sl@0
   200
	}
sl@0
   201
sl@0
   202
TInt NumberOfCpus()
sl@0
   203
	{
sl@0
   204
	TInt r = UserSvr::HalFunction(EHalGroupKernel, EKernelHalNumLogicalCpus, 0, 0);
sl@0
   205
	test(r>0);
sl@0
   206
	return r;
sl@0
   207
	}
sl@0
   208
sl@0
   209
TInt ParseArgs(void)
sl@0
   210
	{
sl@0
   211
	TBuf<256> args;
sl@0
   212
	User::CommandLine(args);
sl@0
   213
	TLex	lex(args);
sl@0
   214
sl@0
   215
	FOREVER
sl@0
   216
		{
sl@0
   217
		TPtrC  token=lex.NextToken();
sl@0
   218
		if(token.Length()!=0)
sl@0
   219
			{
sl@0
   220
			if (token == _L("unbound"))
sl@0
   221
				{
sl@0
   222
				TestUseMathRandom = EFalse;
sl@0
   223
				}
sl@0
   224
			if (token == _L("single"))
sl@0
   225
				{
sl@0
   226
				TestSingleCpu = ETrue;
sl@0
   227
				}
sl@0
   228
			if (token == _L("dual"))
sl@0
   229
				{
sl@0
   230
				TestDualCpu = ETrue;
sl@0
   231
				}
sl@0
   232
			if (token == _L("silent"))
sl@0
   233
				{
sl@0
   234
				TestNoPrint = ETrue;
sl@0
   235
				}
sl@0
   236
			if (token == _L("onethread"))
sl@0
   237
				{
sl@0
   238
				TestSingleCpu = ETrue;
sl@0
   239
				TestSingleThread = ETrue;
sl@0
   240
				}
sl@0
   241
			if (token == _L("help"))
sl@0
   242
				{
sl@0
   243
				test.Printf(_L("smp_demo: unbound | single | onethread | silent | dual | noaffinity | help \n"));
sl@0
   244
				return -1;
sl@0
   245
				}
sl@0
   246
			if (token == _L("noaffinity"))
sl@0
   247
				{
sl@0
   248
				TestUseAffinity = EFalse;
sl@0
   249
				}
sl@0
   250
			}
sl@0
   251
		else
sl@0
   252
			{
sl@0
   253
			break;
sl@0
   254
			}
sl@0
   255
		}
sl@0
   256
		return KErrNone;
sl@0
   257
	}
sl@0
   258
sl@0
   259
TInt E32Main()
sl@0
   260
	{
sl@0
   261
	test.Title();
sl@0
   262
	test.Start(_L("SMP Demonstration guessing War and Peace...."));
sl@0
   263
	
sl@0
   264
	if (ParseArgs() != KErrNone)
sl@0
   265
		{
sl@0
   266
		test.Getch();
sl@0
   267
		test.End();
sl@0
   268
		return KErrNone;
sl@0
   269
		}
sl@0
   270
sl@0
   271
	TUint   start = User::TickCount();
sl@0
   272
	TInt	tickPeriod = 0;
sl@0
   273
	HAL::Get(HAL::ESystemTickPeriod, tickPeriod);
sl@0
   274
sl@0
   275
	if (TestSingleCpu)
sl@0
   276
		{
sl@0
   277
		TestCpuCount = 1;
sl@0
   278
		}
sl@0
   279
	else if (TestDualCpu)
sl@0
   280
		{
sl@0
   281
		TestCpuCount = 2;
sl@0
   282
		}
sl@0
   283
	else
sl@0
   284
		{
sl@0
   285
		TestCpuCount = NumberOfCpus();
sl@0
   286
		}
sl@0
   287
	
sl@0
   288
	DEBUG_PRINT((_L("CPU Count %d\n"), TestCpuCount));
sl@0
   289
sl@0
   290
	TRequestStatus	theStatus[MAX_THREADS];
sl@0
   291
	RThread			theThreads[MAX_THREADS];
sl@0
   292
	TBool			threadInUse[MAX_THREADS];
sl@0
   293
sl@0
   294
	TInt	index;
sl@0
   295
	TInt	maxChapters = MAX_CHAPTERS;
sl@0
   296
sl@0
   297
	if (TestUseMathRandom)
sl@0
   298
		{
sl@0
   299
		maxChapters = 2;
sl@0
   300
		}
sl@0
   301
sl@0
   302
	TInt	maxIndex = TestCpuCount - 1;
sl@0
   303
	if (maxIndex == 0)
sl@0
   304
		{
sl@0
   305
		maxChapters = 2;
sl@0
   306
		maxIndex = 1;
sl@0
   307
		}
sl@0
   308
	else if ((maxIndex == 1) && (TestUseMathRandom))
sl@0
   309
		{
sl@0
   310
		maxChapters = 4;
sl@0
   311
		}
sl@0
   312
sl@0
   313
	TInt	ret;
sl@0
   314
	TUint32 cpu = 0;
sl@0
   315
sl@0
   316
	if (TestUseAffinity)
sl@0
   317
		{
sl@0
   318
		UserSvr::HalFunction(EHalGroupKernel, EKernelHalLockThreadToCpu, (TAny *)cpu, 0);
sl@0
   319
		}
sl@0
   320
sl@0
   321
	if (TestSingleThread)
sl@0
   322
		{
sl@0
   323
		TInt	chapterIndex;
sl@0
   324
		TUint8	guess = 0;
sl@0
   325
		
sl@0
   326
		maxChapters = MAX_CHAPTERS;
sl@0
   327
sl@0
   328
		TRequestStatus keyStatus;
sl@0
   329
		CConsoleBase*  console=test.Console();
sl@0
   330
		
sl@0
   331
		console->Read(keyStatus);
sl@0
   332
sl@0
   333
		for (chapterIndex = 0; chapterIndex < maxChapters; chapterIndex ++)
sl@0
   334
			{
sl@0
   335
			HBufC8 *chapterPtr = NULL;
sl@0
   336
			ret = LoadChapter(chapterIndex + 1, &chapterPtr);
sl@0
   337
			if ((ret != KErrNone) || (chapterPtr == NULL))
sl@0
   338
				{
sl@0
   339
				DEBUG_PRINT((_L("E32Main: LoadChapter failed %d\n"), ret));
sl@0
   340
				}
sl@0
   341
			else
sl@0
   342
				{
sl@0
   343
				TPtr8			theDes = chapterPtr->Des();
sl@0
   344
				TUint8		   *pData = (TUint8 *)theDes.Ptr();
sl@0
   345
				TInt			dataLength = chapterPtr->Length();
sl@0
   346
sl@0
   347
sl@0
   348
				while (dataLength > 0)
sl@0
   349
					{
sl@0
   350
					if (TestUseMathRandom)
sl@0
   351
						guess = (TUint8)Math::Random();
sl@0
   352
					else
sl@0
   353
						guess ++;
sl@0
   354
sl@0
   355
 					if (*pData == guess)
sl@0
   356
						{
sl@0
   357
						pData ++;
sl@0
   358
						dataLength --;
sl@0
   359
						if (!TestNoPrint)
sl@0
   360
							{
sl@0
   361
							test.Printf(_L("%c"), (TUint8)guess);
sl@0
   362
							}
sl@0
   363
						}
sl@0
   364
					if (keyStatus != KRequestPending)
sl@0
   365
						{
sl@0
   366
						if (console->KeyCode() == EKeyEscape)
sl@0
   367
							{
sl@0
   368
							TestThreadsExit = ETrue;
sl@0
   369
							break;
sl@0
   370
							}
sl@0
   371
						console->Read(keyStatus);
sl@0
   372
						}
sl@0
   373
					}
sl@0
   374
				// clean up
sl@0
   375
				delete chapterPtr;
sl@0
   376
				test.Printf(_L("\n\n"));
sl@0
   377
				if (TestThreadsExit)
sl@0
   378
					{
sl@0
   379
					break;
sl@0
   380
					}
sl@0
   381
				}
sl@0
   382
			}
sl@0
   383
		console->ReadCancel();
sl@0
   384
		test.Printf(_L("Finished after %d chapters!\n"),chapterIndex);
sl@0
   385
		}
sl@0
   386
	else
sl@0
   387
		{
sl@0
   388
		for (index = 0; index < maxIndex; index ++)
sl@0
   389
			{
sl@0
   390
			TestGuessLock[index].CreateLocal(LOCK_TYPE_CREATE_PARAM);
sl@0
   391
			TestChangedLock[index].CreateLocal(LOCK_TYPE_CREATE_PARAM);
sl@0
   392
			ret = theThreads[index].Create(KTestBlank,DemoThread,KDefaultStackSize,NULL,(TAny*) index);
sl@0
   393
			if (ret == KErrNone)
sl@0
   394
				{
sl@0
   395
				theThreads[index].Logon(theStatus[index]);
sl@0
   396
				if (theStatus[index] != KRequestPending)
sl@0
   397
					{
sl@0
   398
					DEBUG_PRINT((_L("E32Main: !KRequestPending %d\n"), theStatus[index].Int() ));
sl@0
   399
					}	
sl@0
   400
				theThreads[index].Resume();
sl@0
   401
				threadInUse[index] = ETrue;
sl@0
   402
				DEBUG_PRINT((_L("E32Main: starting thread %d %d\n"), index, index % TestCpuCount));
sl@0
   403
				}
sl@0
   404
			else
sl@0
   405
				{
sl@0
   406
				DEBUG_PRINT((_L("E32Main: Create thread failed %d\n"), ret));
sl@0
   407
				return KErrGeneral;
sl@0
   408
				}
sl@0
   409
			}
sl@0
   410
sl@0
   411
		TInt	chapterIndex;
sl@0
   412
		TInt    index2;
sl@0
   413
sl@0
   414
		TRequestStatus keyStatus;
sl@0
   415
		CConsoleBase*  console=test.Console();
sl@0
   416
		
sl@0
   417
		console->Read(keyStatus);
sl@0
   418
sl@0
   419
		for (chapterIndex = 0; chapterIndex < maxChapters; chapterIndex ++)
sl@0
   420
			{
sl@0
   421
			HBufC8 *chapterPtr = NULL;
sl@0
   422
			ret = LoadChapter(chapterIndex + 1, &chapterPtr);
sl@0
   423
			if ((ret != KErrNone) || (chapterPtr == NULL))
sl@0
   424
				{
sl@0
   425
				DEBUG_PRINT((_L("E32Main: LoadChapter failed %d\n"), ret));
sl@0
   426
				}
sl@0
   427
			else
sl@0
   428
				{
sl@0
   429
				TPtr8			theDes = chapterPtr->Des();
sl@0
   430
				TUint8		   *pData = (TUint8 *)theDes.Ptr();
sl@0
   431
				TInt			dataLength = chapterPtr->Length();
sl@0
   432
				for (index2 = 0; index2 < maxIndex; index2 ++)
sl@0
   433
					{
sl@0
   434
					TestChangedLock[index2].Wait();
sl@0
   435
					TestGuessChanged[index2] = ETrue;
sl@0
   436
					TestNext[index2] = (TUint8)*pData;
sl@0
   437
					TestChangedLock[index2].Signal();
sl@0
   438
					}
sl@0
   439
				// where the real code goes!!
sl@0
   440
				TUint8	guess = 0;
sl@0
   441
				TBool	wasReady = EFalse;
sl@0
   442
				while (dataLength > 0)
sl@0
   443
					{
sl@0
   444
					for (index = 0; index < maxIndex; index ++)
sl@0
   445
						{
sl@0
   446
						wasReady = EFalse;
sl@0
   447
						if (TestGuessReady[index])
sl@0
   448
							{
sl@0
   449
							wasReady = ETrue;
sl@0
   450
							TestGuessLock[index].Wait();
sl@0
   451
							guess = (TUint8)TestGuess[index];
sl@0
   452
							TestGuessReady[index] = EFalse;
sl@0
   453
							TestGuessLock[index].Signal();
sl@0
   454
							}
sl@0
   455
						if (wasReady)
sl@0
   456
							{
sl@0
   457
							if (*pData == guess)
sl@0
   458
								{
sl@0
   459
								pData ++;
sl@0
   460
								dataLength --;
sl@0
   461
								for (index2 = 0; index2 < maxIndex; index2 ++)
sl@0
   462
									{
sl@0
   463
									TestChangedLock[index2].Wait();
sl@0
   464
									TestNext[index2] = (TUint8)*pData;
sl@0
   465
									TestGuessChanged[index2] = ETrue;
sl@0
   466
									TestChangedLock[index2].Signal();
sl@0
   467
									}
sl@0
   468
								if (!TestNoPrint)
sl@0
   469
									{
sl@0
   470
									test.Printf(_L("%c"), (TUint8)guess);
sl@0
   471
									}
sl@0
   472
								}
sl@0
   473
							else
sl@0
   474
								{
sl@0
   475
								TestGuessCollision[index] ++;
sl@0
   476
								}
sl@0
   477
							}
sl@0
   478
						if (TestCpuCount == 1)
sl@0
   479
							{
sl@0
   480
							User::After(0);
sl@0
   481
							}
sl@0
   482
						}
sl@0
   483
					if (keyStatus != KRequestPending)
sl@0
   484
						{
sl@0
   485
						if (console->KeyCode() == EKeyEscape)
sl@0
   486
							{
sl@0
   487
							TestThreadsExit = ETrue;
sl@0
   488
							break;
sl@0
   489
							}
sl@0
   490
						console->Read(keyStatus);
sl@0
   491
						}
sl@0
   492
					}
sl@0
   493
				// clean up
sl@0
   494
				delete chapterPtr;
sl@0
   495
				test.Printf(_L("\n\n"));
sl@0
   496
				if (TestThreadsExit)
sl@0
   497
					{
sl@0
   498
					break;
sl@0
   499
					}
sl@0
   500
				}
sl@0
   501
			}
sl@0
   502
sl@0
   503
		console->ReadCancel();
sl@0
   504
		
sl@0
   505
		test.Printf(_L("Finished after %d chapters!\n"),chapterIndex);
sl@0
   506
		for (index = 0; index < maxIndex; index ++)
sl@0
   507
			{
sl@0
   508
			test.Printf(_L("Thread %d stalls %u correct %u incorrect %u collision %u\n"), index, TestGuessMisses[index],TestGuessCorrect[index],TestGuessIncorrect[index], TestGuessCollision[index]);
sl@0
   509
			}
sl@0
   510
			
sl@0
   511
		// real code ends!!
sl@0
   512
		TestThreadsExit = ETrue;
sl@0
   513
		
sl@0
   514
		TBool		anyUsed = ETrue;
sl@0
   515
sl@0
   516
		while(anyUsed)
sl@0
   517
			{
sl@0
   518
			anyUsed = EFalse;
sl@0
   519
sl@0
   520
			for (index = 0; index < maxIndex; index++)
sl@0
   521
				{
sl@0
   522
				if (threadInUse[index])
sl@0
   523
					{
sl@0
   524
					if (theThreads[index].ExitType() != EExitPending)
sl@0
   525
						{
sl@0
   526
						threadInUse[index] = EFalse;
sl@0
   527
						TestGuessLock[index].Close();
sl@0
   528
						TestChangedLock[index].Close();
sl@0
   529
						}
sl@0
   530
					else
sl@0
   531
						{
sl@0
   532
						anyUsed = ETrue;
sl@0
   533
						}
sl@0
   534
					}
sl@0
   535
				}
sl@0
   536
			}
sl@0
   537
		}		
sl@0
   538
	TUint time = TUint((TUint64)(User::TickCount()-start)*(TUint64)tickPeriod/(TUint64)1000000);
sl@0
   539
	test.Printf(_L("Complete in %u seconds\n"), time);	
sl@0
   540
	test.Getch();
sl@0
   541
	test.End();
sl@0
   542
	return KErrNone;
sl@0
   543
	}
sl@0
   544