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