First public contribution.
1 // Copyright (c) 2007-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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // e32test\nkernsa\testdfc.cpp
18 #include <nktest/nkutils.h>
21 #define iNThreadBaseSpare7 iSpare7
25 extern "C" TUint32 set_bit0_if_nonnull(TUint32&);
26 extern "C" void flip_bit0(TUint32&);
27 extern "C" TUint32 swap_out_if_bit0_clear(TUint32&);
30 class TAddDfc : public TGenericIPI
32 class TAddDfc : public NTimer
37 TDfc* Add(TDfc* aDfc, TUint32 aCpuMask);
38 static TAddDfc* New();
40 static void Isr(TGenericIPI*);
42 static void TimerCallBack(TAny*);
43 void WaitCompletion();
53 : NTimer(&TimerCallBack, this),
59 TAddDfc* TAddDfc::New()
61 TAddDfc* p = new TAddDfc;
67 void TAddDfc::Isr(TGenericIPI* a)
69 void TAddDfc::TimerCallBack(TAny* a)
72 TAddDfc& adder = *(TAddDfc*)a;
73 TDfc* dfc = (TDfc*)__e32_atomic_swp_ord_ptr(&adder.iDfc, 0);
78 TDfc* TAddDfc::Add(TDfc* aDfc, TUint32 aCpuMask)
80 TDfc* old = (TDfc*)__e32_atomic_swp_ord_ptr(&iDfc, aDfc);
82 Queue(&Isr, aCpuMask);
91 void TAddDfc::WaitCompletion()
98 class TTestDfc : public TDfc
102 TTestDfc(TUint aId, TDfcQue* aQ, TInt aPri);
103 static void Run(TAny* aPtr);
105 static void CheckEmpty(TInt aLine);
106 static void CheckFirstEntry(TInt aLine, TUint32 aCpu, TUint32 aContext, TDfcQue* aQ, TUint32 aId);
108 static CircBuf* Buffer;
109 static volatile TBool Full;
110 static volatile TUint32 Last;
112 enum {EBufferSlots=1024};
115 #define CHECK_EMPTY() TTestDfc::CheckEmpty(__LINE__)
116 #define CHECK_FIRST_ENTRY(cpu, ctx, q, id) TTestDfc::CheckFirstEntry(__LINE__, cpu, ctx, q, id)
118 CircBuf* TTestDfc::Buffer;
119 volatile TBool TTestDfc::Full = FALSE;
120 volatile TUint32 TTestDfc::Last;
122 TTestDfc::TTestDfc(TUint aId)
123 : TDfc(&Run, (TAny*)aId)
127 TTestDfc::TTestDfc(TUint aId, TDfcQue* aQ, TInt aPri)
128 : TDfc(&Run, (TAny*)aId, aQ, aPri)
132 void TTestDfc::Run(TAny* aPtr)
134 TUint32 id = (TUint32)aPtr;
136 TUint32 ctx = NKern::CurrentContext();
137 TUint32 cpu = NKern::CurrentCpu();
138 if (ctx == NKern::EThread)
140 NThread* t = NKern::CurrentThread();
141 tid = t->iNThreadBaseSpare7;
143 TUint32 x = (cpu<<24) | (ctx<<16) | (tid<<8) | id;
144 TInt r = Buffer->TryPut(x);
150 void TTestDfc::CheckEmpty(TInt aLine)
152 TInt c = Buffer->Count();
157 TEST_PRINT3("Line %d Buffer not empty C:%d X:%08x", aLine, c, x);
161 void TTestDfc::CheckFirstEntry(TInt aLine, TUint32 aCpu, TUint32 aContext, TDfcQue* aQ, TUint32 aId)
163 TUint32 tid = aQ ? aQ->iThread->iNThreadBaseSpare7 : 0;
164 TUint32 expected = (aCpu<<24) | (aContext<<16) | (tid << 8) | aId;
166 TInt r = Buffer->TryGet(x);
169 TEST_PRINT2("Line %d Buffer empty, Expected %08x", aLine, expected);
171 else if (x != expected)
173 TEST_PRINT3("Line %d Got %08x Expected %08x", aLine, x, expected);
177 class TPauseIDFC : public TDfc
181 void Pause(TInt aCpu);
183 static void Run(TAny*);
188 TPauseIDFC::TPauseIDFC()
194 void TPauseIDFC::Pause(TInt aCpu)
198 __e32_memory_barrier();
199 adder.Add(this, 1u<<aCpu);
200 adder.WaitCompletion();
205 void TPauseIDFC::Release()
207 __e32_atomic_store_ord32(&iFlag, 1);
210 void TPauseIDFC::Run(TAny* aPtr)
212 TPauseIDFC* p = (TPauseIDFC*)aPtr;
213 __e32_atomic_store_ord32(&p->iFlag, 0);
214 while (__e32_atomic_load_acq32(&p->iFlag) == 0)
218 class TPauseDFC : public TDfc
221 TPauseDFC(TDfcQue* aQ);
222 void Pause(TInt aWait=0);
225 static void Run(TAny*);
227 NFastSemaphore* volatile iSem;
231 TPauseDFC::TPauseDFC(TDfcQue* aQ)
232 : TDfc(&Run, this, aQ, 0),
237 void TPauseDFC::Pause(TInt aWait)
240 NFastSemaphore entrySem(0);
243 NKern::FSWait(&entrySem);
246 void TPauseDFC::BusyPause()
248 volatile TInt& flag = (volatile TInt&)iSem;
249 __e32_atomic_store_ord32(&flag, 0xfffffffe);
251 while (__e32_atomic_load_acq32(&flag) == 0xfffffffe)
255 void TPauseDFC::Release()
257 NFastSemaphore* s = (NFastSemaphore*)__e32_atomic_swp_ord_ptr(&iSem, 0);
260 volatile TInt& flag = (volatile TInt&)iSem;
261 __e32_atomic_store_ord32(&flag, 0);
267 void TPauseDFC::Run(TAny* aPtr)
269 TPauseDFC* p = (TPauseDFC*)aPtr;
270 volatile TInt& flag = (volatile TInt&)p->iSem;
274 __e32_memory_barrier();
280 NFastSemaphore exitSem(0);
281 NFastSemaphore* s = (NFastSemaphore*)__e32_atomic_swp_ord_ptr(&p->iSem, &exitSem);
284 nfcfspin(__microseconds_to_norm_fast_counter(10000));
285 NKern::Sleep(p->iWait);
288 NKern::FSWait(&exitSem);
294 TEST_PRINT("DFCTest1");
298 TDfcQue* q = CreateDfcQ("DfcQ0", 1, cpu);
300 q = CreateDfcQ("DfcQ1", 32, cpu);
305 TBool QueueDfc(TDfc* aDfc, TInt aMode, TBool aExRet)
308 return !aExRet == !aDfc->Enque();
312 TInt cpu = aMode - 1;
313 adder.Add(aDfc, 1u<<cpu);
314 adder.WaitCompletion();
315 nfcfspin(__microseconds_to_norm_fast_counter(10000));
321 TBool ret = aDfc->Add();
323 return !aExRet == !ret;
328 #define QUEUE_DFC(dfc, mode, exret) TEST_RESULT(QueueDfc(dfc,mode,exret),"")
332 TEST_PRINT("DFCTest2");
333 TInt num_cpus = NKern::NumberOfCpus();
334 TInt this_cpu = NKern::CurrentCpu();
336 q = CreateDfcQ("DfcQ2", 1, this_cpu);
338 q->iThread->iNThreadBaseSpare7 = 1;
340 TTestDfc* d1 = new TTestDfc(1, q, 1);
342 TEST_RESULT(!d1->IsIDFC(), "");
343 TTestDfc* d2 = new TTestDfc(2, q, 2);
345 TEST_RESULT(!d2->IsIDFC(), "");
346 TTestDfc* d3 = new TTestDfc(3, q, 2);
348 TEST_RESULT(!d3->IsIDFC(), "");
349 TTestDfc* d4 = new TTestDfc(4, q, 3);
351 TEST_RESULT(!d4->IsIDFC(), "");
354 for (mode=-1; mode<=num_cpus; ++mode)
356 TEST_PRINT1("Mode %d", mode);
358 TEST_RESULT(!d1->Queued(), "");
359 QUEUE_DFC(d1, mode, TRUE);
360 TEST_RESULT(d1->Queued(), "");
361 QUEUE_DFC(d1, mode, FALSE);
362 TEST_RESULT(d1->Queued(), "");
363 QUEUE_DFC(d2, mode, TRUE);
364 QUEUE_DFC(d3, mode, TRUE);
365 QUEUE_DFC(d4, mode, TRUE);
368 CHECK_FIRST_ENTRY(this_cpu, NKern::EThread, q, 4);
369 CHECK_FIRST_ENTRY(this_cpu, NKern::EThread, q, 2);
370 CHECK_FIRST_ENTRY(this_cpu, NKern::EThread, q, 3);
371 CHECK_FIRST_ENTRY(this_cpu, NKern::EThread, q, 1);
373 QUEUE_DFC(d4, mode, TRUE);
374 QUEUE_DFC(d3, mode, TRUE);
375 QUEUE_DFC(d2, mode, TRUE);
376 QUEUE_DFC(d1, mode, TRUE);
379 CHECK_FIRST_ENTRY(this_cpu, NKern::EThread, q, 4);
380 CHECK_FIRST_ENTRY(this_cpu, NKern::EThread, q, 3);
381 CHECK_FIRST_ENTRY(this_cpu, NKern::EThread, q, 2);
382 CHECK_FIRST_ENTRY(this_cpu, NKern::EThread, q, 1);
384 QUEUE_DFC(d4, mode, TRUE);
385 QUEUE_DFC(d3, mode, TRUE);
386 QUEUE_DFC(d2, mode, TRUE);
387 QUEUE_DFC(d1, mode, TRUE);
388 TEST_RESULT(d4->Queued(), "");
389 TEST_RESULT(d4->Cancel(), "");
390 TEST_RESULT(!d4->Cancel(), "");
391 TEST_RESULT(!d4->Queued(), "");
394 CHECK_FIRST_ENTRY(this_cpu, NKern::EThread, q, 3);
395 CHECK_FIRST_ENTRY(this_cpu, NKern::EThread, q, 2);
396 CHECK_FIRST_ENTRY(this_cpu, NKern::EThread, q, 1);
398 QUEUE_DFC(d4, mode, TRUE);
399 QUEUE_DFC(d3, mode, TRUE);
400 QUEUE_DFC(d2, mode, TRUE);
401 QUEUE_DFC(d1, mode, TRUE);
402 TEST_RESULT(d3->Queued(), "");
403 TEST_RESULT(d3->Cancel(), "");
404 TEST_RESULT(!d3->Queued(), "");
407 CHECK_FIRST_ENTRY(this_cpu, NKern::EThread, q, 4);
408 CHECK_FIRST_ENTRY(this_cpu, NKern::EThread, q, 2);
409 CHECK_FIRST_ENTRY(this_cpu, NKern::EThread, q, 1);
411 QUEUE_DFC(d4, mode, TRUE);
412 QUEUE_DFC(d3, mode, TRUE);
413 QUEUE_DFC(d2, mode, TRUE);
414 QUEUE_DFC(d1, mode, TRUE);
415 TEST_RESULT(d3->Queued(), "");
416 TEST_RESULT(d2->Queued(), "");
417 TEST_RESULT(d3->Cancel(), "");
418 TEST_RESULT(d2->Cancel(), "");
419 TEST_RESULT(!d3->Queued(), "");
420 TEST_RESULT(!d2->Queued(), "");
423 CHECK_FIRST_ENTRY(this_cpu, NKern::EThread, q, 4);
424 CHECK_FIRST_ENTRY(this_cpu, NKern::EThread, q, 1);
426 QUEUE_DFC(d4, mode, TRUE);
427 QUEUE_DFC(d3, mode, TRUE);
428 QUEUE_DFC(d2, mode, TRUE);
429 QUEUE_DFC(d1, mode, TRUE);
430 TEST_RESULT(d3->Cancel(), "");
431 TEST_RESULT(d2->Cancel(), "");
432 TEST_RESULT(d4->Cancel(), "");
433 TEST_RESULT(d1->Cancel(), "");
437 QUEUE_DFC(d4, mode, TRUE);
438 QUEUE_DFC(d3, mode, TRUE);
439 QUEUE_DFC(d2, mode, TRUE);
440 QUEUE_DFC(d1, mode, TRUE);
441 TEST_RESULT(d1->Queued(), "");
442 TEST_RESULT(d3->Cancel(), "");
443 TEST_RESULT(d2->Cancel(), "");
444 TEST_RESULT(d4->Cancel(), "");
445 TEST_RESULT(d1->Cancel(), "");
446 TEST_RESULT(!d1->Queued(), "");
447 QUEUE_DFC(d1, mode, TRUE);
448 TEST_RESULT(d1->Queued(), "");
449 QUEUE_DFC(d1, mode, FALSE);
450 TEST_RESULT(d1->Queued(), "");
453 CHECK_FIRST_ENTRY(this_cpu, NKern::EThread, q, 1);
464 void DoDFCTest3(TInt aCpu)
466 TEST_PRINT1("DFCTest3 CPU %d", aCpu);
467 TInt num_cpus = NKern::NumberOfCpus();
468 TInt this_cpu = NKern::CurrentCpu();
469 TBool same_cpu = (aCpu==this_cpu);
471 q = CreateDfcQ("DfcQ2", 32, aCpu);
473 q->iThread->iNThreadBaseSpare7 = 1;
476 TTestDfc* d1 = new TTestDfc(1, q, 1);
478 TEST_RESULT(!d1->IsIDFC(), "");
479 TTestDfc* d2 = new TTestDfc(2, q, 2);
481 TEST_RESULT(!d2->IsIDFC(), "");
482 TTestDfc* d3 = new TTestDfc(3, q, 2);
484 TEST_RESULT(!d3->IsIDFC(), "");
485 TTestDfc* d4 = new TTestDfc(4, q, 3);
487 TEST_RESULT(!d4->IsIDFC(), "");
490 for (mode=-1; mode<=num_cpus; ++mode)
492 TEST_PRINT1("Mode %d", mode);
494 TEST_RESULT(!d1->Queued(), "");
495 QUEUE_DFC(d1, mode, TRUE);
497 while (d1->Queued()) {}
498 TEST_RESULT(!d1->Queued(), "");
499 QUEUE_DFC(d1, mode, TRUE);
501 while (d1->Queued()) {}
502 TEST_RESULT(!d1->Queued(), "");
503 QUEUE_DFC(d2, mode, TRUE);
505 while (d2->Queued()) {}
506 QUEUE_DFC(d3, mode, TRUE);
508 while (d3->Queued()) {}
509 QUEUE_DFC(d4, mode, TRUE);
511 while (d4->Queued()) {}
512 CHECK_FIRST_ENTRY(aCpu, NKern::EThread, q, 1);
513 CHECK_FIRST_ENTRY(aCpu, NKern::EThread, q, 1);
514 CHECK_FIRST_ENTRY(aCpu, NKern::EThread, q, 2);
515 CHECK_FIRST_ENTRY(aCpu, NKern::EThread, q, 3);
516 CHECK_FIRST_ENTRY(aCpu, NKern::EThread, q, 4);
518 QUEUE_DFC(d4, mode, TRUE);
519 QUEUE_DFC(d3, mode, TRUE);
520 QUEUE_DFC(d2, mode, TRUE);
521 QUEUE_DFC(d1, mode, TRUE);
523 while (d1->Queued()) {}
524 CHECK_FIRST_ENTRY(aCpu, NKern::EThread, q, 4);
525 CHECK_FIRST_ENTRY(aCpu, NKern::EThread, q, 3);
526 CHECK_FIRST_ENTRY(aCpu, NKern::EThread, q, 2);
527 CHECK_FIRST_ENTRY(aCpu, NKern::EThread, q, 1);
529 QUEUE_DFC(d4, mode, TRUE);
530 QUEUE_DFC(d3, mode, TRUE);
531 QUEUE_DFC(d2, mode, TRUE);
532 QUEUE_DFC(d1, mode, TRUE);
534 while (d1->Queued()) {}
535 TEST_RESULT(!d4->Queued(), "");
536 TEST_RESULT(!d4->Cancel(), "");
537 TEST_RESULT(!d4->Queued(), "");
538 CHECK_FIRST_ENTRY(aCpu, NKern::EThread, q, 4);
539 CHECK_FIRST_ENTRY(aCpu, NKern::EThread, q, 3);
540 CHECK_FIRST_ENTRY(aCpu, NKern::EThread, q, 2);
541 CHECK_FIRST_ENTRY(aCpu, NKern::EThread, q, 1);
545 TEST_RESULT(!d1->Queued(), "");
546 QUEUE_DFC(d1, mode, TRUE);
547 TEST_RESULT(d1->Queued(), "");
548 QUEUE_DFC(d1, mode, FALSE);
549 TEST_RESULT(d1->Queued(), "");
550 QUEUE_DFC(d2, mode, TRUE);
551 QUEUE_DFC(d3, mode, TRUE);
552 QUEUE_DFC(d4, mode, TRUE);
553 QUEUE_DFC(d4, mode, FALSE);
558 CHECK_FIRST_ENTRY(aCpu, NKern::EThread, q, 4);
559 CHECK_FIRST_ENTRY(aCpu, NKern::EThread, q, 2);
560 CHECK_FIRST_ENTRY(aCpu, NKern::EThread, q, 3);
561 CHECK_FIRST_ENTRY(aCpu, NKern::EThread, q, 1);
565 TEST_RESULT(!d1->Queued(), "");
566 QUEUE_DFC(d1, mode, TRUE);
567 TEST_RESULT(d1->Queued(), "");
568 QUEUE_DFC(d1, mode, FALSE);
569 TEST_RESULT(d1->Queued(), "");
570 QUEUE_DFC(d4, mode, TRUE);
571 QUEUE_DFC(d3, mode, TRUE);
572 QUEUE_DFC(d2, mode, TRUE);
577 CHECK_FIRST_ENTRY(aCpu, NKern::EThread, q, 4);
578 CHECK_FIRST_ENTRY(aCpu, NKern::EThread, q, 3);
579 CHECK_FIRST_ENTRY(aCpu, NKern::EThread, q, 2);
580 CHECK_FIRST_ENTRY(aCpu, NKern::EThread, q, 1);
584 TEST_RESULT(!d1->Queued(), "");
585 QUEUE_DFC(d1, mode, TRUE);
586 TEST_RESULT(d1->Queued(), "");
587 QUEUE_DFC(d1, mode, FALSE);
588 TEST_RESULT(d1->Queued(), "");
589 QUEUE_DFC(d2, mode, TRUE);
590 QUEUE_DFC(d3, mode, TRUE);
591 QUEUE_DFC(d4, mode, TRUE);
593 TEST_RESULT(d1->Cancel(), "");
594 TEST_RESULT(!d1->Queued(), "");
598 CHECK_FIRST_ENTRY(aCpu, NKern::EThread, q, 4);
599 CHECK_FIRST_ENTRY(aCpu, NKern::EThread, q, 2);
600 CHECK_FIRST_ENTRY(aCpu, NKern::EThread, q, 3);
611 TBool QueueIDfc(TDfc* aDfc, TInt aMode, TBool aExRet)
614 return !aExRet == !aDfc->RawAdd();
617 TTestDfc::Last = 0xffffffffu;
619 TInt cpu = (aMode&0xff) - 1;
620 adder.Add(aDfc, 1u<<cpu);
621 adder.WaitCompletion();
624 while (TTestDfc::Last != (TUint32)aDfc->iPtr)
632 TBool ret = aDfc->Add();
634 return !aExRet == !ret;
639 #define QUEUE_IDFC(dfc, mode, exret) TEST_RESULT(QueueIDfc(dfc,mode,exret),"")
643 TEST_PRINT("IDFCTest1");
645 TInt num_cpus = NKern::NumberOfCpus();
646 TInt this_cpu = NKern::CurrentCpu();
648 TTestDfc* d1 = new TTestDfc(1);
650 TEST_RESULT(d1->IsIDFC(), "");
651 TTestDfc* d2 = new TTestDfc(2);
653 TEST_RESULT(d2->IsIDFC(), "");
654 TTestDfc* d3 = new TTestDfc(3);
656 TEST_RESULT(d3->IsIDFC(), "");
657 TTestDfc* d4 = new TTestDfc(4);
659 TEST_RESULT(d4->IsIDFC(), "");
662 for (mode=-1; mode<=num_cpus; ++mode)
664 TInt xcpu = (mode>0) ? (mode-1) : this_cpu;
665 TEST_PRINT1("Mode %d", mode);
667 TEST_RESULT(!d1->Queued(), "");
668 QUEUE_IDFC(d1, mode, TRUE);
669 TEST_RESULT(!d1->Queued(), "");
670 QUEUE_IDFC(d1, mode, TRUE);
671 TEST_RESULT(!d1->Queued(), "");
672 QUEUE_IDFC(d2, mode, TRUE);
673 QUEUE_IDFC(d3, mode, TRUE);
674 QUEUE_IDFC(d4, mode, TRUE);
675 CHECK_FIRST_ENTRY(xcpu, NKern::EIDFC, 0, 1);
676 CHECK_FIRST_ENTRY(xcpu, NKern::EIDFC, 0, 1);
677 CHECK_FIRST_ENTRY(xcpu, NKern::EIDFC, 0, 2);
678 CHECK_FIRST_ENTRY(xcpu, NKern::EIDFC, 0, 3);
679 CHECK_FIRST_ENTRY(xcpu, NKern::EIDFC, 0, 4);
681 QUEUE_IDFC(d4, mode, TRUE);
682 QUEUE_IDFC(d3, mode, TRUE);
683 QUEUE_IDFC(d2, mode, TRUE);
684 QUEUE_IDFC(d1, mode, TRUE);
685 CHECK_FIRST_ENTRY(xcpu, NKern::EIDFC, 0, 4);
686 CHECK_FIRST_ENTRY(xcpu, NKern::EIDFC, 0, 3);
687 CHECK_FIRST_ENTRY(xcpu, NKern::EIDFC, 0, 2);
688 CHECK_FIRST_ENTRY(xcpu, NKern::EIDFC, 0, 1);
691 TInt irq = NKern::DisableAllInterrupts();
692 TEST_RESULT(d1->RawAdd(), "");
693 TEST_RESULT(d1->Queued(), "");
695 NKern::RestoreInterrupts(irq);
696 TEST_RESULT(!d1->Queued(), "");
697 CHECK_FIRST_ENTRY(this_cpu, NKern::EIDFC, 0, 1);
700 TEST_RESULT(d1->Add(), "");
701 TEST_RESULT(d3->Add(), "");
702 TEST_RESULT(d2->Add(), "");
703 TEST_RESULT(d4->Add(), "");
704 TEST_RESULT(!d1->Add(), "");
705 TEST_RESULT(d1->Queued(), "");
706 TEST_RESULT(d2->Queued(), "");
707 TEST_RESULT(d3->Queued(), "");
708 TEST_RESULT(d4->Queued(), "");
711 TEST_RESULT(!d1->Queued(), "");
712 TEST_RESULT(!d2->Queued(), "");
713 TEST_RESULT(!d3->Queued(), "");
714 TEST_RESULT(!d4->Queued(), "");
715 CHECK_FIRST_ENTRY(this_cpu, NKern::EIDFC, 0, 1);
716 CHECK_FIRST_ENTRY(this_cpu, NKern::EIDFC, 0, 3);
717 CHECK_FIRST_ENTRY(this_cpu, NKern::EIDFC, 0, 2);
718 CHECK_FIRST_ENTRY(this_cpu, NKern::EIDFC, 0, 4);
722 TEST_RESULT(d1->Add(), "");
723 TEST_RESULT(d3->Add(), "");
724 TEST_RESULT(d2->Add(), "");
725 TEST_RESULT(d4->Add(), "");
726 TEST_RESULT(d1->Queued(), "");
727 TEST_RESULT(d2->Queued(), "");
728 TEST_RESULT(d3->Queued(), "");
729 TEST_RESULT(d4->Queued(), "");
730 TEST_RESULT(d3->Cancel(), "");
731 TEST_RESULT(!d3->Queued(), "");
732 TEST_RESULT(!d3->Cancel(), "");
735 TEST_RESULT(!d1->Queued(), "");
736 TEST_RESULT(!d2->Queued(), "");
737 TEST_RESULT(!d4->Queued(), "");
738 CHECK_FIRST_ENTRY(this_cpu, NKern::EIDFC, 0, 1);
739 CHECK_FIRST_ENTRY(this_cpu, NKern::EIDFC, 0, 2);
740 CHECK_FIRST_ENTRY(this_cpu, NKern::EIDFC, 0, 4);
744 TEST_RESULT(d1->Add(), "");
745 TEST_RESULT(d3->Add(), "");
746 TEST_RESULT(d2->Add(), "");
747 TEST_RESULT(d4->Add(), "");
748 TEST_RESULT(d1->Queued(), "");
749 TEST_RESULT(d2->Queued(), "");
750 TEST_RESULT(d3->Queued(), "");
751 TEST_RESULT(d4->Queued(), "");
752 TEST_RESULT(d3->Cancel(), "");
753 TEST_RESULT(d1->Cancel(), "");
754 TEST_RESULT(d2->Cancel(), "");
755 TEST_RESULT(d4->Cancel(), "");
756 TEST_RESULT(!d1->Queued(), "");
757 TEST_RESULT(!d2->Queued(), "");
758 TEST_RESULT(!d3->Queued(), "");
759 TEST_RESULT(!d4->Queued(), "");
771 TEST_PRINT1("CPU %d", cpu);
774 TEST_RESULT(!d1->Queued(), "");
775 QUEUE_IDFC(d1, mode, TRUE);
776 TEST_RESULT(d1->Queued(), "");
777 QUEUE_IDFC(d1, mode, FALSE);
778 TEST_RESULT(d1->Queued(), "");
779 QUEUE_IDFC(d2, mode, TRUE);
780 QUEUE_IDFC(d3, mode, TRUE);
781 QUEUE_IDFC(d4, mode, TRUE);
786 CHECK_FIRST_ENTRY(cpu, NKern::EIDFC, 0, 1);
787 CHECK_FIRST_ENTRY(cpu, NKern::EIDFC, 0, 2);
788 CHECK_FIRST_ENTRY(cpu, NKern::EIDFC, 0, 3);
789 CHECK_FIRST_ENTRY(cpu, NKern::EIDFC, 0, 4);
793 TEST_RESULT(!d1->Queued(), "");
794 QUEUE_IDFC(d1, mode, TRUE);
795 TEST_RESULT(d1->Queued(), "");
796 QUEUE_IDFC(d2, mode, TRUE);
797 QUEUE_IDFC(d3, mode, TRUE);
798 QUEUE_IDFC(d4, mode, TRUE);
799 TEST_RESULT(d1->Cancel(), "");
800 TEST_RESULT(!d1->Queued(), "");
801 TEST_RESULT(!d1->Cancel(), "");
806 CHECK_FIRST_ENTRY(cpu, NKern::EIDFC, 0, 2);
807 CHECK_FIRST_ENTRY(cpu, NKern::EIDFC, 0, 3);
808 CHECK_FIRST_ENTRY(cpu, NKern::EIDFC, 0, 4);
812 TEST_RESULT(!d1->Queued(), "");
813 QUEUE_IDFC(d1, mode, TRUE);
814 TEST_RESULT(d1->Queued(), "");
815 QUEUE_IDFC(d2, mode, TRUE);
816 QUEUE_IDFC(d3, mode, TRUE);
817 QUEUE_IDFC(d4, mode, TRUE);
818 TEST_RESULT(d1->Cancel(), "");
819 TEST_RESULT(!d1->Queued(), "");
820 TEST_RESULT(d4->Cancel(), "");
821 TEST_RESULT(d2->Cancel(), "");
822 TEST_RESULT(d3->Cancel(), "");
836 void DoIdleDFCTest1(TInt aCpu)
839 TEST_PRINT2("IdleDFCTest1 CPU %d (%08x)", aCpu, TheScheduler.iCpusNotIdle);
841 TEST_PRINT1("IdleDFCTest1 CPU %d (%08x)", aCpu);
843 // TInt num_cpus = NKern::NumberOfCpus();
844 TInt this_cpu = NKern::CurrentCpu();
845 TBool same_cpu = (aCpu==this_cpu);
847 TPauseDFC* pauser = 0;
850 q = CreateDfcQ("DfcQ3", 1, aCpu);
852 pauser = new TPauseDFC(q);
856 TTestDfc* d1 = new TTestDfc(1);
858 TEST_RESULT(d1->IsIDFC(), "");
859 TTestDfc* d2 = new TTestDfc(2);
861 TEST_RESULT(d2->IsIDFC(), "");
862 TTestDfc* d3 = new TTestDfc(3);
864 TEST_RESULT(d3->IsIDFC(), "");
865 TTestDfc* d4 = new TTestDfc(4);
867 TEST_RESULT(d4->IsIDFC(), "");
869 TEST_RESULT(!d1->Queued(), "");
870 TEST_RESULT(d1->QueueOnIdle(), "");
871 TEST_RESULT(d1->Queued(), "");
872 TEST_RESULT(!d1->QueueOnIdle(), "");
878 TEST_RESULT(d1->Queued(), "");
881 TEST_RESULT(!d1->Queued(), "");
882 CHECK_FIRST_ENTRY(this_cpu, NKern::EIDFC, 0, 1);
885 TBool ret = d1->QueueOnIdle();
886 TEST_RESULT(pauser?!ret:ret, "");
887 TEST_RESULT(d1->Queued(), "");
888 TEST_RESULT(d1->Cancel(), "");
889 TEST_RESULT(!d1->Queued(), "");
895 TEST_RESULT(d4->QueueOnIdle(), "");
896 TEST_RESULT(d3->QueueOnIdle(), "");
897 TEST_RESULT(d1->QueueOnIdle(), "");
898 TEST_RESULT(d2->QueueOnIdle(), "");
899 TEST_RESULT(d3->Cancel(), "");
901 TInt xcpu = this_cpu;
910 CHECK_FIRST_ENTRY(xcpu, NKern::EIDFC, 0, 4);
911 CHECK_FIRST_ENTRY(xcpu, NKern::EIDFC, 0, 1);
912 CHECK_FIRST_ENTRY(xcpu, NKern::EIDFC, 0, 2);
925 NFastSemaphore* IdleDFCTest2Fs;
927 void IdleDFCTest2Fn(TAny* a)
929 TUint32 id = (TUint32)a;
932 TEST_RESULT(Dfcs[1]->Cancel(), "");
933 TEST_RESULT(Dfcs[3]->QueueOnIdle(), "");
934 TEST_RESULT(Dfcs[4]->QueueOnIdle(), "");
935 TEST_RESULT(Dfcs[5]->QueueOnIdle(), "");
938 IdleDFCTest2Fs->Signal();
941 TEST_RESULT(Dfcs[5]->Cancel(), "");
946 void DoIdleDFCTest2()
948 TEST_PRINT("IdleDFCTest2");
949 NFastSemaphore sem(0);
950 TInt this_cpu = NKern::CurrentCpu();
954 Dfcs[i] = new TDfc(&IdleDFCTest2Fn, (TAny*)(i+1));
957 TEST_RESULT(Dfcs[0]->QueueOnIdle(), "");
958 TEST_RESULT(Dfcs[1]->QueueOnIdle(), "");
959 TEST_RESULT(Dfcs[2]->QueueOnIdle(), "");
960 IdleDFCTest2Fs = &sem;
963 CHECK_FIRST_ENTRY(this_cpu, NKern::EIDFC, 0, 1);
964 CHECK_FIRST_ENTRY(this_cpu, NKern::EIDFC, 0, 3);
967 CHECK_FIRST_ENTRY(this_cpu, NKern::EIDFC, 0, 4);
968 CHECK_FIRST_ENTRY(this_cpu, NKern::EIDFC, 0, 5);
991 static void IDfcFn(TAny*);
992 static void DfcFn(TAny*);
993 static void TimerIsrFn(TAny*);
994 static void TimerDfcFn(TAny*);
996 TBool Add(TAny* a=0);
997 TBool Cancel(TAny* a=0);
998 TBool Enque(TAny* a=0);
999 TBool QueueOnIdle(TAny* a=0);
1003 TBool SafeQueueOnIdle();
1004 void CreateDfcOrTimer();
1005 void GetDesc(char* aDesc);
1006 inline TBool IsIDFC()
1007 {return (iFlags & (EFlag_IDFC|EFlag_Timer)) == EFlag_IDFC;}
1008 inline TBool IsIdler()
1009 {return iFlags & EFlag_IdleDFC;}
1010 void ThreadActivity();
1014 TDfc* volatile iDfc;
1015 NTimer* volatile iTimer;
1018 TUint32 iQueueCount;
1019 TUint32 iRunCount[KMaxCpus];
1020 TUint32 iCancelCount;
1021 TUint32 iExclusionFailCount;
1025 TUint64 iTimeQueued;
1028 TSpinLock iSpinLock;
1029 NSchedulable* iXTied;
1030 volatile TUint32* iExclusionCheck;
1034 : iSpinLock(TSpinLock::EOrderGenericIrqLow1)
1036 memclr(this,sizeof(TDfcX));
1037 new (&iSpinLock) TSpinLock(TSpinLock::EOrderGenericIrqLow1);
1042 TAny* p = __e32_atomic_swp_ord_ptr(&iDfc, 0);
1045 if (iFlags & EFlag_Timer)
1046 delete ((NTimer*)p);
1057 EMode_Wait =0x00000001u,
1058 EMode_AllowCancel =0x00000002u,
1059 EMode_AllowIdle =0x00000004u,
1060 EMode_AllowEnque =0x00000008u,
1061 EMode_Recycle =0x00000010u,
1062 EMode_UseTied =0x00000020u,
1063 EMode_Migrate =0x00000040u,
1064 EMode_SelfMigrate =0x00000080u,
1065 EMode_Exit =0x80000000u
1068 enum {EMaxDfc=48, EMaxDfcQ=8};
1071 static TDfcStress* New(TInt aNumDfc, TInt aNumDfcQ, TBool aTimerTest);
1073 static void DoThreadFn(TAny*);
1075 static void BackStopFn(TAny*);
1078 void DoTestPhase(TInt aMode, TInt aTime, TInt aCount);
1079 void GetModeText(char* aName);
1081 TDfcX* NewDfc(TUint32 aId, TUint32 aFlags, TInt aDfcQ);
1082 TDfcX* NewIDfc(TUint32 aId, TUint32 aFlags, NSchedulable* aTied=0);
1083 TDfcX* NewTimer(TUint32 aId, TUint32 aFlags, TInt aDfcQ, NSchedulable* aTied);
1084 void CreateDfc(TUint32 aId);
1087 TDfcX* iDfcX[EMaxDfc];
1090 TDfcQue* iDfcQ[EMaxDfcQ];
1091 NThread* iThread[KMaxCpus];
1092 volatile TBool iStop;
1093 volatile TInt iRunning;
1094 volatile TInt iMode;
1095 NFastSemaphore* iExitSem;
1096 TDfcX* volatile iGarbage;
1097 TUint32 iRandomTimeLimit;
1098 TDfc* iBackStopIdleDfc;
1099 TDfcQue* iBackStopIdleDfcQ;
1102 void TDfcX::Update()
1106 if (iExclusionCheck)
1107 exc0 = *iExclusionCheck;
1108 TInt cpu = NKern::CurrentCpu();
1109 __e32_atomic_add_ord32(&iRunCount[cpu], 1);
1110 TInt ctx = NKern::CurrentContext();
1111 TBool is_idfc = IsIDFC();
1112 TBool is_timer = iFlags & EFlag_Timer;
1113 TBool is_tied = iFlags & EFlag_Tied;
1114 if ((is_idfc||is_timer) && is_tied && !(iS->iMode & (TDfcStress::EMode_Migrate|TDfcStress::EMode_SelfMigrate)))
1116 TInt cpu = NKern::CurrentCpu();
1117 TInt xcpu = iXTied->iCpuAffinity;
1124 if ((ctx!=NKern::EThread) && (iS->iMode & TDfcStress::EMode_AllowCancel))
1125 irq = iSpinLock.LockIrqSave();
1126 TUint64 now = fast_counter();
1127 TUint64 delta = now - iTimeQueued;
1128 if (TInt64(delta)>=0)
1130 if (delta > iMaxTime)
1134 if ((ctx!=NKern::EThread) && (iS->iMode & TDfcStress::EMode_AllowCancel))
1135 iSpinLock.UnlockIrqRestore(irq);
1140 for (i=0; i<KMaxCpus; ++i)
1142 NThread* t = iS->iThread[i];
1144 t->iRequestSemaphore.Reset();
1147 iS->iBackStopIdleDfc->Cancel();
1149 if (iExclusionCheck)
1150 exc1 = *iExclusionCheck;
1152 __e32_atomic_add_ord32(&iExclusionFailCount, 1);
1155 void TDfcStress::BackStopFn(TAny* a)
1157 TDfcStress* s = (TDfcStress*)a;
1160 for (i=0; i<KMaxCpus; ++i)
1162 NThread* t = s->iThread[i];
1164 t->iRequestSemaphore.Reset();
1169 void TDfcX::IDfcFn(TAny* a)
1171 TDfcX* d = (TDfcX*)a;
1175 void TDfcX::DfcFn(TAny* a)
1177 TDfcX* d = (TDfcX*)a;
1178 d->ThreadActivity();
1180 d->ThreadActivity();
1183 void TDfcX::TimerDfcFn(TAny* a)
1185 TDfcX* d = (TDfcX*)a;
1186 d->ThreadActivity();
1188 d->ThreadActivity();
1191 void TDfcX::TimerIsrFn(TAny* a)
1193 TDfcX* d = (TDfcX*)a;
1197 void TDfcX::ThreadActivity()
1199 TInt ncpus = NKern::NumberOfCpus();
1200 TInt ocpu = NKern::CurrentCpu();
1201 NThread* pC = NKern::CurrentThread();
1202 volatile TUint32* pX = (volatile TUint32*)&pC->iRunCount32[1]; // HACK!
1205 if ((iS->iMode & TDfcStress::EMode_SelfMigrate) && !pC->iEvents.IsEmpty())
1207 for (i=0; i<ncpus; ++i)
1212 NKern::ThreadSetCpuAffinity(pC, cpu);
1231 TBool TDfcX::Add(TAny* a)
1233 TBool is_timer = iFlags & EFlag_Timer;
1236 TUint64 time = fast_counter();
1239 ok = ((NTimer*)a)->OneShot(1) == KErrNone;
1241 ok = ((TDfc*)a)->Add();
1245 __e32_atomic_add_ord32(&iQueueCount, 1);
1250 TBool TDfcX::Cancel(TAny* a)
1252 TBool is_timer = iFlags & EFlag_Timer;
1257 ok = ((NTimer*)a)->Cancel();
1259 ok = ((TDfc*)a)->Cancel();
1261 __e32_atomic_add_ord32(&iCancelCount, 1);
1265 TBool TDfcX::Enque(TAny* a)
1267 TBool is_timer = iFlags & EFlag_Timer;
1270 TUint64 time = fast_counter();
1273 ok = ((NTimer*)a)->Again(2) == KErrNone;
1275 ok = ((TDfc*)a)->Enque();
1279 __e32_atomic_add_ord32(&iQueueCount, 1);
1284 TBool TDfcX::QueueOnIdle(TAny* a)
1286 TBool is_timer = iFlags & EFlag_Timer;
1291 TUint64 time = fast_counter();
1292 TBool ok = ((TDfc*)a)->QueueOnIdle();
1296 __e32_atomic_add_ord32(&iQueueCount, 1);
1301 TBool TDfcX::SafeAdd()
1304 TUint32 x = set_bit0_if_nonnull((TUint32&)iDfc);
1309 flip_bit0((TUint32&)iDfc);
1314 TBool TDfcX::SafeEnque()
1317 TUint32 x = set_bit0_if_nonnull((TUint32&)iDfc);
1322 flip_bit0((TUint32&)iDfc);
1327 TBool TDfcX::SafeQueueOnIdle()
1330 TUint32 x = set_bit0_if_nonnull((TUint32&)iDfc);
1334 ret = QueueOnIdle(p);
1335 flip_bit0((TUint32&)iDfc);
1340 TBool TDfcX::SafeCancel()
1343 TUint32 x = swap_out_if_bit0_clear((TUint32&)iDfc);
1346 if (iFlags & EFlag_Timer)
1348 NTimer* p = (NTimer*)x;
1351 memset(p, 0xbb, sizeof(NTimer));
1359 memset(p, 0xbb, sizeof(TDfc));
1367 void TDfcX::GetDesc(char* a)
1370 if (iFlags & EFlag_Timer)
1372 if (iFlags & EFlag_IDFC)
1374 if (iFlags & EFlag_DFC)
1376 if (iFlags & EFlag_IdleDFC)
1378 if (iFlags & EFlag_Tied)
1382 TDfcStress::TDfcStress()
1384 memclr(this, sizeof(*this));
1387 TDfcX* TDfcStress::NewDfc(TUint32 aId, TUint32 aFlags, TInt aDfcQ)
1389 TDfcX* d = new TDfcX;
1395 d->iDfcQ = iDfcQ[aDfcQ];
1396 d->CreateDfcOrTimer();
1400 TDfcX* TDfcStress::NewIDfc(TUint32 aId, TUint32 aFlags, NSchedulable* aTied)
1402 TDfcX* d = new TDfcX;
1409 d->CreateDfcOrTimer();
1413 TDfcX* TDfcStress::NewTimer(TUint32 aId, TUint32 aFlags, TInt aDfcQ, NSchedulable* aTied)
1415 TDfcX* d = new TDfcX;
1421 d->iDfcQ = (aFlags & TDfcX::EFlag_DFC) ? iDfcQ[aDfcQ] : 0;
1422 d->iXTied = (aFlags & TDfcX::EFlag_Tied) ? aTied : 0;
1423 d->CreateDfcOrTimer();
1428 void TDfcX::CreateDfcOrTimer()
1430 // volatile TUint32* xc = 0;
1431 NThreadBase* t = iS->iDfcQ[0]->iThread;
1432 volatile TUint32* xc = &t->iRunCount32[1]; // HACK!
1433 if (!(iFlags & EFlag_Timer))
1436 if (!(iFlags & EFlag_IDFC))
1438 d = new TDfc(&TDfcX::DfcFn, this, iDfcQ, 1);
1439 xc = (volatile TUint32*)&iDfcQ->iThread->iRunCount32[1];
1441 else if (iFlags & EFlag_Tied)
1443 d = new TDfc(iXTied, &TDfcX::IDfcFn, this);
1444 xc = (volatile TUint32*)&iXTied->iRunCount32[1];
1447 d = new TDfc(&TDfcX::IDfcFn, this);
1448 __NK_ASSERT_ALWAYS(d!=0);
1449 __e32_atomic_store_rel_ptr(&iDfc, d);
1454 if (iFlags & EFlag_DFC)
1456 tmr = new NTimer(&TDfcX::TimerDfcFn, this, iDfcQ, 1);
1457 xc = (volatile TUint32*)&iDfcQ->iThread->iRunCount32[1];
1459 else if (iFlags & EFlag_Tied)
1461 tmr = new NTimer(iXTied, &TDfcX::TimerIsrFn, this);
1462 xc = (volatile TUint32*)&iXTied->iRunCount32[1];
1465 tmr = new NTimer(&TDfcX::TimerIsrFn, this);
1466 __NK_ASSERT_ALWAYS(tmr!=0);
1467 __e32_atomic_store_rel_ptr(&iTimer, tmr);
1469 iExclusionCheck = xc;
1472 TDfcStress* TDfcStress::New(TInt aNumDfc, TInt aNumDfcQ, TBool aTimerTest)
1474 TDfcStress* p = new TDfcStress;
1476 p->iTimerTest = aTimerTest;
1477 p->iNumDfc = aNumDfc;
1478 p->iNumDfcQ = aNumDfcQ;
1483 void TDfcStress::Create()
1485 DEBUGPRINT("TDfcStress @ %08x", this);
1487 TInt num_cpus = NKern::NumberOfCpus();
1489 iExitSem = new NFastSemaphore(0);
1491 for (i=0; i<iNumDfcQ; ++i)
1493 char c[8] = "DFCQ*";
1494 c[4] = (char)('0'+i);
1495 TDfcQue* q = CreateDfcQ(c, 32, cpu);
1498 if (++cpu == num_cpus)
1500 NThreadBase* t = q->iThread;
1501 DEBUGPRINT("DfcQ %2d @ %08x Thread @%08x Stack %08x+%08x", i, iDfcQ[i], t, t->iStackBase, t->iStackSize);
1503 iBackStopIdleDfcQ = CreateDfcQ("BackStop", 1, 0);
1504 TEST_OOM(iBackStopIdleDfcQ);
1505 iBackStopIdleDfc = new TDfc(&BackStopFn, this, iBackStopIdleDfcQ, 1);
1506 TEST_OOM(iBackStopIdleDfc);
1507 for (i=0; i<num_cpus; ++i)
1509 char c[8] = "THRD*";
1510 c[4] = (char)('0'+i);
1511 NThread* t = CreateUnresumedThreadSignalOnExit(c, &DoThreadFn, 11, this, 0, -1, iExitSem, i);
1514 DEBUGPRINT("Thread %2d @ %08x (Stack %08x+%08x)", i, iThread[i], t->iStackBase, t->iStackSize);
1516 for (i=0; i<iNumDfc; ++i)
1519 DEBUGPRINT("DfcX %2d @ %08x (DFC @ %08x)", i, iDfcX[i], iDfcX[i]->iDfc);
1523 void TDfcStress::CreateDfc(TUint32 aId)
1525 TUint32 type = aId & 7;
1526 TUint32 q = aId % iNumDfcQ;
1535 d = NewTimer(aId, TDfcX::EFlag_Timer|TDfcX::EFlag_DFC, q, 0);
1537 d = NewDfc(aId, TDfcX::EFlag_DFC, q);
1542 d = NewTimer(aId, TDfcX::EFlag_Timer|TDfcX::EFlag_Tied, 0, iDfcQ[iNumDfcQ-1-(type&1)]->iThread);
1545 if (aId>=16 && aId<32 && iNumDfcQ>2)
1546 d = NewIDfc(aId, TDfcX::EFlag_IDFC|TDfcX::EFlag_Tied, iDfcQ[2]->iThread);
1548 d = NewIDfc(aId, TDfcX::EFlag_IDFC);
1554 d = NewTimer(aId, TDfcX::EFlag_Timer, 0, 0);
1556 d = NewDfc(aId, TDfcX::EFlag_DFC|TDfcX::EFlag_IdleDFC, q);
1559 __e32_atomic_store_rel_ptr(&iDfcX[aId], d);
1562 void TDfcStress::Close()
1566 // delete DFCs before the DFC queues they might be on
1567 for (i=0; i<iNumDfc; ++i)
1569 TDfcX* d = iDfcX[i];
1572 delete iBackStopIdleDfc;
1574 for (i=0; i<iNumDfcQ; ++i)
1575 DestroyDfcQ(iDfcQ[i]);
1576 DestroyDfcQ(iBackStopIdleDfcQ);
1582 void TDfcStress::DoThreadFn(TAny* a)
1584 ((TDfcStress*)a)->ThreadFn();
1587 void append(char*& a, const char* s)
1594 void TDfcStress::GetModeText(char* a)
1599 append(a, "Add only");
1602 if (iMode & EMode_Wait)
1604 if (iMode & EMode_AllowCancel)
1605 append(a, "Cancel ");
1606 if (iMode & EMode_AllowIdle)
1608 if (iMode & EMode_AllowEnque)
1609 append(a, "Enque ");
1610 if (iMode & EMode_Recycle)
1611 append(a, "Recycle ");
1612 if (iMode & EMode_Migrate)
1613 append(a, "Migrate ");
1614 if (iMode & EMode_SelfMigrate)
1615 append(a, "SelfMigrate ");
1621 Bit 31 If set causes thread to exit
1622 Bit 0 If set does random wait after each operation
1623 Bit 1 Allows Cancel operations if set
1624 Bit 2 Allows idle operations if set
1625 Bit 3 Test Enque() as well as Add()
1626 Bit 4 Use SafeXXX operations
1627 Bit 5 Use tied IDFCs
1628 Bit 6 Migrate threads with things tied to them
1629 Bit 7 Threads with things tied to them migrate themselves during execution
1632 void TDfcStress::ThreadFn()
1634 TBool finish = FALSE;
1636 seed[0] = NKern::CurrentCpu() ^ 0xddb3d743;
1642 __e32_atomic_add_ord32(&iRunning, (TUint32)(-1));
1654 __e32_atomic_add_ord32(&iRunning, 1);
1656 if (iMode & EMode_Wait)
1658 TUint32 wait = random(seed);
1659 wait %= iRandomTimeLimit;
1663 TUint32 action = random(seed);
1664 TUint32 action2 = random(seed);
1665 if (action & 0xff000000)
1667 // queue or cancel a DFC or timer
1668 TBool cancel = action2 & 2;
1669 TUint32 id = action % iNumDfc;
1670 TDfcX* d = iDfcX[id];
1671 if (iMode & EMode_Recycle)
1673 TBool isIDFC = d->IsIDFC();
1674 TBool isIdler = d->IsIdler();
1678 d->SafeQueueOnIdle();
1679 else if ((iMode & EMode_AllowEnque) && (action2 & 1) && !isIDFC)
1690 if (cancel && (iMode & EMode_AllowCancel))
1694 else if (!d->IsIdler())
1696 if ((iMode & EMode_AllowEnque) && (action2 & 1) && !d->IsIDFC())
1714 if (iMode & EMode_AllowIdle)
1716 iBackStopIdleDfc->QueueOnIdle();
1717 NKern::WaitForAnyRequest();
1722 void StopTimeout(TAny*)
1727 void TDfcStress::DoTestPhase(TInt aMode, TInt aTime, TInt aCount)
1729 char mode_text[128];
1735 GetModeText(mode_text);
1736 TEST_PRINT1("Testing with: %s", mode_text);
1737 for (i=0; i<aCount; ++i)
1739 NKern::Sleep(aTime);
1742 DebugPrint("\r\n",2);
1743 TEST_PRINT("Stopping ...");
1745 NTimer timer(&StopTimeout, 0);
1746 timer.OneShot(2000);
1749 while (iRunning && ++n<=100)
1755 iBackStopIdleDfc->Cancel();
1757 TEST_PRINT("Threads stopped");
1758 for (i=0; i<iNumDfcQ; ++i)
1760 TUint32 ev = iDfcQ[i]->iThread->iEventState;
1761 DEBUGPRINT("DfcThread %d EventState = %08x", i, ev);
1762 TEST_RESULT(!(ev & NSchedulable::EEventCountMask), "");
1764 for (i=0; i<NKern::NumberOfCpus(); ++i)
1766 TUint32 ev = iThread[i]->iEventState;
1767 DEBUGPRINT("Thread %d EventState = %08x", i, ev);
1768 TEST_RESULT(!(ev & NSchedulable::EEventCountMask), "");
1771 for (i=0; i<iNumDfc; ++i)
1773 TDfcX* d = iDfcX[i];
1775 TUint32 qc = d->iQueueCount;
1776 TUint32* rc = d->iRunCount;
1777 TUint32 totrc = rc[0] + rc[1] + rc[2] + rc[3] + rc[4] + rc[5] + rc[6] + rc[7];
1778 TUint32 cc = d->iCancelCount;
1779 TUint32 f = d->iFlags;
1780 // TUint32 imm = d->IsIDFC()?1:0;
1781 TUint32 max = d->iMaxTime;
1783 TUint32 xfc = d->iExclusionFailCount;
1785 avg = TUint32(d->iSumTime / TUint64(totrc));
1791 DEBUGPRINT("%2d: %s QC %9d RC %9d CC %9d MAX %9d AVG %9d XFC %9d RC %9d %9d %9d %9d %9d %9d %9d %9d", i, desc, qc, totrc, cc, max, avg, xfc, rc[0], rc[1], rc[2], rc[3], rc[4], rc[5], rc[6], rc[7]);
1792 TInt diff = (TInt)(qc - (totrc+cc));
1793 TEST_RESULT1(diff==0, "Counts mismatched, diff=%d", diff);
1794 TEST_RESULT(!(f&TDfcX::EFlag_Tied) || xfc==0, "Exclusion Failure!");
1796 memclr(d->iRunCount, sizeof(d->iRunCount));
1797 d->iCancelCount = 0;
1801 if (!iRandomTimeLimit)
1802 iRandomTimeLimit = maxavg + (maxavg>>1);
1805 void TDfcStress::Run()
1811 TInt num_cpus = NKern::NumberOfCpus();
1812 iRunning = num_cpus;
1813 for (i=0; i<KMaxCpus; ++i)
1817 NKern::ThreadResume(t);
1819 TEST_PRINT("Threads resumed");
1822 DoTestPhase(0x00, 10000, 1);
1826 DoTestPhase(EMode_AllowCancel|EMode_AllowEnque|EMode_Recycle, 10000, N);
1827 DoTestPhase(EMode_AllowCancel|EMode_AllowEnque|EMode_Wait|EMode_Recycle, 10000, N);
1828 DoTestPhase(EMode_AllowCancel|EMode_AllowEnque|EMode_Recycle|EMode_SelfMigrate, 10000, N);
1829 DoTestPhase(EMode_AllowCancel|EMode_AllowEnque|EMode_Wait|EMode_Recycle|EMode_SelfMigrate, 10000, N);
1830 DoTestPhase(EMode_AllowCancel|EMode_AllowEnque, 10000, N);
1831 DoTestPhase(EMode_AllowCancel|EMode_AllowEnque|EMode_Wait, 10000, N);
1832 DoTestPhase(EMode_AllowCancel|EMode_AllowEnque|EMode_SelfMigrate, 10000, N);
1833 DoTestPhase(EMode_AllowCancel|EMode_AllowEnque|EMode_Wait|EMode_SelfMigrate, 10000, N);
1837 DoTestPhase(EMode_AllowCancel|EMode_AllowEnque, 10000, 20);
1838 DoTestPhase(EMode_AllowCancel|EMode_AllowIdle|EMode_AllowEnque, 10000, 20);
1839 DoTestPhase(EMode_AllowIdle|EMode_AllowEnque, 10000, 20);
1840 DoTestPhase(EMode_AllowCancel|EMode_AllowIdle, 10000, 20);
1841 DoTestPhase(EMode_AllowCancel|EMode_Wait, 10000, 20);
1842 DoTestPhase(EMode_AllowCancel, 10000, 20);
1843 DoTestPhase(EMode_AllowCancel|EMode_AllowIdle|EMode_AllowEnque|EMode_Recycle, 10000, 20);
1847 TEST_PRINT("Terminating threads");
1848 for (i=0; i<num_cpus; ++i)
1849 NKern::FSWait(iExitSem);
1853 void DoStressTest(TBool aTimerTest)
1855 TEST_PRINT("Stress test...");
1858 switch (NKern::NumberOfCpus())
1860 case 1: ndfcs=16; ndfcq=2; break;
1861 case 2: ndfcs=16; ndfcq=2; break;
1862 case 3: ndfcs=24; ndfcq=2; break;
1863 case 4: ndfcs=32; ndfcq=3; break;
1864 case 5: ndfcs=32; ndfcq=3; break;
1865 case 6: ndfcs=48; ndfcq=4; break;
1866 case 7: ndfcs=48; ndfcq=4; break;
1867 case 8: ndfcs=48; ndfcq=4; break;
1869 __NK_ASSERT_ALWAYS(0);
1872 TDfcStress* ds = TDfcStress::New(ndfcs, ndfcq, aTimerTest);
1881 TEST_PRINT("Testing DFCs...");
1883 TTestDfc::Buffer = CircBuf::New(TTestDfc::EBufferSlots);
1899 DoIdleDFCTest1(cpu);
1904 DoStressTest(FALSE);
1907 delete TTestDfc::Buffer;
1908 TTestDfc::Buffer = 0;