38 // |
38 // |
39 // |
39 // |
40 |
40 |
41 #define __E32TEST_EXTENSION__ |
41 #define __E32TEST_EXTENSION__ |
42 #include <e32test.h> |
42 #include <e32test.h> |
43 #include <u32std.h> |
43 #include <hal.h> |
|
44 #include <e32atomics.h> |
|
45 #include <u32hal.h> |
44 #include <e32svr.h> |
46 #include <e32svr.h> |
45 |
47 |
46 const TInt KMaxBufferSize=10; |
48 const TInt KMaxBufferSize=10; |
47 const TInt KMaxArraySize=10; |
49 const TInt KMaxArraySize=10; |
48 const TInt KNumProducerItems=100; |
50 const TInt KNumProducerItems=100; |
49 |
51 |
50 enum {EThread1ID=1,EThread2ID}; |
52 enum {EThread1ID=1,EThread2ID}; |
51 |
53 |
52 RTest test(_L("T_SEMUTX")); |
54 RTest test(_L("T_SEMUTX")); |
53 RMutex mutex; |
55 RMutex mutex; |
54 RCriticalSection criticalSn; |
56 RCriticalSection criticalSn; |
55 TInt thread1Count,thread2Count; |
57 TInt thread1Count,thread2Count; |
56 TInt arrayIndex; |
58 TInt arrayIndex; |
57 TInt array[KMaxArraySize]; |
59 TInt array[KMaxArraySize]; |
58 TInt consumerArray[KNumProducerItems]; |
60 TInt consumerArray[KNumProducerItems]; |
59 RSemaphore slotAvailable,itemAvailable; |
61 RSemaphore slotAvailable,itemAvailable; |
|
62 TBool doCpuLocking = EFalse; |
|
63 |
|
64 // return num of cpus in system |
|
65 TInt NumCpus() |
|
66 { |
|
67 TInt r = UserSvr::HalFunction(EHalGroupKernel, EKernelHalNumLogicalCpus, 0, 0); |
|
68 return r; |
|
69 } |
|
70 |
|
71 |
|
72 TInt LockCurrentThreadToCpu0(TBool aCallingIsMainTestThread = EFalse) |
|
73 { |
|
74 if (aCallingIsMainTestThread) |
|
75 { |
|
76 if (NumCpus() > 1) |
|
77 { |
|
78 doCpuLocking = ETrue; |
|
79 return UserSvr::HalFunction(EHalGroupKernel, EKernelHalLockThreadToCpu, 0, 0); |
|
80 } |
|
81 else |
|
82 { |
|
83 return KErrNone; |
|
84 } |
|
85 } |
|
86 return UserSvr::HalFunction(EHalGroupKernel, EKernelHalLockThreadToCpu, 0, 0); |
|
87 } |
|
88 |
|
89 TInt UnlockCurrentThreadToCpu0(TBool aCallingIsMainTestThread = EFalse) |
|
90 { |
|
91 if (aCallingIsMainTestThread) |
|
92 { |
|
93 if (NumCpus() > 1) |
|
94 { |
|
95 doCpuLocking = EFalse; |
|
96 return UserSvr::HalFunction(EHalGroupKernel, EKernelHalLockThreadToCpu, (TAny*) 0xffffffffu, 0); |
|
97 } |
|
98 else |
|
99 { |
|
100 return KErrNone; |
|
101 } |
|
102 } |
|
103 return UserSvr::HalFunction(EHalGroupKernel, EKernelHalLockThreadToCpu, (TAny*) 0xffffffffu, 0); |
|
104 } |
|
105 |
|
106 |
|
107 /****************************************************************************** |
|
108 * Random Number Generation |
|
109 ******************************************************************************/ |
|
110 void Random(TUint64& a) |
|
111 { |
|
112 TInt i; |
|
113 for (i=64; i>0; --i) |
|
114 { |
|
115 TUint64 x = a<<1; |
|
116 TUint64 y = x<<1; |
|
117 x^=y; |
|
118 a = (y>>1) | (x>>63); |
|
119 } |
|
120 } |
|
121 |
|
122 // Returns 256*log2(a/2^64) |
|
123 TInt Log2(TUint64 a) |
|
124 { |
|
125 const TUint64 KBit63 = UI64LIT(0x8000000000000000); |
|
126 TInt n = __e32_find_ms1_64(a); |
|
127 a <<= (63-n); |
|
128 n -= 64; |
|
129 TInt i; |
|
130 for (i=0; i<8; ++i) |
|
131 { |
|
132 a >>= 32; |
|
133 a *= a; |
|
134 n <<= 1; |
|
135 if (a & KBit63) |
|
136 { |
|
137 ++n; |
|
138 } |
|
139 else |
|
140 { |
|
141 a <<= 1; |
|
142 } |
|
143 } |
|
144 return n; |
|
145 } |
|
146 |
|
147 TUint32 ExpRV(TUint64 aU, TUint32 aMean, TUint32 aTick) |
|
148 { |
|
149 TInt n = -Log2(aU); |
|
150 TUint64 x = TUint64(n) * TUint64(aMean); |
|
151 x *= TUint64(22713); // 2^15 * ln2 |
|
152 TUint64 p(aTick); |
|
153 p <<= 22; |
|
154 x += p; |
|
155 p += p; |
|
156 x /= p; |
|
157 return I64LOW(x); |
|
158 } |
|
159 |
|
160 |
|
161 |
|
162 /*----------------------------------------------------------------------------*/ |
|
163 class MLock |
|
164 { |
|
165 public: |
|
166 enum {EPollable=1, ETimeoutAvail=2, ENestable=4, ELimit1=8, ELooseTimeout=16}; |
|
167 public: |
|
168 virtual TInt Flags()=0; |
|
169 virtual void Release()=0; |
|
170 virtual void Wait()=0; |
|
171 virtual void Signal()=0; |
|
172 virtual TInt Wait(TInt aTimeout); |
|
173 virtual TInt Poll(); |
|
174 }; |
|
175 |
|
176 TInt MLock::Wait(TInt) |
|
177 { return KErrNotSupported; } |
|
178 TInt MLock::Poll() |
|
179 { return KErrNotSupported; } |
|
180 |
|
181 /*----------------------------------------------------------------------------*/ |
|
182 class LockS : public MLock |
|
183 { |
|
184 public: |
|
185 LockS(); |
|
186 virtual TInt Flags(); |
|
187 virtual void Release(); |
|
188 virtual void Wait(); |
|
189 virtual void Signal(); |
|
190 virtual TInt Wait(TInt aTimeout); |
|
191 virtual TInt Poll(); |
|
192 public: |
|
193 RSemaphore iT; |
|
194 }; |
|
195 |
|
196 LockS::LockS() |
|
197 { test_KErrNone(iT.CreateLocal(1)); } |
|
198 TInt LockS::Flags() |
|
199 { return EPollable|ETimeoutAvail; } |
|
200 void LockS::Release() |
|
201 { iT.Close(); } |
|
202 void LockS::Wait() |
|
203 { iT.Wait(); } |
|
204 void LockS::Signal() |
|
205 { iT.Signal(); } |
|
206 TInt LockS::Wait(TInt aTimeout) |
|
207 { return iT.Wait(aTimeout); } |
|
208 TInt LockS::Poll() |
|
209 { return iT.Poll(); } |
|
210 |
|
211 /*----------------------------------------------------------------------------*/ |
|
212 class LockM : public MLock |
|
213 { |
|
214 public: |
|
215 LockM(); |
|
216 virtual TInt Flags(); |
|
217 virtual void Release(); |
|
218 virtual void Wait(); |
|
219 virtual void Signal(); |
|
220 virtual TInt Wait(TInt aTimeout); |
|
221 virtual TInt Poll(); |
|
222 public: |
|
223 RMutex iT; |
|
224 }; |
|
225 |
|
226 LockM::LockM() |
|
227 { test_KErrNone(iT.CreateLocal()); } |
|
228 TInt LockM::Flags() |
|
229 { return EPollable|ETimeoutAvail|ENestable|ELimit1; } |
|
230 void LockM::Release() |
|
231 { iT.Close(); } |
|
232 void LockM::Wait() |
|
233 { iT.Wait(); } |
|
234 void LockM::Signal() |
|
235 { iT.Signal(); } |
|
236 TInt LockM::Wait(TInt aTimeout) |
|
237 { return iT.Wait(aTimeout); } |
|
238 TInt LockM::Poll() |
|
239 { return iT.Poll(); } |
|
240 |
|
241 /*----------------------------------------------------------------------------*/ |
|
242 |
|
243 class LockFL : public MLock |
|
244 { |
|
245 public: |
|
246 LockFL(); |
|
247 virtual TInt Flags(); |
|
248 virtual void Release(); |
|
249 virtual void Wait(); |
|
250 virtual void Signal(); |
|
251 virtual TInt Wait(TInt aTimeout); |
|
252 virtual TInt Poll(); |
|
253 public: |
|
254 RFastLock iT; |
|
255 }; |
|
256 |
|
257 LockFL::LockFL() |
|
258 { test_KErrNone(iT.CreateLocal()); } |
|
259 TInt LockFL::Flags() |
|
260 { return ETimeoutAvail|EPollable|ELimit1|ELooseTimeout; } |
|
261 void LockFL::Release() |
|
262 { iT.Close(); } |
|
263 void LockFL::Wait() |
|
264 { iT.Wait(); } |
|
265 void LockFL::Signal() |
|
266 { iT.Signal(); } |
|
267 TInt LockFL::Wait(TInt aTimeout) |
|
268 { return iT.Wait(aTimeout); } |
|
269 TInt LockFL::Poll() |
|
270 { return iT.Poll(); } |
|
271 |
|
272 /*----------------------------------------------------------------------------*/ |
|
273 class LockCS : public MLock |
|
274 { |
|
275 public: |
|
276 LockCS(); |
|
277 virtual TInt Flags(); |
|
278 virtual void Release(); |
|
279 virtual void Wait(); |
|
280 virtual void Signal(); |
|
281 public: |
|
282 RCriticalSection iT; |
|
283 }; |
|
284 |
|
285 LockCS::LockCS() |
|
286 { test_KErrNone(iT.CreateLocal()); } |
|
287 TInt LockCS::Flags() |
|
288 { return ELimit1; } |
|
289 void LockCS::Release() |
|
290 { iT.Close(); } |
|
291 void LockCS::Wait() |
|
292 { iT.Wait(); } |
|
293 void LockCS::Signal() |
|
294 { iT.Signal(); } |
|
295 |
|
296 |
60 |
297 |
|
298 /*----------------------------------------------------------------------------*/ |
|
299 class LFSR |
|
300 { |
|
301 public: |
|
302 LFSR(TInt aBits, TInt aTap2, TInt aTap3=0, TInt aTap4=0); |
|
303 ~LFSR(); |
|
304 void Step(); |
|
305 void Step(TInt aSteps); |
|
306 TBool operator==(const LFSR& a) const; |
|
307 public: |
|
308 TUint32* iData; |
|
309 TInt iBits; |
|
310 TInt iTap2; |
|
311 TInt iTap3; |
|
312 TInt iTap4; |
|
313 TInt iNW; |
|
314 TInt iSh1; |
|
315 TInt iIx2; |
|
316 TInt iSh2; |
|
317 TInt iIx3; |
|
318 TInt iSh3; |
|
319 TInt iIx4; |
|
320 TInt iSh4; |
|
321 }; |
|
322 |
|
323 LFSR::LFSR(TInt aBits, TInt aTap2, TInt aTap3, TInt aTap4) |
|
324 { |
|
325 iBits = aBits; |
|
326 iTap2 = aTap2; |
|
327 iTap3 = aTap3; |
|
328 iTap4 = aTap4; |
|
329 iNW = (aBits + 31) >> 5; |
|
330 iData = (TUint32*)User::AllocZ(iNW*sizeof(TUint32)); |
|
331 test(iData!=0); |
|
332 iData[0] = 1; |
|
333 iSh1 = (aBits-1)&31; |
|
334 iIx2 = (iTap2-1)>>5; |
|
335 iSh2 = (iTap2-1)&31; |
|
336 if (iTap3) |
|
337 { |
|
338 iIx3 = (iTap3-1)>>5; |
|
339 iSh3 = (iTap3-1)&31; |
|
340 } |
|
341 else |
|
342 { |
|
343 iIx3 = -1; |
|
344 iSh3 = 0; |
|
345 } |
|
346 if (iTap4) |
|
347 { |
|
348 iIx4 = (iTap4-1)>>5; |
|
349 iSh4 = (iTap4-1)&31; |
|
350 } |
|
351 else |
|
352 { |
|
353 iIx4 = -1; |
|
354 iSh4 = 0; |
|
355 } |
|
356 } |
|
357 |
|
358 LFSR::~LFSR() |
|
359 { |
|
360 User::Free(iData); |
|
361 } |
|
362 |
|
363 void LFSR::Step(TInt aSteps) |
|
364 { |
|
365 while (aSteps--) |
|
366 Step(); |
|
367 } |
|
368 |
|
369 void LFSR::Step() |
|
370 { |
|
371 TUint32 b = iData[iNW-1]>>iSh1; |
|
372 b ^= (iData[iIx2]>>iSh2); |
|
373 if (iIx3>=0) |
|
374 b ^= (iData[iIx3]>>iSh3); |
|
375 if (iIx4>=0) |
|
376 b ^= (iData[iIx4]>>iSh4); |
|
377 b &= 1; |
|
378 TInt i; |
|
379 for (i=0; i<iNW; ++i) |
|
380 { |
|
381 TUint32 bb = iData[i] >> 31; |
|
382 iData[i] = (iData[i]<<1)|b; |
|
383 b = bb; |
|
384 } |
|
385 iData[iNW-1] &= ((2u<<iSh1)-1u); |
|
386 } |
|
387 |
|
388 TBool LFSR::operator==(const LFSR& a) const |
|
389 { |
|
390 if (iBits!=a.iBits || iTap2!=a.iTap2 || iTap3!=a.iTap3 || iTap4!=a.iTap4 || iNW!=a.iNW) |
|
391 return EFalse; |
|
392 if (iData==a.iData) |
|
393 return ETrue; |
|
394 if (memcompare((const TUint8*)iData, iNW, (const TUint8*)a.iData, a.iNW)) |
|
395 return EFalse; |
|
396 return ETrue; |
|
397 } |
|
398 |
|
399 |
|
400 |
|
401 /*----------------------------------------------------------------------------*/ |
61 class CStack |
402 class CStack |
62 { |
403 { |
63 public: |
404 public: |
64 CStack() {iCount=0;}; |
405 CStack() {iCount=0;}; |
65 void Push(TInt aItem) {iStack[iCount++]=aItem;}; |
406 void Push(TInt aItem) {iStack[iCount++]=aItem;}; |
207 criticalSn.Signal(); |
571 criticalSn.Signal(); |
208 } while (running); |
572 } while (running); |
209 return(KErrNone); |
573 return(KErrNone); |
210 } |
574 } |
211 |
575 |
212 struct SWaitSem |
576 |
213 { |
577 /*----------------------------------------------------------------------------*/ |
214 RSemaphore iSem; |
578 struct SWaitLock |
|
579 { |
|
580 enum {EDummy=-2, EPoll=-1, EInfinite=0}; |
|
581 |
|
582 static TInt WaitLockThread(TAny*); |
|
583 void Start(RThread& aT, TThreadPriority aP=EPriorityLess); |
|
584 void Wait(RThread& aT, TInt aResult); |
|
585 TInt DoTest2(RThread& aT, TInt aTimeout, TInt aResult, TThreadPriority aP=EPriorityLess); |
|
586 void Test2(); |
|
587 void TestSignalled(); |
|
588 void TestNotSignalled(); |
|
589 void TestState(); |
|
590 |
|
591 |
|
592 MLock* iLock; |
215 TInt iTimeout; |
593 TInt iTimeout; |
216 }; |
594 }; |
217 |
595 |
218 TInt WaitSemThread(TAny* a) |
596 TInt SWaitLock::WaitLockThread(TAny* a) |
219 { |
597 { |
220 SWaitSem& ws = *(SWaitSem*)a; |
598 |
221 return ws.iSem.Wait(ws.iTimeout); |
599 if (doCpuLocking) |
222 } |
600 { |
223 |
601 TInt r = LockCurrentThreadToCpu0(); |
224 void StartWaitSemThread(RThread& aT, SWaitSem& aW, TThreadPriority aP=EPriorityLess) |
602 if (KErrNone!=r) return r; |
225 { |
603 // Rendevous was requested |
226 TInt r = aT.Create(KNullDesC, &WaitSemThread, 0x1000, 0x1000, 0x1000, &aW); |
604 RThread::Rendezvous(KErrNone); |
|
605 } |
|
606 |
|
607 SWaitLock& w = *(SWaitLock*)a; |
|
608 TInt lfl = w.iLock->Flags(); |
|
609 TBool limit1 = lfl & MLock::ELimit1; |
|
610 TInt r; |
|
611 switch (w.iTimeout) |
|
612 { |
|
613 case EDummy: |
|
614 return KErrNone; |
|
615 case EPoll: |
|
616 r = w.iLock->Poll(); |
|
617 break; |
|
618 case EInfinite: |
|
619 w.iLock->Wait(); |
|
620 r = KErrNone; |
|
621 break; |
|
622 default: |
|
623 r = w.iLock->Wait(w.iTimeout); |
|
624 break; |
|
625 } |
|
626 if (limit1 && r==KErrNone) |
|
627 w.iLock->Signal(); |
|
628 return r; |
|
629 } |
|
630 |
|
631 void SWaitLock::Start(RThread& aT, TThreadPriority aP) |
|
632 { |
|
633 TRequestStatus st; |
|
634 TInt r = aT.Create(KNullDesC, &WaitLockThread, 0x1000, 0x1000, 0x1000, this); |
227 test_KErrNone(r); |
635 test_KErrNone(r); |
228 aT.SetPriority(aP); |
636 aT.SetPriority(aP); |
|
637 if (doCpuLocking) |
|
638 { |
|
639 aT.Rendezvous(st); |
|
640 } |
229 aT.Resume(); |
641 aT.Resume(); |
230 } |
642 if (doCpuLocking) |
231 |
643 { |
232 void WaitForWaitSemThread(RThread& aT, TInt aResult) |
644 User::WaitForRequest(st); |
|
645 test_KErrNone(st.Int()); |
|
646 } |
|
647 } |
|
648 |
|
649 void SWaitLock::Wait(RThread& aT, TInt aResult) |
233 { |
650 { |
234 TRequestStatus s; |
651 TRequestStatus s; |
235 aT.Logon(s); |
652 aT.Logon(s); |
236 User::WaitForRequest(s); |
653 User::WaitForRequest(s); |
237 test_Equal(EExitKill, aT.ExitType()); |
654 test_Equal(EExitKill, aT.ExitType()); |
238 test_Equal(aResult, aT.ExitReason()); |
655 test_Equal(aResult, aT.ExitReason()); |
239 test_Equal(aResult, s.Int()); |
656 test_Equal(aResult, s.Int()); |
240 CLOSE_AND_WAIT(aT); |
657 CLOSE_AND_WAIT(aT); |
241 } |
658 } |
242 |
659 |
243 TInt DummyThread(TAny*) |
660 TInt SWaitLock::DoTest2(RThread& aT, TInt aTimeout, TInt aResult, TThreadPriority aP) |
244 { |
661 { |
245 return 0; |
|
246 } |
|
247 |
|
248 void TestSemaphore2() |
|
249 { |
|
250 test.Start(_L("Test semaphore wait with timeout")); |
|
251 SWaitSem ws; |
|
252 RThread t; |
|
253 TTime initial; |
662 TTime initial; |
254 TTime final; |
663 TTime final; |
255 TInt elapsed=0; |
664 iTimeout = aTimeout; |
256 TInt r = ws.iSem.CreateLocal(0); |
665 initial.HomeTime(); |
|
666 Start(aT, aP); |
|
667 Wait(aT, aResult); |
|
668 final.HomeTime(); |
|
669 TInt elapsed = I64INT(final.Int64()-initial.Int64()); |
|
670 return elapsed; |
|
671 } |
|
672 |
|
673 void SWaitLock::TestSignalled() |
|
674 { |
|
675 TInt r = iLock->Poll(); |
|
676 if (r == KErrNotSupported) |
|
677 r = iLock->Wait(1); |
257 test_KErrNone(r); |
678 test_KErrNone(r); |
|
679 } |
|
680 |
|
681 void SWaitLock::TestNotSignalled() |
|
682 { |
|
683 TInt r = iLock->Poll(); |
|
684 if (r == KErrNotSupported) |
|
685 r = iLock->Wait(1); |
|
686 test_Equal(KErrTimedOut, r); |
|
687 } |
|
688 |
|
689 void SWaitLock::TestState() |
|
690 { |
|
691 if (iLock->Flags() & MLock::ELimit1) |
|
692 TestSignalled(); // not signalled afterwards |
|
693 else |
|
694 TestNotSignalled(); |
|
695 } |
|
696 |
|
697 void SWaitLock::Test2() |
|
698 { |
|
699 test.Start(_L("SWaitLock::Test2")); |
|
700 RThread t; |
|
701 RThread t2; |
|
702 TTime initial; |
|
703 TTime final; |
|
704 TInt elapsed = 0; |
|
705 TInt r = 0; |
|
706 TInt lfl = iLock->Flags(); |
|
707 TBool nestable = lfl & MLock::ENestable; |
|
708 TBool limit1 = lfl & MLock::ELimit1; |
|
709 TBool pollable = lfl & MLock::EPollable; |
|
710 TBool to = lfl & MLock::ETimeoutAvail; |
|
711 TBool lto = lfl & MLock::ELooseTimeout; |
258 |
712 |
259 RThread().SetPriority(EPriorityAbsoluteVeryLow); |
713 RThread().SetPriority(EPriorityAbsoluteVeryLow); |
260 TInt threadcount=0; |
714 TInt threadcount=0; |
|
715 iTimeout = EDummy; |
261 initial.HomeTime(); |
716 initial.HomeTime(); |
262 while (elapsed<1000000) |
717 while (elapsed<1000000) |
263 { |
718 { |
264 r = t.Create(KNullDesC, &DummyThread, 0x1000, NULL, NULL); |
719 Start(t, EPriorityMore); |
265 test_KErrNone(r); |
720 Wait(t, KErrNone); |
266 t.SetPriority(EPriorityMore); |
|
267 t.Resume(); |
|
268 t.Close(); |
|
269 ++threadcount; |
721 ++threadcount; |
270 final.HomeTime(); |
722 final.HomeTime(); |
271 elapsed = I64INT(final.Int64()-initial.Int64()); |
723 elapsed = I64INT(final.Int64()-initial.Int64()); |
272 } |
724 } |
273 RThread().SetPriority(EPriorityNormal); |
725 RThread().SetPriority(EPriorityNormal); |
274 test.Printf(_L("%d threads in 1 sec\n"),threadcount); |
726 test.Printf(_L("%d threads in 1 sec\n"),threadcount); |
275 TInt overhead = 1000000/threadcount; |
727 TInt overhead = 1000000/threadcount; |
276 test.Printf(_L("overhead = %dus\n"),overhead); |
728 test.Printf(_L("overhead = %dus\n"),overhead); |
277 |
729 |
278 ws.iTimeout=1000000; |
730 iLock->Wait(); |
279 initial.HomeTime(); |
731 |
280 StartWaitSemThread(t, ws); |
732 if (to) |
281 WaitForWaitSemThread(t, KErrTimedOut); |
733 { |
282 final.HomeTime(); |
734 elapsed = DoTest2(t, 1000000, KErrTimedOut); |
283 elapsed = I64INT(final.Int64()-initial.Int64()); |
735 test.Printf(_L("Time taken = %dus\n"), elapsed); |
284 test.Printf(_L("Time taken = %dus\n"), elapsed); |
736 test(elapsed>=900000+overhead && elapsed<1500000+overhead); |
285 test(elapsed>=900000+overhead && elapsed<1500000+overhead); |
737 elapsed = DoTest2(t, -99, KErrArgument); |
286 |
738 test.Printf(_L("Time taken = %dus\n"), elapsed); |
287 ws.iTimeout=-1; |
739 } |
288 initial.HomeTime(); |
740 |
289 StartWaitSemThread(t, ws); |
741 if (pollable) |
290 WaitForWaitSemThread(t, KErrArgument); |
742 { |
291 final.HomeTime(); |
743 test.Printf(_L("Testing Poll() function\n")); |
292 elapsed = I64INT(final.Int64()-initial.Int64()); |
744 r = iLock->Poll(); |
293 test.Printf(_L("Time taken = %dus\n"), elapsed); |
745 test_Equal((nestable ? KErrNone : KErrTimedOut), r); |
294 |
746 if (nestable) |
295 ws.iTimeout=2000000; |
747 { |
296 initial.HomeTime(); |
748 iTimeout=EPoll; |
297 StartWaitSemThread(t, ws); |
749 r = iLock->Poll(); |
298 User::After(1000000); |
750 test_KErrNone(r); |
299 ws.iSem.Signal(); |
751 iLock->Signal(); |
300 WaitForWaitSemThread(t, KErrNone); |
752 Start(t, EPriorityMore); |
301 final.HomeTime(); |
753 Wait(t, KErrTimedOut); |
302 elapsed = I64INT(final.Int64()-initial.Int64()); |
754 } |
303 test.Printf(_L("Time taken = %dus\n"), elapsed); |
755 iLock->Signal(); |
304 test(elapsed>=900000+overhead && elapsed<1500000+overhead); |
756 if (nestable) |
305 |
757 { |
306 ws.iTimeout=100000; |
758 iTimeout=EPoll; |
307 StartWaitSemThread(t, ws, EPriorityMore); |
759 r = iLock->Poll(); |
308 t.Suspend(); |
760 test_KErrNone(r); |
309 ws.iSem.Signal(); |
761 iLock->Signal(); |
310 User::After(200000); |
762 Start(t, EPriorityMore); |
311 t.Resume(); |
763 Wait(t, KErrTimedOut); |
312 WaitForWaitSemThread(t, KErrTimedOut); |
764 iLock->Signal(); |
313 test_KErrNone(ws.iSem.Wait(1)); |
765 Start(t, EPriorityMore); |
314 |
766 Wait(t, KErrNone); |
315 ws.iTimeout=100000; |
767 } |
316 StartWaitSemThread(t, ws, EPriorityMore); |
768 r = iLock->Poll(); |
317 t.Suspend(); |
769 test_KErrNone(r); |
318 ws.iSem.Signal(); |
770 if (!nestable) |
319 User::After(50000); |
771 { |
320 t.Resume(); |
772 r = iLock->Poll(); |
321 WaitForWaitSemThread(t, KErrNone); |
773 test_Equal(KErrTimedOut, r); |
322 test_Equal(KErrTimedOut, ws.iSem.Wait(1)); |
774 iLock->Signal(); |
323 |
775 if (!limit1) |
324 RThread t2; |
776 { |
325 ws.iTimeout=100000; |
777 iLock->Signal(); |
326 StartWaitSemThread(t, ws, EPriorityMuchMore); |
778 r = iLock->Poll(); |
327 StartWaitSemThread(t2, ws, EPriorityMore); |
779 test_KErrNone(r); |
328 t.Suspend(); |
780 } |
329 ws.iSem.Signal(); |
781 r = iLock->Poll(); |
330 test_Equal(EExitKill, t2.ExitType()); |
782 test_KErrNone(r); |
331 test_Equal(EExitPending, t.ExitType()); |
783 r = iLock->Poll(); |
332 t.Resume(); |
784 test_Equal(KErrTimedOut, r); |
333 WaitForWaitSemThread(t, KErrTimedOut); |
785 } |
334 WaitForWaitSemThread(t2, KErrNone); |
786 elapsed = DoTest2(t, EPoll, KErrTimedOut); |
335 test_Equal(KErrTimedOut, ws.iSem.Wait(1)); |
787 test.Printf(_L("Time taken = %dus\n"), elapsed); |
336 |
788 test(elapsed<=50000+3*overhead); |
337 ws.iTimeout=1000000; |
789 iLock->Signal(); |
338 initial.HomeTime(); |
790 elapsed = DoTest2(t, EPoll, KErrNone); |
339 StartWaitSemThread(t2, ws, EPriorityMore); |
791 test.Printf(_L("Time taken = %dus\n"), elapsed); |
340 StartWaitSemThread(t, ws, EPriorityMuchMore); |
792 test(elapsed<=50000+3*overhead); |
341 ws.iSem.Signal(); |
793 TestState(); |
342 WaitForWaitSemThread(t, KErrNone); |
794 iLock->Signal(); |
343 final.HomeTime(); |
795 r = LockCurrentThreadToCpu0(ETrue); |
344 elapsed = I64INT(final.Int64()-initial.Int64()); |
796 test_KErrNone(r); |
345 test.Printf(_L("Time taken = %dus\n"), elapsed); |
797 Start(t, EPriorityMuchMore); |
346 WaitForWaitSemThread(t2, KErrTimedOut); |
798 Start(t2, EPriorityMore); |
347 final.HomeTime(); |
799 test_Equal(EExitKill, t2.ExitType()); |
348 elapsed = I64INT(final.Int64()-initial.Int64()); |
800 test_Equal(EExitKill, t.ExitType()); |
349 test.Printf(_L("Time taken = %dus\n"), elapsed); |
801 Wait(t2, limit1 ? KErrNone : KErrTimedOut); |
350 test(elapsed>=900000+2*overhead && elapsed<1500000+2*overhead); |
802 Wait(t, KErrNone); |
351 |
803 r = UnlockCurrentThreadToCpu0(ETrue); |
352 ws.iTimeout=1000000; |
804 test_KErrNone(r); |
353 initial.HomeTime(); |
805 TestState(); |
354 StartWaitSemThread(t2, ws, EPriorityMore); |
806 } |
355 StartWaitSemThread(t, ws, EPriorityMuchMore); |
807 else |
356 WaitForWaitSemThread(t, KErrTimedOut); |
808 { |
357 final.HomeTime(); |
809 test.Printf(_L("Poll() function not supported\n")); |
358 elapsed = I64INT(final.Int64()-initial.Int64()); |
810 } |
359 test.Printf(_L("Time taken = %dus\n"), elapsed); |
811 |
360 WaitForWaitSemThread(t2, KErrTimedOut); |
812 if (to) |
361 final.HomeTime(); |
813 { |
362 elapsed = I64INT(final.Int64()-initial.Int64()); |
814 iTimeout=2000000; |
363 test.Printf(_L("Time taken = %dus\n"), elapsed); |
815 initial.HomeTime(); |
364 test(elapsed>=900000+2*overhead && elapsed<1500000+2*overhead); |
816 Start(t); |
365 |
817 User::After(1000000); |
366 ws.iTimeout=1000000; |
818 iLock->Signal(); |
367 initial.HomeTime(); |
819 Wait(t, KErrNone); |
368 StartWaitSemThread(t2, ws, EPriorityMore); |
820 final.HomeTime(); |
369 StartWaitSemThread(t, ws, EPriorityMuchMore); |
821 elapsed = I64INT(final.Int64()-initial.Int64()); |
370 t.Kill(299792458); |
822 test.Printf(_L("Time taken = %dus\n"), elapsed); |
371 WaitForWaitSemThread(t2, KErrTimedOut); |
823 test(elapsed>=900000+overhead && elapsed<1500000+overhead); |
372 WaitForWaitSemThread(t, 299792458); |
824 TestState(); |
373 final.HomeTime(); |
825 |
374 elapsed = I64INT(final.Int64()-initial.Int64()); |
826 r = LockCurrentThreadToCpu0(ETrue); |
375 test.Printf(_L("Time taken = %dus\n"), elapsed); |
827 test_KErrNone(r); |
376 test(elapsed>=900000+2*overhead && elapsed<1500000+2*overhead); |
828 |
377 |
829 if (!lto) |
378 ws.iTimeout=1000000; |
830 { |
379 initial.HomeTime(); |
831 iTimeout=100000; |
380 StartWaitSemThread(t, ws, EPriorityMore); |
832 Start(t, EPriorityMore); |
381 StartWaitSemThread(t2, ws, EPriorityMuchMore); |
833 t.Suspend(); |
382 test_Equal(EExitPending, t.ExitType()); |
834 iLock->Signal(); |
383 test_Equal(EExitPending, t2.ExitType()); |
835 User::After(200000); |
384 ws.iSem.Close(); |
836 t.Resume(); |
385 test_Equal(EExitKill, t.ExitType()); |
837 Wait(t, KErrTimedOut); |
386 test_Equal(EExitKill, t2.ExitType()); |
838 TestSignalled(); |
387 WaitForWaitSemThread(t2, KErrGeneral); |
839 |
388 WaitForWaitSemThread(t, KErrGeneral); |
840 iTimeout=100000; |
389 final.HomeTime(); |
841 Start(t, EPriorityMore); |
390 elapsed = I64INT(final.Int64()-initial.Int64()); |
842 t.Suspend(); |
391 test.Printf(_L("Time taken = %dus\n"), elapsed); |
843 iLock->Signal(); |
392 test(elapsed<=50000+3*overhead); |
844 User::After(50000); |
393 |
845 t.Resume(); |
|
846 Wait(t, KErrNone); |
|
847 TestState(); |
|
848 |
|
849 iTimeout=100000; |
|
850 Start(t, EPriorityMuchMore); |
|
851 Start(t2, EPriorityMore); |
|
852 t.Suspend(); |
|
853 iLock->Signal(); |
|
854 test_Equal(EExitKill, t2.ExitType()); |
|
855 test_Equal(EExitPending, t.ExitType()); |
|
856 t.Resume(); |
|
857 Wait(t, limit1 ? KErrNone : KErrTimedOut); |
|
858 Wait(t2, KErrNone); |
|
859 TestState(); |
|
860 } |
|
861 |
|
862 iTimeout=1000000; |
|
863 initial.HomeTime(); |
|
864 Start(t2, EPriorityMore); |
|
865 Start(t, EPriorityMuchMore); |
|
866 iLock->Signal(); |
|
867 Wait(t, KErrNone); |
|
868 final.HomeTime(); |
|
869 elapsed = I64INT(final.Int64()-initial.Int64()); |
|
870 test.Printf(_L("Time taken = %dus\n"), elapsed); |
|
871 Wait(t2, limit1 ? KErrNone : KErrTimedOut); |
|
872 final.HomeTime(); |
|
873 elapsed = I64INT(final.Int64()-initial.Int64()); |
|
874 test.Printf(_L("Time taken = %dus\n"), elapsed); |
|
875 if (!limit1) |
|
876 { |
|
877 test(elapsed>=900000+2*overhead && elapsed<1500000+2*overhead); |
|
878 } |
|
879 TestState(); |
|
880 |
|
881 iTimeout=1000000; |
|
882 initial.HomeTime(); |
|
883 Start(t2, EPriorityMore); |
|
884 Start(t, EPriorityMuchMore); |
|
885 Wait(t, KErrTimedOut); |
|
886 final.HomeTime(); |
|
887 elapsed = I64INT(final.Int64()-initial.Int64()); |
|
888 test.Printf(_L("Time taken = %dus\n"), elapsed); |
|
889 Wait(t2, KErrTimedOut); |
|
890 final.HomeTime(); |
|
891 elapsed = I64INT(final.Int64()-initial.Int64()); |
|
892 test.Printf(_L("Time taken = %dus\n"), elapsed); |
|
893 test(elapsed>=900000+2*overhead && elapsed<1500000+2*overhead); |
|
894 |
|
895 iTimeout=1000000; |
|
896 initial.HomeTime(); |
|
897 Start(t2, EPriorityMore); |
|
898 Start(t, EPriorityMuchMore); |
|
899 t.Kill(299792458); |
|
900 Wait(t2, KErrTimedOut); |
|
901 Wait(t, 299792458); |
|
902 final.HomeTime(); |
|
903 elapsed = I64INT(final.Int64()-initial.Int64()); |
|
904 test.Printf(_L("Time taken = %dus\n"), elapsed); |
|
905 test(elapsed>=900000+2*overhead && elapsed<1500000+2*overhead); |
|
906 |
|
907 iTimeout=1000000; |
|
908 initial.HomeTime(); |
|
909 Start(t, EPriorityMore); |
|
910 Start(t2, EPriorityMuchMore); |
|
911 test_Equal(EExitPending, t.ExitType()); |
|
912 test_Equal(EExitPending, t2.ExitType()); |
|
913 iLock->Release(); |
|
914 test_Equal(EExitKill, t.ExitType()); |
|
915 test_Equal(EExitKill, t2.ExitType()); |
|
916 Wait(t2, KErrGeneral); |
|
917 Wait(t, KErrGeneral); |
|
918 final.HomeTime(); |
|
919 elapsed = I64INT(final.Int64()-initial.Int64()); |
|
920 test.Printf(_L("Time taken = %dus\n"), elapsed); |
|
921 test(elapsed<=50000+3*overhead); |
|
922 r = UnlockCurrentThreadToCpu0(ETrue); |
|
923 test_KErrNone(r); |
|
924 } |
|
925 else |
|
926 { |
|
927 test.Printf(_L("Timed waits not supported\n")); |
|
928 iLock->Release(); |
|
929 } |
394 test.End(); |
930 test.End(); |
395 } |
931 } |
396 |
932 |
|
933 volatile TBool NoRepeat = EFalse; |
|
934 void TestPollTimeout() |
|
935 { |
|
936 SWaitLock w; |
|
937 do { |
|
938 test.Printf(_L("TestPollTimeout - RSemaphore\n")); |
|
939 LockS ls; |
|
940 w.iLock = &ls; |
|
941 w.Test2(); // Release()s ls |
|
942 } while(NoRepeat); |
|
943 do { |
|
944 test.Printf(_L("TestPollTimeout - RMutex\n")); |
|
945 LockM lm; |
|
946 w.iLock = &lm; |
|
947 w.Test2(); // Release()s lm |
|
948 } while(NoRepeat); |
|
949 do { |
|
950 test.Printf(_L("TestPollTimeout - RFastLock\n")); |
|
951 LockFL fl; |
|
952 w.iLock = &fl; |
|
953 w.Test2(); // Release()s fl |
|
954 } while(NoRepeat); |
|
955 } |
|
956 |
|
957 |
|
958 /*----------------------------------------------------------------------------*/ |
|
959 class CMXThreadGrp; |
|
960 |
|
961 struct SStats |
|
962 { |
|
963 SStats(); |
|
964 void Add(TInt aValue); |
|
965 void Add(const SStats& aS); |
|
966 TInt Count() const {return iN;} |
|
967 TInt Min() const; |
|
968 TInt Max() const; |
|
969 TInt Mean() const; |
|
970 |
|
971 TInt64 iSum; |
|
972 TInt iMin; |
|
973 TInt iMax; |
|
974 TInt iN; |
|
975 TInt iSp; |
|
976 }; |
|
977 |
|
978 SStats::SStats() |
|
979 { |
|
980 iSum = 0; |
|
981 iMax = KMinTInt; |
|
982 iMin = ~iMax; |
|
983 iN = 0; |
|
984 iSp = 0; |
|
985 } |
|
986 |
|
987 void SStats::Add(TInt aValue) |
|
988 { |
|
989 TInt64 v = aValue; |
|
990 iSum += v; |
|
991 ++iN; |
|
992 if (aValue > iMax) |
|
993 iMax = aValue; |
|
994 if (aValue < iMin) |
|
995 iMin = aValue; |
|
996 } |
|
997 |
|
998 void SStats::Add(const SStats& a) |
|
999 { |
|
1000 iN += a.iN; |
|
1001 iSum += a.iSum; |
|
1002 if (a.iMax > iMax) |
|
1003 iMax = a.iMax; |
|
1004 if (a.iMin < iMin) |
|
1005 iMin = a.iMin; |
|
1006 } |
|
1007 |
|
1008 TInt SStats::Min() const |
|
1009 {return iN ? iMin : 0;} |
|
1010 |
|
1011 TInt SStats::Max() const |
|
1012 {return iN ? iMax : 0;} |
|
1013 |
|
1014 TInt SStats::Mean() const |
|
1015 { |
|
1016 if (iN==0) |
|
1017 return 0; |
|
1018 return (TInt)(iSum/TInt64(iN)); |
|
1019 } |
|
1020 |
|
1021 TUint32 ticks_to_us(TUint32 aTicks, TUint32 aF) |
|
1022 { |
|
1023 TUint64 x = aTicks; |
|
1024 TUint64 f = aF; |
|
1025 x *= TUint64(1000000); |
|
1026 x += (f>>1); |
|
1027 x /= f; |
|
1028 return I64LOW(x); |
|
1029 } |
|
1030 |
|
1031 class CMXThread : public CBase |
|
1032 { |
|
1033 private: |
|
1034 CMXThread(); |
|
1035 ~CMXThread(); |
|
1036 static CMXThread* New(CMXThreadGrp* aG, TUint32 aId, TUint32 aL, TUint32 aD); |
|
1037 void Start(); |
|
1038 void Wait(); |
|
1039 TInt Construct(CMXThreadGrp* aG, TUint32 aId, TUint32 aL, TUint32 aD); |
|
1040 TInt Steps(); |
|
1041 TInt Action(); |
|
1042 TInt Run(); |
|
1043 static TInt ThreadFunc(TAny*); |
|
1044 void PrintStats(); |
|
1045 private: |
|
1046 TUint64 iSeed; |
|
1047 RThread iThread; |
|
1048 TRequestStatus iExitStatus; |
|
1049 CMXThreadGrp* iG; |
|
1050 LFSR* iDummyLfsr; |
|
1051 TUint32 iId; |
|
1052 TUint32 iLambda; |
|
1053 TUint32 iDummySteps; |
|
1054 TInt iTotalSteps; |
|
1055 TInt iIterations; |
|
1056 TInt iPolls; |
|
1057 TInt iPollFails; |
|
1058 SStats iStats; |
|
1059 SStats iTimeoutStats; |
|
1060 private: |
|
1061 friend class CMXThreadGrp; |
|
1062 }; |
|
1063 |
|
1064 class CMXThreadGrp : public CBase |
|
1065 { |
|
1066 public: |
|
1067 static CMXThreadGrp* New(MLock* aLock, TInt aNThreads, TUint32 aLambda, TUint32 aDummySteps, TUint32 aTime); |
|
1068 CMXThreadGrp(); |
|
1069 ~CMXThreadGrp(); |
|
1070 TBool Run(); |
|
1071 void PrintStats(); |
|
1072 private: |
|
1073 TInt Construct(MLock* aLock, TInt aNThreads, TUint32 aLambda, TUint32 aDummySteps, TUint32 aTime); |
|
1074 private: |
|
1075 TInt iNThreads; |
|
1076 CMXThread** iThreads; |
|
1077 MLock* iLock; |
|
1078 LFSR* iLfsr; |
|
1079 LFSR* iLfsr0; |
|
1080 TUint32 iNTickPeriod; |
|
1081 TUint32 iFCF; |
|
1082 TUint32 iNTicks; |
|
1083 TInt iTotalSteps; |
|
1084 TInt iIterations; |
|
1085 TInt iPolls; |
|
1086 TInt iPollFails; |
|
1087 SStats iStats; |
|
1088 SStats iTimeoutStats; |
|
1089 private: |
|
1090 friend class CMXThread; |
|
1091 }; |
|
1092 |
|
1093 CMXThread::CMXThread() |
|
1094 { |
|
1095 iThread.SetHandle(0); |
|
1096 } |
|
1097 |
|
1098 CMXThread::~CMXThread() |
|
1099 { |
|
1100 delete iDummyLfsr; |
|
1101 if (iThread.Handle()) |
|
1102 { |
|
1103 if (iThread.ExitType() == EExitPending) |
|
1104 { |
|
1105 iThread.Kill(0); |
|
1106 Wait(); |
|
1107 } |
|
1108 CLOSE_AND_WAIT(iThread); |
|
1109 } |
|
1110 } |
|
1111 |
|
1112 void CMXThread::PrintStats() |
|
1113 { |
|
1114 test.Printf(_L("Thread %d:\n"), iId); |
|
1115 test.Printf(_L(" ST:%10d IT:%10d P:%10d PF:%10d TO:%10d\n"), iTotalSteps, iIterations, iPolls, iPollFails, iTimeoutStats.Count()); |
|
1116 TUint32 min, max, mean; |
|
1117 min = ticks_to_us(iStats.Min(), iG->iFCF); |
|
1118 max = ticks_to_us(iStats.Max(), iG->iFCF); |
|
1119 mean = ticks_to_us(iStats.Mean(), iG->iFCF); |
|
1120 test.Printf(_L(" Lock acquire times MIN %10d MAX %10d AVG %10d\n"), min, max, mean); |
|
1121 min = ticks_to_us(iTimeoutStats.Min(), iG->iFCF); |
|
1122 max = ticks_to_us(iTimeoutStats.Max(), iG->iFCF); |
|
1123 mean = ticks_to_us(iTimeoutStats.Mean(), iG->iFCF); |
|
1124 test.Printf(_L(" Lock timeout times MIN %10d MAX %10d AVG %10d\n"), min, max, mean); |
|
1125 } |
|
1126 |
|
1127 TInt CMXThread::Construct(CMXThreadGrp* aG, TUint32 aId, TUint32 aL, TUint32 aD) |
|
1128 { |
|
1129 iG = aG; |
|
1130 iId = aId; |
|
1131 iLambda = aL; |
|
1132 iDummySteps = aD; |
|
1133 iSeed = iId + 1; |
|
1134 iDummyLfsr = new LFSR(785,693); |
|
1135 if (!iDummyLfsr) |
|
1136 return KErrNoMemory; |
|
1137 TBuf<16> name = _L("TSThrd"); |
|
1138 name.AppendNum(iId); |
|
1139 TInt r = iThread.Create(name, &ThreadFunc, 0x1000, NULL, this); |
|
1140 if (r!=KErrNone) |
|
1141 return r; |
|
1142 iThread.Logon(iExitStatus); |
|
1143 if (iExitStatus != KRequestPending) |
|
1144 { |
|
1145 iThread.Kill(0); |
|
1146 iThread.Close(); |
|
1147 iThread.SetHandle(0); |
|
1148 return iExitStatus.Int(); |
|
1149 } |
|
1150 iThread.SetPriority(EPriorityLess); |
|
1151 return KErrNone; |
|
1152 } |
|
1153 |
|
1154 CMXThread* CMXThread::New(CMXThreadGrp* aG, TUint32 aId, TUint32 aL, TUint32 aD) |
|
1155 { |
|
1156 CMXThread* p = new CMXThread; |
|
1157 if (p) |
|
1158 { |
|
1159 TInt r = p->Construct(aG, aId, aL, aD); |
|
1160 if (r != KErrNone) |
|
1161 { |
|
1162 delete p; |
|
1163 p = 0; |
|
1164 } |
|
1165 } |
|
1166 return p; |
|
1167 } |
|
1168 |
|
1169 void CMXThread::Start() |
|
1170 { |
|
1171 iThread.Resume(); |
|
1172 } |
|
1173 |
|
1174 void CMXThread::Wait() |
|
1175 { |
|
1176 User::WaitForRequest(iExitStatus); |
|
1177 } |
|
1178 |
|
1179 TInt CMXThread::ThreadFunc(TAny* aPtr) |
|
1180 { |
|
1181 CMXThread& a = *(CMXThread*)aPtr; |
|
1182 return a.Run(); |
|
1183 } |
|
1184 |
|
1185 TInt CMXThread::Steps() |
|
1186 { |
|
1187 Random(iSeed); |
|
1188 return ExpRV(iSeed, iLambda, 1); |
|
1189 } |
|
1190 |
|
1191 TInt CMXThread::Action() |
|
1192 { |
|
1193 Random(iSeed); |
|
1194 return I64LOW(iSeed)%3; |
|
1195 } |
|
1196 |
|
1197 TInt CMXThread::Run() |
|
1198 { |
|
1199 MLock* lock = iG->iLock; |
|
1200 LFSR* lfsr = iG->iLfsr; |
|
1201 TInt lfl = lock->Flags(); |
|
1202 TBool pollable = lfl & MLock::EPollable; |
|
1203 TBool to = lfl & MLock::ETimeoutAvail; |
|
1204 TUint32 start_time = User::NTickCount(); |
|
1205 TInt r; |
|
1206 |
|
1207 FOREVER |
|
1208 { |
|
1209 TUint32 now = User::NTickCount(); |
|
1210 if (now - start_time >= iG->iNTicks) |
|
1211 break; |
|
1212 ++iIterations; |
|
1213 iDummyLfsr->Step(iDummySteps); |
|
1214 TInt action = Action(); |
|
1215 TInt steps = Steps(); |
|
1216 TUint32 initial = User::FastCounter(); |
|
1217 if (action==2 && to) |
|
1218 { |
|
1219 r = lock->Wait(1000); |
|
1220 if (r!=KErrNone) |
|
1221 { |
|
1222 TUint32 final = User::FastCounter(); |
|
1223 TInt elapsed = TInt(final - initial); |
|
1224 iTimeoutStats.Add(elapsed); |
|
1225 } |
|
1226 } |
|
1227 else if (action==1 && pollable) |
|
1228 { |
|
1229 ++iPolls; |
|
1230 r = lock->Poll(); |
|
1231 if (r!=KErrNone) |
|
1232 ++iPollFails; |
|
1233 } |
|
1234 else |
|
1235 { |
|
1236 lock->Wait(); |
|
1237 r = KErrNone; |
|
1238 } |
|
1239 if (r == KErrNone) |
|
1240 { |
|
1241 TUint32 final = User::FastCounter(); |
|
1242 lfsr->Step(steps); |
|
1243 lock->Signal(); |
|
1244 TInt elapsed = TInt(final - initial); |
|
1245 iTotalSteps += steps; |
|
1246 iStats.Add(elapsed); |
|
1247 } |
|
1248 } |
|
1249 |
|
1250 return KErrNone; |
|
1251 } |
|
1252 |
|
1253 CMXThreadGrp* CMXThreadGrp::New(MLock* aLock, TInt aNThreads, TUint32 aLambda, TUint32 aDummySteps, TUint32 aTime) |
|
1254 { |
|
1255 CMXThreadGrp* p = new CMXThreadGrp; |
|
1256 if (p) |
|
1257 { |
|
1258 TInt r = p->Construct(aLock, aNThreads, aLambda, aDummySteps, aTime); |
|
1259 if (r != KErrNone) |
|
1260 { |
|
1261 delete p; |
|
1262 p = 0; |
|
1263 } |
|
1264 } |
|
1265 return p; |
|
1266 } |
|
1267 |
|
1268 CMXThreadGrp::CMXThreadGrp() |
|
1269 { |
|
1270 } |
|
1271 |
|
1272 TInt CMXThreadGrp::Construct(MLock* aLock, TInt aNThreads, TUint32 aLambda, TUint32 aDummySteps, TUint32 aTime) |
|
1273 { |
|
1274 iNThreads = aNThreads; |
|
1275 iLock = aLock; |
|
1276 TInt r = HAL::Get(HAL::EFastCounterFrequency, (TInt&)iFCF); |
|
1277 if (r!=KErrNone) |
|
1278 return r; |
|
1279 r = HAL::Get(HAL::ENanoTickPeriod, (TInt&)iNTickPeriod); |
|
1280 if (r!=KErrNone) |
|
1281 return r; |
|
1282 iNTicks = (aTime+iNTickPeriod-1)/iNTickPeriod; |
|
1283 iLfsr = new LFSR(785,693); |
|
1284 iLfsr0 = new LFSR(785,693); |
|
1285 if (!iLfsr || !iLfsr0) |
|
1286 return KErrNoMemory; |
|
1287 iThreads = (CMXThread**)User::AllocZ(iNThreads*sizeof(CMXThread*)); |
|
1288 if (!iThreads) |
|
1289 return KErrNoMemory; |
|
1290 TInt i; |
|
1291 for (i=0; i<iNThreads; ++i) |
|
1292 { |
|
1293 iThreads[i] = CMXThread::New(this, i, aLambda, aDummySteps); |
|
1294 if (!iThreads[i]) |
|
1295 return KErrNoMemory; |
|
1296 } |
|
1297 return KErrNone; |
|
1298 } |
|
1299 |
|
1300 CMXThreadGrp::~CMXThreadGrp() |
|
1301 { |
|
1302 delete iLfsr; |
|
1303 delete iLfsr0; |
|
1304 if (iThreads) |
|
1305 { |
|
1306 TInt i; |
|
1307 for (i=0; i<iNThreads; ++i) |
|
1308 delete iThreads[i]; |
|
1309 } |
|
1310 User::Free(iThreads); |
|
1311 } |
|
1312 |
|
1313 TBool CMXThreadGrp::Run() |
|
1314 { |
|
1315 TInt i; |
|
1316 test.Printf(_L("Starting test with N=%d L=%d D=%d T=%d\n"), iNThreads, iThreads[0]->iLambda, iThreads[0]->iDummySteps, iNTicks); |
|
1317 for (i=0; i<iNThreads; ++i) |
|
1318 iThreads[i]->Start(); |
|
1319 for (i=0; i<iNThreads; ++i) |
|
1320 iThreads[i]->Wait(); |
|
1321 for (i=0; i<iNThreads; ++i) |
|
1322 { |
|
1323 iTotalSteps += iThreads[i]->iTotalSteps; |
|
1324 iIterations += iThreads[i]->iIterations; |
|
1325 iPolls += iThreads[i]->iPolls; |
|
1326 iPollFails += iThreads[i]->iPollFails; |
|
1327 iStats.Add(iThreads[i]->iStats); |
|
1328 iTimeoutStats.Add(iThreads[i]->iTimeoutStats); |
|
1329 } |
|
1330 test.Printf(_L("Total LFSR steps %d\n"), iTotalSteps); |
|
1331 iLfsr0->Step(iTotalSteps); |
|
1332 TBool ok = (*iLfsr == *iLfsr0); |
|
1333 return ok; |
|
1334 } |
|
1335 |
|
1336 void CMXThreadGrp::PrintStats() |
|
1337 { |
|
1338 TInt i; |
|
1339 for (i=0; i<iNThreads; ++i) |
|
1340 { |
|
1341 iThreads[i]->PrintStats(); |
|
1342 } |
|
1343 test.Printf(_L("TOTALS:\n")); |
|
1344 test.Printf(_L(" ST:%10d IT:%10d P:%10d PF:%10d TO:%10d\n"), iTotalSteps, iIterations, iPolls, iPollFails, iTimeoutStats.Count()); |
|
1345 TUint32 min, max, mean; |
|
1346 min = ticks_to_us(iStats.Min(), iFCF); |
|
1347 max = ticks_to_us(iStats.Max(), iFCF); |
|
1348 mean = ticks_to_us(iStats.Mean(), iFCF); |
|
1349 test.Printf(_L(" Lock acquire times MIN %10d MAX %10d AVG %10d\n"), min, max, mean); |
|
1350 min = ticks_to_us(iTimeoutStats.Min(), iFCF); |
|
1351 max = ticks_to_us(iTimeoutStats.Max(), iFCF); |
|
1352 mean = ticks_to_us(iTimeoutStats.Mean(), iFCF); |
|
1353 test.Printf(_L(" Lock timeout times MIN %10d MAX %10d AVG %10d\n"), min, max, mean); |
|
1354 } |
|
1355 |
|
1356 TUint32 Calibrate() |
|
1357 { |
|
1358 TUint32 fcf; |
|
1359 TInt r = HAL::Get(HAL::EFastCounterFrequency, (TInt&)fcf); |
|
1360 test_KErrNone(r); |
|
1361 LFSR* d = new LFSR(785,693); |
|
1362 test(d!=0); |
|
1363 TInt steps = 2; |
|
1364 TUint32 ticks = fcf/10; |
|
1365 TUint32 elapsed; |
|
1366 FOREVER |
|
1367 { |
|
1368 TUint32 h0 = User::FastCounter(); |
|
1369 d->Step(steps); |
|
1370 TUint32 h1 = User::FastCounter(); |
|
1371 elapsed = h1 - h0; |
|
1372 if (elapsed > ticks) |
|
1373 break; |
|
1374 steps *= 2; |
|
1375 } |
|
1376 delete d; |
|
1377 test.Printf(_L("%d steps in %d fast ticks\n"), steps, elapsed); |
|
1378 TUint64 x = elapsed; |
|
1379 TUint64 s = steps; |
|
1380 TUint64 y = fcf; |
|
1381 y /= x; |
|
1382 s *= y; // steps per second |
|
1383 TUint32 res = I64LOW(s); |
|
1384 test.Printf(_L("%d steps per second\n"), res); |
|
1385 return res; |
|
1386 } |
|
1387 |
|
1388 void DoTMX(MLock* aLock, TInt aNThreads, TUint32 aLambda, TUint32 aDummySteps, TUint32 aTime, TBool aShouldFail=EFalse) |
|
1389 { |
|
1390 CMXThreadGrp* g = CMXThreadGrp::New(aLock, aNThreads, aLambda, aDummySteps, aTime); |
|
1391 test(g!=0); |
|
1392 TBool ok = g->Run(); |
|
1393 if (aShouldFail) |
|
1394 { |
|
1395 test(!ok); |
|
1396 } |
|
1397 else |
|
1398 { |
|
1399 test(ok); |
|
1400 } |
|
1401 g->PrintStats(); |
|
1402 delete g; |
|
1403 } |
|
1404 |
|
1405 void DoTMX(MLock* aLock, TUint32 aLambda, TUint32 aDummySteps, TUint32 aTime) |
|
1406 { |
|
1407 TInt n; |
|
1408 for (n=1; n<=4; ++n) |
|
1409 { |
|
1410 TUint32 l = (n<2) ? aLambda : (aLambda/(n-1)); |
|
1411 DoTMX(aLock, n, l, aDummySteps, aTime); |
|
1412 } |
|
1413 aLock->Release(); |
|
1414 } |
|
1415 |
|
1416 |
|
1417 void TestMutualExclusion() |
|
1418 { |
|
1419 TInt ntp; |
|
1420 TInt r = HAL::Get(HAL::ENanoTickPeriod, ntp); |
|
1421 test_KErrNone(r); |
|
1422 test.Printf(_L("Nanokernel tick period = %dus\n"), ntp); |
|
1423 TUint32 sps = Calibrate(); |
|
1424 TUint32 lambda = sps/2000; |
|
1425 TUint32 dummy = sps/2000; |
|
1426 TUint32 time = 5000000; |
|
1427 do { |
|
1428 test.Printf(_L("TestMutualExclusion - RSemaphore\n")); |
|
1429 LockS ls; |
|
1430 DoTMX(&ls, lambda, dummy, time); |
|
1431 } while(NoRepeat); |
|
1432 do { |
|
1433 test.Printf(_L("TestMutualExclusion - RSemaphore init=2\n")); |
|
1434 LockS ls2; |
|
1435 ls2.Signal(); // count=2 |
|
1436 DoTMX(&ls2, 4, lambda, dummy, time, ETrue); |
|
1437 } while(NoRepeat); |
|
1438 do { |
|
1439 test.Printf(_L("TestMutualExclusion - RMutex\n")); |
|
1440 LockM lm; |
|
1441 DoTMX(&lm, lambda, dummy, time); |
|
1442 } while(NoRepeat); |
|
1443 do { |
|
1444 test.Printf(_L("TestMutualExclusion - RFastLock\n")); |
|
1445 LockFL fl; |
|
1446 DoTMX(&fl, lambda, dummy, time); |
|
1447 } while(NoRepeat); |
|
1448 do { |
|
1449 test.Printf(_L("TestMutualExclusion - RCriticalSection\n")); |
|
1450 LockCS cs; |
|
1451 DoTMX(&cs, lambda, dummy, time); |
|
1452 } while(NoRepeat); |
|
1453 } |
|
1454 |
|
1455 |
|
1456 |
|
1457 |
|
1458 /*----------------------------------------------------------------------------*/ |
397 void TestSemaphore() |
1459 void TestSemaphore() |
398 { |
1460 { |
399 /*********** TO DO ************/ |
1461 /*********** TO DO ************/ |
400 // Check it panics if the count <0 |
1462 // Check it panics if the count <0 |
401 |
1463 |