os/kernelhwsrv/kerneltest/e32test/prime/t_rwlock.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
// Copyright (c) 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_rwlock.cpp
sl@0
    15
// Overview:
sl@0
    16
// Test the RReadWriteLock type.
sl@0
    17
// API Information:
sl@0
    18
// RReadWriteLock
sl@0
    19
// Details:
sl@0
    20
// Test all functions individually and in combination.
sl@0
    21
// Platforms/Drives/Compatibility:
sl@0
    22
// All.
sl@0
    23
// Assumptions/Requirement/Pre-requisites:
sl@0
    24
// Failures and causes:
sl@0
    25
// Base Port information:
sl@0
    26
// 
sl@0
    27
//
sl@0
    28
sl@0
    29
//! @SYMTestCaseID             KBASE-T_RWLOCK-2444
sl@0
    30
//! @SYMTestType               UT
sl@0
    31
//! @SYMTestCaseDesc           Verify correct operation of RReadWriteLock
sl@0
    32
//! @SYMPREQ                   PREQ2094
sl@0
    33
//! @SYMTestPriority           High
sl@0
    34
//! @SYMTestActions            Call all functions of RReadWriteLock in a variety
sl@0
    35
//!                            of circumstances and verify correct results                                            
sl@0
    36
//! @SYMTestExpectedResults    All tests pass
sl@0
    37
sl@0
    38
#include <e32atomics.h>
sl@0
    39
#include <e32test.h>
sl@0
    40
#include <e32panic.h>
sl@0
    41
#include <e32def.h>
sl@0
    42
#include <e32def_private.h>
sl@0
    43
sl@0
    44
RTest Test(_L("T_RWLOCK"));
sl@0
    45
RReadWriteLock TheLock;
sl@0
    46
volatile TInt ThreadsRunning;
sl@0
    47
TInt LogIndex;
sl@0
    48
TBool LogReaders[20];
sl@0
    49
sl@0
    50
// Check creating, using and closing a lock doesn't leak memory
sl@0
    51
void TestCreation()
sl@0
    52
	{
sl@0
    53
	Test.Next(_L("Creation"));
sl@0
    54
	
sl@0
    55
    __KHEAP_MARK;
sl@0
    56
    __UHEAP_MARK;
sl@0
    57
sl@0
    58
	Test(TheLock.CreateLocal() == KErrNone);
sl@0
    59
	TheLock.ReadLock();
sl@0
    60
	TheLock.Unlock();
sl@0
    61
	TheLock.WriteLock();
sl@0
    62
	TheLock.Unlock();
sl@0
    63
	TheLock.Close();
sl@0
    64
sl@0
    65
	__UHEAP_MARKEND;
sl@0
    66
	__KHEAP_MARKEND;
sl@0
    67
	}
sl@0
    68
sl@0
    69
TInt ReadEntryPoint(TAny* aArg)
sl@0
    70
	{
sl@0
    71
	*(TBool*)aArg = ETrue;
sl@0
    72
	__e32_atomic_add_ord32(&ThreadsRunning, 1);
sl@0
    73
	TheLock.ReadLock();
sl@0
    74
	const TInt index = __e32_atomic_add_ord32(&LogIndex, 1);
sl@0
    75
	LogReaders[index] = ETrue;
sl@0
    76
	TheLock.Unlock();
sl@0
    77
	__e32_atomic_add_ord32(&ThreadsRunning, TUint32(-1));
sl@0
    78
	return KErrNone;
sl@0
    79
	}
sl@0
    80
sl@0
    81
TInt WriteEntryPoint(TAny* aArg)
sl@0
    82
	{
sl@0
    83
	*(TBool*)aArg = ETrue;
sl@0
    84
	__e32_atomic_add_ord32(&ThreadsRunning, 1);
sl@0
    85
	TheLock.WriteLock();
sl@0
    86
	const TInt index = __e32_atomic_add_ord32(&LogIndex, 1);
sl@0
    87
	LogReaders[index] = EFalse;
sl@0
    88
	TheLock.Unlock();
sl@0
    89
	__e32_atomic_add_ord32(&ThreadsRunning, TUint32(-1));
sl@0
    90
	return KErrNone;
sl@0
    91
	}
sl@0
    92
sl@0
    93
void Init()
sl@0
    94
	{
sl@0
    95
	__e32_atomic_store_ord32(&ThreadsRunning, 0);
sl@0
    96
	__e32_atomic_store_ord32(&LogIndex, 0);
sl@0
    97
	}
sl@0
    98
sl@0
    99
void CreateThread(TBool aReader)
sl@0
   100
	{
sl@0
   101
	RThread newThread;
sl@0
   102
	TBool threadStarted = EFalse;
sl@0
   103
	TInt ret = newThread.Create(KNullDesC, aReader ? ReadEntryPoint : WriteEntryPoint, KDefaultStackSize, KMinHeapSize, KMinHeapSize, &threadStarted, EOwnerProcess);
sl@0
   104
	Test(ret == KErrNone, __LINE__);
sl@0
   105
	newThread.SetPriority(EPriorityMore);
sl@0
   106
	newThread.Resume();
sl@0
   107
	while (!threadStarted)
sl@0
   108
		User::After(1000);
sl@0
   109
	newThread.Close();
sl@0
   110
	}
sl@0
   111
sl@0
   112
void WaitForThreadsToClose(TInt aThreads = 0)
sl@0
   113
	{
sl@0
   114
	while (ThreadsRunning > aThreads)
sl@0
   115
		{
sl@0
   116
		User::After(1000);
sl@0
   117
		}
sl@0
   118
	}
sl@0
   119
sl@0
   120
// Check that queuing multiple reads and writes on a lock with writer priority
sl@0
   121
// results in the correct type of client being released in the correct order
sl@0
   122
// (can' predict exact client order on multi-processor systems though)
sl@0
   123
void TestWriterPriority()
sl@0
   124
	{
sl@0
   125
	Test.Next(_L("Writer Priority"));
sl@0
   126
	TInt ret = TheLock.CreateLocal(RReadWriteLock::EWriterPriority);
sl@0
   127
	Test(ret == KErrNone, __LINE__);
sl@0
   128
	TheLock.WriteLock();
sl@0
   129
sl@0
   130
	Init();
sl@0
   131
	CreateThread(ETrue);
sl@0
   132
	CreateThread(ETrue);
sl@0
   133
	CreateThread(EFalse);
sl@0
   134
	CreateThread(ETrue);
sl@0
   135
	CreateThread(EFalse);
sl@0
   136
	CreateThread(ETrue);
sl@0
   137
	CreateThread(EFalse);
sl@0
   138
	CreateThread(ETrue);
sl@0
   139
	CreateThread(EFalse);
sl@0
   140
	CreateThread(ETrue);
sl@0
   141
sl@0
   142
	TheLock.Unlock();
sl@0
   143
	WaitForThreadsToClose();
sl@0
   144
	TheLock.ReadLock();
sl@0
   145
sl@0
   146
	CreateThread(EFalse);
sl@0
   147
	CreateThread(ETrue);
sl@0
   148
	CreateThread(ETrue);
sl@0
   149
	CreateThread(EFalse);
sl@0
   150
	CreateThread(ETrue);
sl@0
   151
sl@0
   152
	TheLock.Unlock();
sl@0
   153
	WaitForThreadsToClose();
sl@0
   154
sl@0
   155
	TheLock.Close();
sl@0
   156
sl@0
   157
	Test(LogIndex == 15, __LINE__);
sl@0
   158
	const TBool expected[] = { EFalse, EFalse, EFalse, EFalse, ETrue, ETrue, ETrue, ETrue, ETrue, ETrue, EFalse, EFalse, ETrue, ETrue, ETrue };
sl@0
   159
	for (TInt index = 0; index < LogIndex; index++)
sl@0
   160
		{
sl@0
   161
		Test(LogReaders[index] == expected[index], __LINE__);
sl@0
   162
		}
sl@0
   163
	}
sl@0
   164
sl@0
   165
// Check that queuing multiple reads and writes on a lock with alternate priority
sl@0
   166
// results in the correct type of client being released in the correct order
sl@0
   167
// (can' predict exact client order on multi-processor systems though)
sl@0
   168
void TestAlternatePriority()
sl@0
   169
	{
sl@0
   170
	Test.Next(_L("Alternate Priority"));
sl@0
   171
	TInt ret = TheLock.CreateLocal(RReadWriteLock::EAlternatePriority);
sl@0
   172
	Test(ret == KErrNone, __LINE__);
sl@0
   173
	TheLock.WriteLock();
sl@0
   174
sl@0
   175
	Init();
sl@0
   176
	CreateThread(ETrue);
sl@0
   177
	CreateThread(ETrue);
sl@0
   178
	CreateThread(ETrue);
sl@0
   179
	CreateThread(ETrue);
sl@0
   180
	CreateThread(ETrue);
sl@0
   181
	CreateThread(EFalse);
sl@0
   182
	CreateThread(EFalse);
sl@0
   183
	CreateThread(EFalse);
sl@0
   184
	CreateThread(EFalse);
sl@0
   185
	CreateThread(EFalse);
sl@0
   186
sl@0
   187
	TheLock.Unlock();
sl@0
   188
	WaitForThreadsToClose();
sl@0
   189
	TheLock.ReadLock();
sl@0
   190
sl@0
   191
	CreateThread(EFalse);
sl@0
   192
	CreateThread(ETrue);
sl@0
   193
	CreateThread(ETrue);
sl@0
   194
	CreateThread(EFalse);
sl@0
   195
	CreateThread(ETrue);
sl@0
   196
sl@0
   197
	TheLock.Unlock();
sl@0
   198
	WaitForThreadsToClose();
sl@0
   199
sl@0
   200
	TheLock.Close();
sl@0
   201
sl@0
   202
	Test(LogIndex == 15, __LINE__);
sl@0
   203
	const TInt expected[] = { ETrue, EFalse, ETrue, EFalse, ETrue, EFalse, ETrue, EFalse, ETrue, EFalse, EFalse, ETrue, EFalse, ETrue, ETrue };
sl@0
   204
	for (TInt index = 0; index < LogIndex; index++)
sl@0
   205
		{
sl@0
   206
		Test(LogReaders[index] == expected[index], __LINE__);
sl@0
   207
		}
sl@0
   208
	}
sl@0
   209
sl@0
   210
// Check that queuing multiple reads and writes on a lock with reader priority
sl@0
   211
// results in the correct type of client being released in the correct order
sl@0
   212
// (can' predict exact client order on multi-processor systems though)
sl@0
   213
void TestReaderPriority()
sl@0
   214
	{
sl@0
   215
	Test.Next(_L("Reader Priority"));
sl@0
   216
	TInt ret = TheLock.CreateLocal(RReadWriteLock::EReaderPriority);
sl@0
   217
	Test(ret == KErrNone, __LINE__);
sl@0
   218
	TheLock.WriteLock();
sl@0
   219
sl@0
   220
	Init();
sl@0
   221
	CreateThread(ETrue);
sl@0
   222
	CreateThread(ETrue);
sl@0
   223
	CreateThread(EFalse);
sl@0
   224
	CreateThread(ETrue);
sl@0
   225
	CreateThread(EFalse);
sl@0
   226
	CreateThread(ETrue);
sl@0
   227
	CreateThread(EFalse);
sl@0
   228
	CreateThread(ETrue);
sl@0
   229
	CreateThread(EFalse);
sl@0
   230
	CreateThread(ETrue);
sl@0
   231
sl@0
   232
	TheLock.Unlock();
sl@0
   233
	WaitForThreadsToClose();
sl@0
   234
	TheLock.WriteLock();
sl@0
   235
sl@0
   236
	CreateThread(EFalse);
sl@0
   237
	CreateThread(ETrue);
sl@0
   238
	CreateThread(ETrue);
sl@0
   239
	CreateThread(EFalse);
sl@0
   240
	CreateThread(ETrue);
sl@0
   241
sl@0
   242
	TheLock.Unlock();
sl@0
   243
	WaitForThreadsToClose();
sl@0
   244
sl@0
   245
	TheLock.Close();
sl@0
   246
sl@0
   247
	Test(LogIndex == 15, __LINE__);
sl@0
   248
	const TInt expected[] = { ETrue, ETrue, ETrue, ETrue, ETrue, ETrue, EFalse, EFalse, EFalse, EFalse, ETrue, ETrue, ETrue, EFalse, EFalse };
sl@0
   249
	for (TInt index = 0; index < LogIndex; index++)
sl@0
   250
		{
sl@0
   251
		Test(LogReaders[index] == expected[index], __LINE__);
sl@0
   252
		}
sl@0
   253
	}
sl@0
   254
sl@0
   255
void DoTestTryLock(TBool aWriterFirst)
sl@0
   256
	{
sl@0
   257
	TheLock.ReadLock();
sl@0
   258
sl@0
   259
		TBool tryLock = TheLock.TryWriteLock();
sl@0
   260
		Test(!tryLock, __LINE__);
sl@0
   261
sl@0
   262
			tryLock = TheLock.TryReadLock();
sl@0
   263
			Test(tryLock, __LINE__);
sl@0
   264
			TheLock.Unlock();
sl@0
   265
sl@0
   266
		Init();
sl@0
   267
		CreateThread(EFalse);
sl@0
   268
		tryLock = TheLock.TryReadLock();
sl@0
   269
		if (tryLock)
sl@0
   270
			{
sl@0
   271
			Test(!aWriterFirst, __LINE__);
sl@0
   272
			TheLock.Unlock();
sl@0
   273
			}
sl@0
   274
		else
sl@0
   275
			{
sl@0
   276
			Test(aWriterFirst, __LINE__);
sl@0
   277
			}
sl@0
   278
		tryLock = TheLock.TryWriteLock();
sl@0
   279
		Test(!tryLock, __LINE__);
sl@0
   280
sl@0
   281
	TheLock.Unlock();
sl@0
   282
	WaitForThreadsToClose();
sl@0
   283
sl@0
   284
	TheLock.WriteLock();
sl@0
   285
sl@0
   286
		tryLock = TheLock.TryReadLock();
sl@0
   287
		Test(!tryLock, __LINE__);
sl@0
   288
		tryLock = TheLock.TryWriteLock();
sl@0
   289
		Test(!tryLock, __LINE__);
sl@0
   290
sl@0
   291
	TheLock.Unlock();
sl@0
   292
	TheLock.Close();
sl@0
   293
	}
sl@0
   294
sl@0
   295
// Check that the TryReadLock and TryWriteLock functions block only when they
sl@0
   296
// should for the different types of priority
sl@0
   297
void TestTryLock()
sl@0
   298
	{
sl@0
   299
	Test.Next(_L("Try Lock"));
sl@0
   300
sl@0
   301
	TInt ret = TheLock.CreateLocal(RReadWriteLock::EWriterPriority);
sl@0
   302
	Test(ret == KErrNone, __LINE__);
sl@0
   303
	DoTestTryLock(ETrue);
sl@0
   304
sl@0
   305
	ret = TheLock.CreateLocal(RReadWriteLock::EAlternatePriority);
sl@0
   306
	Test(ret == KErrNone, __LINE__);
sl@0
   307
	DoTestTryLock(ETrue);
sl@0
   308
sl@0
   309
	ret = TheLock.CreateLocal(RReadWriteLock::EReaderPriority);
sl@0
   310
	Test(ret == KErrNone, __LINE__);
sl@0
   311
	DoTestTryLock(EFalse);
sl@0
   312
sl@0
   313
	TheLock.Close();
sl@0
   314
	}
sl@0
   315
sl@0
   316
void DoTestUpgrade(RReadWriteLock::TReadWriteLockPriority aPriority)
sl@0
   317
	{
sl@0
   318
	TInt ret = TheLock.CreateLocal(aPriority);
sl@0
   319
	Test(ret == KErrNone, __LINE__);
sl@0
   320
	TheLock.ReadLock();
sl@0
   321
sl@0
   322
	TBool success = TheLock.TryUpgradeReadLock();
sl@0
   323
	Test(success, __LINE__);
sl@0
   324
	TheLock.Unlock();
sl@0
   325
sl@0
   326
	TheLock.ReadLock();
sl@0
   327
	TheLock.ReadLock();
sl@0
   328
	success = TheLock.TryUpgradeReadLock();
sl@0
   329
	Test(!success, __LINE__);
sl@0
   330
	TheLock.Unlock();
sl@0
   331
	TheLock.Unlock();
sl@0
   332
sl@0
   333
	TheLock.ReadLock();
sl@0
   334
	Init();
sl@0
   335
	CreateThread(EFalse);
sl@0
   336
	success = TheLock.TryUpgradeReadLock();
sl@0
   337
	Test(success || !(aPriority == RReadWriteLock::EReaderPriority), __LINE__);
sl@0
   338
sl@0
   339
	TheLock.Unlock();
sl@0
   340
	WaitForThreadsToClose();
sl@0
   341
	TheLock.Close();
sl@0
   342
	}
sl@0
   343
sl@0
   344
// Check that upgrading a lock succeeds only when it should
sl@0
   345
void TestUpgrade()
sl@0
   346
	{
sl@0
   347
	Test.Next(_L("Upgrade Lock"));
sl@0
   348
sl@0
   349
	DoTestUpgrade(RReadWriteLock::EWriterPriority);
sl@0
   350
	DoTestUpgrade(RReadWriteLock::EAlternatePriority);
sl@0
   351
	DoTestUpgrade(RReadWriteLock::EReaderPriority);
sl@0
   352
	}
sl@0
   353
sl@0
   354
void DoTestDowngrade(RReadWriteLock::TReadWriteLockPriority aPriority)
sl@0
   355
	{
sl@0
   356
	TInt ret = TheLock.CreateLocal(aPriority);
sl@0
   357
	Test(ret == KErrNone, __LINE__);
sl@0
   358
	TheLock.WriteLock();
sl@0
   359
sl@0
   360
	Init();
sl@0
   361
	CreateThread(ETrue);
sl@0
   362
	CreateThread(EFalse);
sl@0
   363
	CreateThread(ETrue);
sl@0
   364
	CreateThread(EFalse);
sl@0
   365
sl@0
   366
	TheLock.DowngradeWriteLock();
sl@0
   367
sl@0
   368
	switch (aPriority)
sl@0
   369
		{
sl@0
   370
	case RReadWriteLock::EWriterPriority:
sl@0
   371
	case RReadWriteLock::EAlternatePriority:
sl@0
   372
		{
sl@0
   373
		Test(LogIndex == 0, __LINE__);
sl@0
   374
		break;
sl@0
   375
		}
sl@0
   376
	case RReadWriteLock::EReaderPriority:
sl@0
   377
		{
sl@0
   378
		WaitForThreadsToClose(2);
sl@0
   379
		Test(LogIndex == 2, __LINE__);
sl@0
   380
		Test(LogReaders[0], __LINE__);
sl@0
   381
		Test(LogReaders[1], __LINE__);
sl@0
   382
		break;
sl@0
   383
		}
sl@0
   384
		};
sl@0
   385
sl@0
   386
	CreateThread(ETrue);
sl@0
   387
	CreateThread(EFalse);
sl@0
   388
	CreateThread(ETrue);
sl@0
   389
	CreateThread(EFalse);
sl@0
   390
sl@0
   391
	TheLock.Unlock();
sl@0
   392
	WaitForThreadsToClose();
sl@0
   393
	TheLock.Close();
sl@0
   394
sl@0
   395
	Test(LogIndex == 8, __LINE__);
sl@0
   396
sl@0
   397
	switch (aPriority)
sl@0
   398
		{
sl@0
   399
	case RReadWriteLock::EWriterPriority:
sl@0
   400
		{
sl@0
   401
		const TInt expected[] = { EFalse, EFalse, EFalse, EFalse, ETrue, ETrue, ETrue, ETrue };
sl@0
   402
		for (TInt index = 0; index < LogIndex; index++)
sl@0
   403
			{
sl@0
   404
			Test(LogReaders[index] == expected[index], __LINE__);
sl@0
   405
			}
sl@0
   406
		break;
sl@0
   407
		}
sl@0
   408
	case RReadWriteLock::EAlternatePriority:
sl@0
   409
		{
sl@0
   410
		const TInt expected[] = { EFalse, ETrue, EFalse, ETrue, EFalse, ETrue, EFalse, ETrue };
sl@0
   411
		for (TInt index = 0; index < LogIndex; index++)
sl@0
   412
			{
sl@0
   413
			Test(LogReaders[index] == expected[index], __LINE__);
sl@0
   414
			}
sl@0
   415
		break;
sl@0
   416
		}
sl@0
   417
	case RReadWriteLock::EReaderPriority:
sl@0
   418
		{
sl@0
   419
		const TInt expected[] = { ETrue, ETrue, ETrue, ETrue, EFalse, EFalse, EFalse, EFalse };
sl@0
   420
		for (TInt index = 0; index < LogIndex; index++)
sl@0
   421
			{
sl@0
   422
			Test(LogReaders[index] == expected[index], __LINE__);
sl@0
   423
			}
sl@0
   424
		break;
sl@0
   425
		}
sl@0
   426
		};
sl@0
   427
	}
sl@0
   428
sl@0
   429
// Check that downgrading a lock succeeds only when it should
sl@0
   430
void TestDowngrade()
sl@0
   431
	{
sl@0
   432
	Test.Next(_L("Downgrade Lock"));
sl@0
   433
sl@0
   434
	DoTestDowngrade(RReadWriteLock::EWriterPriority);
sl@0
   435
	DoTestDowngrade(RReadWriteLock::EAlternatePriority);
sl@0
   436
	DoTestDowngrade(RReadWriteLock::EReaderPriority);
sl@0
   437
	}
sl@0
   438
sl@0
   439
TInt PanicEntryPoint(TAny* aArg)
sl@0
   440
	{
sl@0
   441
	switch (TInt(aArg))
sl@0
   442
		{
sl@0
   443
		case 0: // Check priority lower bound
sl@0
   444
			TheLock.CreateLocal(RReadWriteLock::TReadWriteLockPriority(RReadWriteLock::EWriterPriority-1));
sl@0
   445
			break;
sl@0
   446
		case 1: // Check priority upper bound
sl@0
   447
			TheLock.CreateLocal(RReadWriteLock::TReadWriteLockPriority(RReadWriteLock::EReaderPriority+1));
sl@0
   448
			break;
sl@0
   449
		case 2: // Check close while holding read lock
sl@0
   450
			TheLock.CreateLocal(RReadWriteLock::TReadWriteLockPriority(RReadWriteLock::EAlternatePriority));
sl@0
   451
			TheLock.ReadLock();
sl@0
   452
			TheLock.Close();
sl@0
   453
			break;
sl@0
   454
		case 3: // Check close while holding write lock
sl@0
   455
			TheLock.CreateLocal(RReadWriteLock::TReadWriteLockPriority(RReadWriteLock::EAlternatePriority));
sl@0
   456
			TheLock.WriteLock();
sl@0
   457
			TheLock.Close();
sl@0
   458
			break;
sl@0
   459
		case 4: // Check max readers
sl@0
   460
			TheLock.CreateLocal(RReadWriteLock::TReadWriteLockPriority(RReadWriteLock::EReaderPriority));
sl@0
   461
			{
sl@0
   462
			for (TInt count = 0; count < RReadWriteLock::EReadWriteLockClientCategoryLimit; count++)
sl@0
   463
				TheLock.ReadLock();
sl@0
   464
			}
sl@0
   465
			TheLock.ReadLock();
sl@0
   466
			break;
sl@0
   467
		case 5: // Check max pending readers
sl@0
   468
			TheLock.CreateLocal(RReadWriteLock::TReadWriteLockPriority(RReadWriteLock::EReaderPriority));
sl@0
   469
			TheLock.WriteLock();
sl@0
   470
			{
sl@0
   471
			TUint16* hackLock = (TUint16*)&TheLock;
sl@0
   472
			hackLock[2] = KMaxTUint16; // Hack readers pending field
sl@0
   473
			}
sl@0
   474
			TheLock.ReadLock();
sl@0
   475
			break;
sl@0
   476
		case 6: // Check max pending writers
sl@0
   477
			TheLock.CreateLocal(RReadWriteLock::TReadWriteLockPriority(RReadWriteLock::EReaderPriority));
sl@0
   478
			TheLock.ReadLock();
sl@0
   479
			{
sl@0
   480
			TUint16* hackLock = (TUint16*)&TheLock;
sl@0
   481
			hackLock[3] = KMaxTUint16; // Hack writers pending field
sl@0
   482
			}
sl@0
   483
			TheLock.WriteLock();
sl@0
   484
			break;
sl@0
   485
		case 7: // Check lock held when unlocking
sl@0
   486
			TheLock.CreateLocal(RReadWriteLock::TReadWriteLockPriority(RReadWriteLock::EAlternatePriority));
sl@0
   487
			TheLock.Unlock();
sl@0
   488
			break;
sl@0
   489
		case 8: // Check lock held when unlocking after read lock/unlock
sl@0
   490
			TheLock.CreateLocal(RReadWriteLock::TReadWriteLockPriority(RReadWriteLock::EAlternatePriority));
sl@0
   491
			TheLock.ReadLock();
sl@0
   492
			TheLock.Unlock();
sl@0
   493
			TheLock.Unlock();
sl@0
   494
			break;
sl@0
   495
		case 9: // Check lock held when unlocking after write lock/unlock
sl@0
   496
			TheLock.CreateLocal(RReadWriteLock::TReadWriteLockPriority(RReadWriteLock::EAlternatePriority));
sl@0
   497
			TheLock.WriteLock();
sl@0
   498
			TheLock.Unlock();
sl@0
   499
			TheLock.Unlock();
sl@0
   500
			break;
sl@0
   501
		default:
sl@0
   502
			return KErrNone;
sl@0
   503
		};
sl@0
   504
sl@0
   505
	return KErrNotSupported;
sl@0
   506
	}
sl@0
   507
sl@0
   508
TBool CreatePanicThread(TInt aTest)
sl@0
   509
	{
sl@0
   510
	User::SetJustInTime(EFalse);
sl@0
   511
	TBool finished = EFalse;
sl@0
   512
sl@0
   513
	RThread panicThread;
sl@0
   514
	TInt ret = panicThread.Create(KNullDesC, PanicEntryPoint, KDefaultStackSize, KMinHeapSize, KMinHeapSize, (TAny*)aTest, EOwnerThread);
sl@0
   515
	Test(ret == KErrNone, __LINE__);
sl@0
   516
	panicThread.Resume();
sl@0
   517
sl@0
   518
	TRequestStatus stat;
sl@0
   519
	panicThread.Logon(stat);
sl@0
   520
	User::WaitForRequest(stat);
sl@0
   521
	User::SetJustInTime(ETrue);
sl@0
   522
sl@0
   523
	if (panicThread.ExitType() == EExitPanic)
sl@0
   524
		{
sl@0
   525
		TInt panicValue = 0;
sl@0
   526
		switch (aTest)
sl@0
   527
			{
sl@0
   528
		case 0:
sl@0
   529
		case 1:
sl@0
   530
			panicValue = EReadWriteLockInvalidPriority;
sl@0
   531
			break;
sl@0
   532
		case 2:
sl@0
   533
		case 3:
sl@0
   534
			panicValue = EReadWriteLockStillPending;
sl@0
   535
			break;
sl@0
   536
		case 4:
sl@0
   537
		case 5:
sl@0
   538
		case 6:
sl@0
   539
			panicValue = EReadWriteLockTooManyClients;
sl@0
   540
			break;
sl@0
   541
		case 7:
sl@0
   542
		case 8:
sl@0
   543
		case 9:
sl@0
   544
			panicValue = EReadWriteLockBadLockState;
sl@0
   545
			break;
sl@0
   546
		default:
sl@0
   547
			Test(0, __LINE__);
sl@0
   548
			break;
sl@0
   549
			};
sl@0
   550
	
sl@0
   551
		Test(stat == panicValue, __LINE__);
sl@0
   552
		Test(panicThread.ExitReason() == panicValue, __LINE__);
sl@0
   553
		}
sl@0
   554
	else
sl@0
   555
		{
sl@0
   556
		Test(stat == KErrNone, __LINE__);
sl@0
   557
		finished = ETrue;
sl@0
   558
		}
sl@0
   559
sl@0
   560
	RTest::CloseHandleAndWaitForDestruction(panicThread);
sl@0
   561
	
sl@0
   562
	switch (aTest)
sl@0
   563
		{
sl@0
   564
		case 2: // Check close while holding read lock
sl@0
   565
		case 3: // Check close while holding write lock
sl@0
   566
			TheLock.Unlock();
sl@0
   567
			TheLock.Close();
sl@0
   568
			break;
sl@0
   569
		case 4: // Check max readers
sl@0
   570
			{
sl@0
   571
			for (TInt count = 0; count < RReadWriteLock::EReadWriteLockClientCategoryLimit; count++)
sl@0
   572
				TheLock.Unlock();
sl@0
   573
			}
sl@0
   574
			TheLock.Close();
sl@0
   575
			break;
sl@0
   576
		case 5: // Check max pending readers
sl@0
   577
		case 6: // Check max pending writers
sl@0
   578
			{
sl@0
   579
			TUint16* hackLock = (TUint16*)&TheLock;
sl@0
   580
			hackLock[2] = 0; // Reset readers pending field
sl@0
   581
			hackLock[3] = 0; // Reset writers pending field
sl@0
   582
			}
sl@0
   583
			TheLock.Unlock();
sl@0
   584
			TheLock.Close();
sl@0
   585
			break;
sl@0
   586
		case 7: // Check lock held when unlocking
sl@0
   587
		case 8: // Check lock held when unlocking after read lock/unlock
sl@0
   588
		case 9: // Check lock held when unlocking after write lock/unlock
sl@0
   589
			TheLock.Close();
sl@0
   590
			break;
sl@0
   591
		default:
sl@0
   592
			break;
sl@0
   593
		};
sl@0
   594
	return finished;
sl@0
   595
	}
sl@0
   596
sl@0
   597
// Check that the various asserts guarding invalid conditions can be reached
sl@0
   598
void TestPanics()
sl@0
   599
	{
sl@0
   600
	Test.Next(_L("Panics"));
sl@0
   601
sl@0
   602
	for (TInt testIndex = 0; !CreatePanicThread(testIndex); testIndex++) ;
sl@0
   603
	}
sl@0
   604
sl@0
   605
TInt E32Main()
sl@0
   606
    {
sl@0
   607
	Test.Title();
sl@0
   608
	Test.Start(_L("RReadWriteLock Testing"));
sl@0
   609
sl@0
   610
	TestCreation();
sl@0
   611
	TestWriterPriority();
sl@0
   612
	TestAlternatePriority();
sl@0
   613
	TestReaderPriority();
sl@0
   614
	TestTryLock();
sl@0
   615
	TestUpgrade();
sl@0
   616
	TestDowngrade();
sl@0
   617
	TestPanics();
sl@0
   618
sl@0
   619
	Test.End();
sl@0
   620
	return KErrNone;
sl@0
   621
    }
sl@0
   622
sl@0
   623