|
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 |