os/kernelhwsrv/kerneltest/e32test/nkernsa/testdfc.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/kernelhwsrv/kerneltest/e32test/nkernsa/testdfc.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,1909 @@
     1.4 +// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +// All rights reserved.
     1.6 +// This component and the accompanying materials are made available
     1.7 +// under the terms of the License "Eclipse Public License v1.0"
     1.8 +// which accompanies this distribution, and is available
     1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +//
    1.11 +// Initial Contributors:
    1.12 +// Nokia Corporation - initial contribution.
    1.13 +//
    1.14 +// Contributors:
    1.15 +//
    1.16 +// Description:
    1.17 +// e32test\nkernsa\testdfc.cpp
    1.18 +// 
    1.19 +//
    1.20 +
    1.21 +#include <nktest/nkutils.h>
    1.22 +
    1.23 +#ifndef __SMP__
    1.24 +#define iNThreadBaseSpare7 iSpare7
    1.25 +class NSchedulable;
    1.26 +#endif
    1.27 +
    1.28 +extern "C" TUint32 set_bit0_if_nonnull(TUint32&);
    1.29 +extern "C" void flip_bit0(TUint32&);
    1.30 +extern "C" TUint32 swap_out_if_bit0_clear(TUint32&);
    1.31 +
    1.32 +#ifdef __SMP__
    1.33 +class TAddDfc : public TGenericIPI
    1.34 +#else
    1.35 +class TAddDfc : public NTimer
    1.36 +#endif
    1.37 +	{
    1.38 +public:
    1.39 +	TAddDfc();
    1.40 +	TDfc* Add(TDfc* aDfc, TUint32 aCpuMask);
    1.41 +	static TAddDfc* New();
    1.42 +#ifdef __SMP__
    1.43 +	static void Isr(TGenericIPI*);
    1.44 +#else
    1.45 +	static void TimerCallBack(TAny*);
    1.46 +	void WaitCompletion();
    1.47 +#endif
    1.48 +public:
    1.49 +	TDfc* iDfc;
    1.50 +	};
    1.51 +
    1.52 +TAddDfc::TAddDfc()
    1.53 +#ifdef __SMP__
    1.54 +	:	iDfc(0)
    1.55 +#else
    1.56 +	:	NTimer(&TimerCallBack, this),
    1.57 +		iDfc(0)
    1.58 +#endif
    1.59 +	{
    1.60 +	}
    1.61 +
    1.62 +TAddDfc* TAddDfc::New()
    1.63 +	{
    1.64 +	TAddDfc* p = new TAddDfc;
    1.65 +	TEST_OOM(p);
    1.66 +	return p;
    1.67 +	}
    1.68 +
    1.69 +#ifdef __SMP__
    1.70 +void TAddDfc::Isr(TGenericIPI* a)
    1.71 +#else
    1.72 +void TAddDfc::TimerCallBack(TAny* a)
    1.73 +#endif
    1.74 +	{
    1.75 +	TAddDfc& adder = *(TAddDfc*)a;
    1.76 +	TDfc* dfc = (TDfc*)__e32_atomic_swp_ord_ptr(&adder.iDfc, 0);
    1.77 +	if (dfc)
    1.78 +		dfc->Add();
    1.79 +	}
    1.80 +
    1.81 +TDfc* TAddDfc::Add(TDfc* aDfc, TUint32 aCpuMask)
    1.82 +	{
    1.83 +	TDfc* old = (TDfc*)__e32_atomic_swp_ord_ptr(&iDfc, aDfc);
    1.84 +#ifdef __SMP__
    1.85 +	Queue(&Isr, aCpuMask);
    1.86 +#else
    1.87 +	(void)aCpuMask;
    1.88 +	OneShot(1);
    1.89 +#endif
    1.90 +	return old;
    1.91 +	}
    1.92 +
    1.93 +#ifndef __SMP__
    1.94 +void TAddDfc::WaitCompletion()
    1.95 +	{
    1.96 +	while (iDfc)
    1.97 +		{}
    1.98 +	}
    1.99 +#endif
   1.100 +
   1.101 +class TTestDfc : public TDfc
   1.102 +	{
   1.103 +public:
   1.104 +	TTestDfc(TUint aId);
   1.105 +	TTestDfc(TUint aId, TDfcQue* aQ, TInt aPri);
   1.106 +	static void Run(TAny* aPtr);
   1.107 +
   1.108 +	static void CheckEmpty(TInt aLine);
   1.109 +	static void CheckFirstEntry(TInt aLine, TUint32 aCpu, TUint32 aContext, TDfcQue* aQ, TUint32 aId);
   1.110 +
   1.111 +	static CircBuf* Buffer;
   1.112 +	static volatile TBool Full;
   1.113 +	static volatile TUint32 Last;
   1.114 +
   1.115 +	enum {EBufferSlots=1024};
   1.116 +	};
   1.117 +
   1.118 +#define CHECK_EMPTY()	TTestDfc::CheckEmpty(__LINE__)
   1.119 +#define CHECK_FIRST_ENTRY(cpu, ctx, q, id)	TTestDfc::CheckFirstEntry(__LINE__, cpu, ctx, q, id)
   1.120 +
   1.121 +CircBuf* TTestDfc::Buffer;
   1.122 +volatile TBool TTestDfc::Full = FALSE;
   1.123 +volatile TUint32 TTestDfc::Last;
   1.124 +
   1.125 +TTestDfc::TTestDfc(TUint aId)
   1.126 +	:	TDfc(&Run, (TAny*)aId)
   1.127 +	{
   1.128 +	}
   1.129 +
   1.130 +TTestDfc::TTestDfc(TUint aId, TDfcQue* aQ, TInt aPri)
   1.131 +	:	TDfc(&Run, (TAny*)aId, aQ, aPri)
   1.132 +	{
   1.133 +	}
   1.134 +
   1.135 +void TTestDfc::Run(TAny* aPtr)
   1.136 +	{
   1.137 +	TUint32 id = (TUint32)aPtr;
   1.138 +	TUint32 tid = 0;
   1.139 +	TUint32 ctx = NKern::CurrentContext();
   1.140 +	TUint32 cpu = NKern::CurrentCpu();
   1.141 +	if (ctx == NKern::EThread)
   1.142 +		{
   1.143 +		NThread* t = NKern::CurrentThread();
   1.144 +		tid = t->iNThreadBaseSpare7;
   1.145 +		}
   1.146 +	TUint32 x = (cpu<<24) | (ctx<<16) | (tid<<8) | id;
   1.147 +	TInt r = Buffer->TryPut(x);
   1.148 +	if (r != KErrNone)
   1.149 +		Full = TRUE;
   1.150 +	Last = id;
   1.151 +	}
   1.152 +
   1.153 +void TTestDfc::CheckEmpty(TInt aLine)
   1.154 +	{
   1.155 +	TInt c = Buffer->Count();
   1.156 +	TUint32 x;
   1.157 +	Buffer->TryGet(x);
   1.158 +	if (c!=0)
   1.159 +		{
   1.160 +		TEST_PRINT3("Line %d Buffer not empty C:%d X:%08x", aLine, c, x);
   1.161 +		}
   1.162 +	}
   1.163 +
   1.164 +void TTestDfc::CheckFirstEntry(TInt aLine, TUint32 aCpu, TUint32 aContext, TDfcQue* aQ, TUint32 aId)
   1.165 +	{
   1.166 +	TUint32 tid = aQ ? aQ->iThread->iNThreadBaseSpare7 : 0;
   1.167 +	TUint32 expected = (aCpu<<24) | (aContext<<16) | (tid << 8) | aId;
   1.168 +	TUint32 x;
   1.169 +	TInt r = Buffer->TryGet(x);
   1.170 +	if (r!=KErrNone)
   1.171 +		{
   1.172 +		TEST_PRINT2("Line %d Buffer empty, Expected %08x", aLine, expected);
   1.173 +		}
   1.174 +	else if (x != expected)
   1.175 +		{
   1.176 +		TEST_PRINT3("Line %d Got %08x Expected %08x", aLine, x, expected);
   1.177 +		}
   1.178 +	}
   1.179 +
   1.180 +class TPauseIDFC : public TDfc
   1.181 +	{
   1.182 +public:
   1.183 +	TPauseIDFC();
   1.184 +	void Pause(TInt aCpu);
   1.185 +	void Release();
   1.186 +	static void Run(TAny*);
   1.187 +public:
   1.188 +	volatile TInt iFlag;
   1.189 +	};
   1.190 +
   1.191 +TPauseIDFC::TPauseIDFC()
   1.192 +	:	TDfc(&Run, this),
   1.193 +		iFlag(-1)
   1.194 +	{
   1.195 +	}
   1.196 +
   1.197 +void TPauseIDFC::Pause(TInt aCpu)
   1.198 +	{
   1.199 +	TAddDfc adder;
   1.200 +	iFlag = -1;
   1.201 +	__e32_memory_barrier();
   1.202 +	adder.Add(this, 1u<<aCpu);
   1.203 +	adder.WaitCompletion();
   1.204 +	while (iFlag == -1)
   1.205 +		{}
   1.206 +	}
   1.207 +
   1.208 +void TPauseIDFC::Release()
   1.209 +	{
   1.210 +	__e32_atomic_store_ord32(&iFlag, 1);
   1.211 +	}
   1.212 +
   1.213 +void TPauseIDFC::Run(TAny* aPtr)
   1.214 +	{
   1.215 +	TPauseIDFC* p = (TPauseIDFC*)aPtr;
   1.216 +	__e32_atomic_store_ord32(&p->iFlag, 0);
   1.217 +	while (__e32_atomic_load_acq32(&p->iFlag) == 0)
   1.218 +		{}
   1.219 +	}
   1.220 +
   1.221 +class TPauseDFC : public TDfc
   1.222 +	{
   1.223 +public:
   1.224 +	TPauseDFC(TDfcQue* aQ);
   1.225 +	void Pause(TInt aWait=0);
   1.226 +	void BusyPause();
   1.227 +	void Release();
   1.228 +	static void Run(TAny*);
   1.229 +public:
   1.230 +	NFastSemaphore* volatile iSem;
   1.231 +	volatile TInt iWait;
   1.232 +	};
   1.233 +
   1.234 +TPauseDFC::TPauseDFC(TDfcQue* aQ)
   1.235 +	:	TDfc(&Run, this, aQ, 0),
   1.236 +		iSem(0)
   1.237 +	{
   1.238 +	}
   1.239 +
   1.240 +void TPauseDFC::Pause(TInt aWait)
   1.241 +	{
   1.242 +	iWait = aWait;
   1.243 +	NFastSemaphore entrySem(0);
   1.244 +	iSem = &entrySem;
   1.245 +	Enque();
   1.246 +	NKern::FSWait(&entrySem);
   1.247 +	}
   1.248 +
   1.249 +void TPauseDFC::BusyPause()
   1.250 +	{
   1.251 +	volatile TInt& flag = (volatile TInt&)iSem;
   1.252 +	__e32_atomic_store_ord32(&flag, 0xfffffffe);
   1.253 +	Enque();
   1.254 +	while (__e32_atomic_load_acq32(&flag) == 0xfffffffe)
   1.255 +		{}
   1.256 +	}
   1.257 +
   1.258 +void TPauseDFC::Release()
   1.259 +	{
   1.260 +	NFastSemaphore* s = (NFastSemaphore*)__e32_atomic_swp_ord_ptr(&iSem, 0);
   1.261 +	if (((TInt)s)==-1)
   1.262 +		{
   1.263 +		volatile TInt& flag = (volatile TInt&)iSem;
   1.264 +		__e32_atomic_store_ord32(&flag, 0);
   1.265 +		}
   1.266 +	else
   1.267 +		NKern::FSSignal(s);
   1.268 +	}
   1.269 +
   1.270 +void TPauseDFC::Run(TAny* aPtr)
   1.271 +	{
   1.272 +	TPauseDFC* p = (TPauseDFC*)aPtr;
   1.273 +	volatile TInt& flag = (volatile TInt&)p->iSem;
   1.274 +	if (flag == -2)
   1.275 +		{
   1.276 +		flag = -1;
   1.277 +		__e32_memory_barrier();
   1.278 +		while (flag == -1)
   1.279 +			{}
   1.280 +		}
   1.281 +	else
   1.282 +		{
   1.283 +		NFastSemaphore exitSem(0);
   1.284 +		NFastSemaphore* s = (NFastSemaphore*)__e32_atomic_swp_ord_ptr(&p->iSem, &exitSem);
   1.285 +		if (p->iWait)
   1.286 +			{
   1.287 +			nfcfspin(__microseconds_to_norm_fast_counter(10000));
   1.288 +			NKern::Sleep(p->iWait);
   1.289 +			}
   1.290 +		NKern::FSSignal(s);
   1.291 +		NKern::FSWait(&exitSem);
   1.292 +		}
   1.293 +	}
   1.294 +
   1.295 +void DoDFCTest1()
   1.296 +	{
   1.297 +	TEST_PRINT("DFCTest1");
   1.298 +	TInt cpu;
   1.299 +	for_each_cpu(cpu)
   1.300 +		{
   1.301 +		TDfcQue* q = CreateDfcQ("DfcQ0", 1, cpu);
   1.302 +		DestroyDfcQ(q);
   1.303 +		q = CreateDfcQ("DfcQ1", 32, cpu);
   1.304 +		DestroyDfcQ(q);
   1.305 +		}
   1.306 +	}
   1.307 +
   1.308 +TBool QueueDfc(TDfc* aDfc, TInt aMode, TBool aExRet)
   1.309 +	{
   1.310 +	if (aMode==0)
   1.311 +		return !aExRet == !aDfc->Enque();
   1.312 +	else if (aMode>0)
   1.313 +		{
   1.314 +		TAddDfc adder;
   1.315 +		TInt cpu = aMode - 1;
   1.316 +		adder.Add(aDfc, 1u<<cpu);
   1.317 +		adder.WaitCompletion();
   1.318 +		nfcfspin(__microseconds_to_norm_fast_counter(10000));
   1.319 +		return TRUE;
   1.320 +		}
   1.321 +	else if (aMode==-1)
   1.322 +		{
   1.323 +		NKern::Lock();
   1.324 +		TBool ret = aDfc->Add();
   1.325 +		NKern::Unlock();
   1.326 +		return !aExRet == !ret;
   1.327 +		}
   1.328 +	return FALSE;
   1.329 +	}
   1.330 +
   1.331 +#define QUEUE_DFC(dfc, mode, exret)	TEST_RESULT(QueueDfc(dfc,mode,exret),"")
   1.332 +
   1.333 +void DoDFCTest2()
   1.334 +	{
   1.335 +	TEST_PRINT("DFCTest2");
   1.336 +	TInt num_cpus = NKern::NumberOfCpus();
   1.337 +	TInt this_cpu = NKern::CurrentCpu();
   1.338 +	TDfcQue* q;
   1.339 +	q = CreateDfcQ("DfcQ2", 1, this_cpu);
   1.340 +	TEST_OOM(q);
   1.341 +	q->iThread->iNThreadBaseSpare7 = 1;
   1.342 +
   1.343 +	TTestDfc* d1 = new TTestDfc(1, q, 1);
   1.344 +	TEST_OOM(d1);
   1.345 +	TEST_RESULT(!d1->IsIDFC(), "");
   1.346 +	TTestDfc* d2 = new TTestDfc(2, q, 2);
   1.347 +	TEST_OOM(d2);
   1.348 +	TEST_RESULT(!d2->IsIDFC(), "");
   1.349 +	TTestDfc* d3 = new TTestDfc(3, q, 2);
   1.350 +	TEST_OOM(d3);
   1.351 +	TEST_RESULT(!d3->IsIDFC(), "");
   1.352 +	TTestDfc* d4 = new TTestDfc(4, q, 3);
   1.353 +	TEST_OOM(d4);
   1.354 +	TEST_RESULT(!d4->IsIDFC(), "");
   1.355 +
   1.356 +	TInt mode;
   1.357 +	for (mode=-1; mode<=num_cpus; ++mode)
   1.358 +		{
   1.359 +		TEST_PRINT1("Mode %d", mode);
   1.360 +		CHECK_EMPTY();
   1.361 +		TEST_RESULT(!d1->Queued(), "");
   1.362 +		QUEUE_DFC(d1, mode, TRUE);
   1.363 +		TEST_RESULT(d1->Queued(), "");
   1.364 +		QUEUE_DFC(d1, mode, FALSE);
   1.365 +		TEST_RESULT(d1->Queued(), "");
   1.366 +		QUEUE_DFC(d2, mode, TRUE);
   1.367 +		QUEUE_DFC(d3, mode, TRUE);
   1.368 +		QUEUE_DFC(d4, mode, TRUE);
   1.369 +		CHECK_EMPTY();
   1.370 +		NKern::Sleep(30);
   1.371 +		CHECK_FIRST_ENTRY(this_cpu, NKern::EThread, q, 4);
   1.372 +		CHECK_FIRST_ENTRY(this_cpu, NKern::EThread, q, 2);
   1.373 +		CHECK_FIRST_ENTRY(this_cpu, NKern::EThread, q, 3);
   1.374 +		CHECK_FIRST_ENTRY(this_cpu, NKern::EThread, q, 1);
   1.375 +		CHECK_EMPTY();
   1.376 +		QUEUE_DFC(d4, mode, TRUE);
   1.377 +		QUEUE_DFC(d3, mode, TRUE);
   1.378 +		QUEUE_DFC(d2, mode, TRUE);
   1.379 +		QUEUE_DFC(d1, mode, TRUE);
   1.380 +		CHECK_EMPTY();
   1.381 +		NKern::Sleep(30);
   1.382 +		CHECK_FIRST_ENTRY(this_cpu, NKern::EThread, q, 4);
   1.383 +		CHECK_FIRST_ENTRY(this_cpu, NKern::EThread, q, 3);
   1.384 +		CHECK_FIRST_ENTRY(this_cpu, NKern::EThread, q, 2);
   1.385 +		CHECK_FIRST_ENTRY(this_cpu, NKern::EThread, q, 1);
   1.386 +		CHECK_EMPTY();
   1.387 +		QUEUE_DFC(d4, mode, TRUE);
   1.388 +		QUEUE_DFC(d3, mode, TRUE);
   1.389 +		QUEUE_DFC(d2, mode, TRUE);
   1.390 +		QUEUE_DFC(d1, mode, TRUE);
   1.391 +		TEST_RESULT(d4->Queued(), "");
   1.392 +		TEST_RESULT(d4->Cancel(), "");
   1.393 +		TEST_RESULT(!d4->Cancel(), "");
   1.394 +		TEST_RESULT(!d4->Queued(), "");
   1.395 +		CHECK_EMPTY();
   1.396 +		NKern::Sleep(30);
   1.397 +		CHECK_FIRST_ENTRY(this_cpu, NKern::EThread, q, 3);
   1.398 +		CHECK_FIRST_ENTRY(this_cpu, NKern::EThread, q, 2);
   1.399 +		CHECK_FIRST_ENTRY(this_cpu, NKern::EThread, q, 1);
   1.400 +		CHECK_EMPTY();
   1.401 +		QUEUE_DFC(d4, mode, TRUE);
   1.402 +		QUEUE_DFC(d3, mode, TRUE);
   1.403 +		QUEUE_DFC(d2, mode, TRUE);
   1.404 +		QUEUE_DFC(d1, mode, TRUE);
   1.405 +		TEST_RESULT(d3->Queued(), "");
   1.406 +		TEST_RESULT(d3->Cancel(), "");
   1.407 +		TEST_RESULT(!d3->Queued(), "");
   1.408 +		CHECK_EMPTY();
   1.409 +		NKern::Sleep(30);
   1.410 +		CHECK_FIRST_ENTRY(this_cpu, NKern::EThread, q, 4);
   1.411 +		CHECK_FIRST_ENTRY(this_cpu, NKern::EThread, q, 2);
   1.412 +		CHECK_FIRST_ENTRY(this_cpu, NKern::EThread, q, 1);
   1.413 +		CHECK_EMPTY();
   1.414 +		QUEUE_DFC(d4, mode, TRUE);
   1.415 +		QUEUE_DFC(d3, mode, TRUE);
   1.416 +		QUEUE_DFC(d2, mode, TRUE);
   1.417 +		QUEUE_DFC(d1, mode, TRUE);
   1.418 +		TEST_RESULT(d3->Queued(), "");
   1.419 +		TEST_RESULT(d2->Queued(), "");
   1.420 +		TEST_RESULT(d3->Cancel(), "");
   1.421 +		TEST_RESULT(d2->Cancel(), "");
   1.422 +		TEST_RESULT(!d3->Queued(), "");
   1.423 +		TEST_RESULT(!d2->Queued(), "");
   1.424 +		CHECK_EMPTY();
   1.425 +		NKern::Sleep(30);
   1.426 +		CHECK_FIRST_ENTRY(this_cpu, NKern::EThread, q, 4);
   1.427 +		CHECK_FIRST_ENTRY(this_cpu, NKern::EThread, q, 1);
   1.428 +		CHECK_EMPTY();
   1.429 +		QUEUE_DFC(d4, mode, TRUE);
   1.430 +		QUEUE_DFC(d3, mode, TRUE);
   1.431 +		QUEUE_DFC(d2, mode, TRUE);
   1.432 +		QUEUE_DFC(d1, mode, TRUE);
   1.433 +		TEST_RESULT(d3->Cancel(), "");
   1.434 +		TEST_RESULT(d2->Cancel(), "");
   1.435 +		TEST_RESULT(d4->Cancel(), "");
   1.436 +		TEST_RESULT(d1->Cancel(), "");
   1.437 +		CHECK_EMPTY();
   1.438 +		NKern::Sleep(30);
   1.439 +		CHECK_EMPTY();
   1.440 +		QUEUE_DFC(d4, mode, TRUE);
   1.441 +		QUEUE_DFC(d3, mode, TRUE);
   1.442 +		QUEUE_DFC(d2, mode, TRUE);
   1.443 +		QUEUE_DFC(d1, mode, TRUE);
   1.444 +		TEST_RESULT(d1->Queued(), "");
   1.445 +		TEST_RESULT(d3->Cancel(), "");
   1.446 +		TEST_RESULT(d2->Cancel(), "");
   1.447 +		TEST_RESULT(d4->Cancel(), "");
   1.448 +		TEST_RESULT(d1->Cancel(), "");
   1.449 +		TEST_RESULT(!d1->Queued(), "");
   1.450 +		QUEUE_DFC(d1, mode, TRUE);
   1.451 +		TEST_RESULT(d1->Queued(), "");
   1.452 +		QUEUE_DFC(d1, mode, FALSE);
   1.453 +		TEST_RESULT(d1->Queued(), "");
   1.454 +		CHECK_EMPTY();
   1.455 +		NKern::Sleep(30);
   1.456 +		CHECK_FIRST_ENTRY(this_cpu, NKern::EThread, q, 1);
   1.457 +		CHECK_EMPTY();
   1.458 +		}
   1.459 +
   1.460 +	delete d4;
   1.461 +	delete d3;
   1.462 +	delete d2;
   1.463 +	delete d1;
   1.464 +	DestroyDfcQ(q);
   1.465 +	}
   1.466 +
   1.467 +void DoDFCTest3(TInt aCpu)
   1.468 +	{
   1.469 +	TEST_PRINT1("DFCTest3 CPU %d", aCpu);
   1.470 +	TInt num_cpus = NKern::NumberOfCpus();
   1.471 +	TInt this_cpu = NKern::CurrentCpu();
   1.472 +	TBool same_cpu = (aCpu==this_cpu);
   1.473 +	TDfcQue* q;
   1.474 +	q = CreateDfcQ("DfcQ2", 32, aCpu);
   1.475 +	TEST_OOM(q);
   1.476 +	q->iThread->iNThreadBaseSpare7 = 1;
   1.477 +	TPauseDFC pauser(q);
   1.478 +
   1.479 +	TTestDfc* d1 = new TTestDfc(1, q, 1);
   1.480 +	TEST_OOM(d1);
   1.481 +	TEST_RESULT(!d1->IsIDFC(), "");
   1.482 +	TTestDfc* d2 = new TTestDfc(2, q, 2);
   1.483 +	TEST_OOM(d2);
   1.484 +	TEST_RESULT(!d2->IsIDFC(), "");
   1.485 +	TTestDfc* d3 = new TTestDfc(3, q, 2);
   1.486 +	TEST_OOM(d3);
   1.487 +	TEST_RESULT(!d3->IsIDFC(), "");
   1.488 +	TTestDfc* d4 = new TTestDfc(4, q, 3);
   1.489 +	TEST_OOM(d4);
   1.490 +	TEST_RESULT(!d4->IsIDFC(), "");
   1.491 +
   1.492 +	TInt mode;
   1.493 +	for (mode=-1; mode<=num_cpus; ++mode)
   1.494 +		{
   1.495 +		TEST_PRINT1("Mode %d", mode);
   1.496 +		CHECK_EMPTY();
   1.497 +		TEST_RESULT(!d1->Queued(), "");
   1.498 +		QUEUE_DFC(d1, mode, TRUE);
   1.499 +		if (!same_cpu)
   1.500 +			while (d1->Queued()) {}
   1.501 +		TEST_RESULT(!d1->Queued(), "");
   1.502 +		QUEUE_DFC(d1, mode, TRUE);
   1.503 +		if (!same_cpu)
   1.504 +			while (d1->Queued()) {}
   1.505 +		TEST_RESULT(!d1->Queued(), "");
   1.506 +		QUEUE_DFC(d2, mode, TRUE);
   1.507 +		if (!same_cpu)
   1.508 +			while (d2->Queued()) {}
   1.509 +		QUEUE_DFC(d3, mode, TRUE);
   1.510 +		if (!same_cpu)
   1.511 +			while (d3->Queued()) {}
   1.512 +		QUEUE_DFC(d4, mode, TRUE);
   1.513 +		if (!same_cpu)
   1.514 +			while (d4->Queued()) {}
   1.515 +		CHECK_FIRST_ENTRY(aCpu, NKern::EThread, q, 1);
   1.516 +		CHECK_FIRST_ENTRY(aCpu, NKern::EThread, q, 1);
   1.517 +		CHECK_FIRST_ENTRY(aCpu, NKern::EThread, q, 2);
   1.518 +		CHECK_FIRST_ENTRY(aCpu, NKern::EThread, q, 3);
   1.519 +		CHECK_FIRST_ENTRY(aCpu, NKern::EThread, q, 4);
   1.520 +		CHECK_EMPTY();
   1.521 +		QUEUE_DFC(d4, mode, TRUE);
   1.522 +		QUEUE_DFC(d3, mode, TRUE);
   1.523 +		QUEUE_DFC(d2, mode, TRUE);
   1.524 +		QUEUE_DFC(d1, mode, TRUE);
   1.525 +		if (!same_cpu)
   1.526 +			while (d1->Queued()) {}
   1.527 +		CHECK_FIRST_ENTRY(aCpu, NKern::EThread, q, 4);
   1.528 +		CHECK_FIRST_ENTRY(aCpu, NKern::EThread, q, 3);
   1.529 +		CHECK_FIRST_ENTRY(aCpu, NKern::EThread, q, 2);
   1.530 +		CHECK_FIRST_ENTRY(aCpu, NKern::EThread, q, 1);
   1.531 +		CHECK_EMPTY();
   1.532 +		QUEUE_DFC(d4, mode, TRUE);
   1.533 +		QUEUE_DFC(d3, mode, TRUE);
   1.534 +		QUEUE_DFC(d2, mode, TRUE);
   1.535 +		QUEUE_DFC(d1, mode, TRUE);
   1.536 +		if (!same_cpu)
   1.537 +			while (d1->Queued()) {}
   1.538 +		TEST_RESULT(!d4->Queued(), "");
   1.539 +		TEST_RESULT(!d4->Cancel(), "");
   1.540 +		TEST_RESULT(!d4->Queued(), "");
   1.541 +		CHECK_FIRST_ENTRY(aCpu, NKern::EThread, q, 4);
   1.542 +		CHECK_FIRST_ENTRY(aCpu, NKern::EThread, q, 3);
   1.543 +		CHECK_FIRST_ENTRY(aCpu, NKern::EThread, q, 2);
   1.544 +		CHECK_FIRST_ENTRY(aCpu, NKern::EThread, q, 1);
   1.545 +		CHECK_EMPTY();
   1.546 +		pauser.Pause();
   1.547 +		CHECK_EMPTY();
   1.548 +		TEST_RESULT(!d1->Queued(), "");
   1.549 +		QUEUE_DFC(d1, mode, TRUE);
   1.550 +		TEST_RESULT(d1->Queued(), "");
   1.551 +		QUEUE_DFC(d1, mode, FALSE);
   1.552 +		TEST_RESULT(d1->Queued(), "");
   1.553 +		QUEUE_DFC(d2, mode, TRUE);
   1.554 +		QUEUE_DFC(d3, mode, TRUE);
   1.555 +		QUEUE_DFC(d4, mode, TRUE);
   1.556 +		QUEUE_DFC(d4, mode, FALSE);
   1.557 +		CHECK_EMPTY();
   1.558 +		pauser.Release();
   1.559 +		pauser.Pause();
   1.560 +		pauser.Release();
   1.561 +		CHECK_FIRST_ENTRY(aCpu, NKern::EThread, q, 4);
   1.562 +		CHECK_FIRST_ENTRY(aCpu, NKern::EThread, q, 2);
   1.563 +		CHECK_FIRST_ENTRY(aCpu, NKern::EThread, q, 3);
   1.564 +		CHECK_FIRST_ENTRY(aCpu, NKern::EThread, q, 1);
   1.565 +		CHECK_EMPTY();
   1.566 +		pauser.Pause();
   1.567 +		CHECK_EMPTY();
   1.568 +		TEST_RESULT(!d1->Queued(), "");
   1.569 +		QUEUE_DFC(d1, mode, TRUE);
   1.570 +		TEST_RESULT(d1->Queued(), "");
   1.571 +		QUEUE_DFC(d1, mode, FALSE);
   1.572 +		TEST_RESULT(d1->Queued(), "");
   1.573 +		QUEUE_DFC(d4, mode, TRUE);
   1.574 +		QUEUE_DFC(d3, mode, TRUE);
   1.575 +		QUEUE_DFC(d2, mode, TRUE);
   1.576 +		CHECK_EMPTY();
   1.577 +		pauser.Release();
   1.578 +		pauser.Pause();
   1.579 +		pauser.Release();
   1.580 +		CHECK_FIRST_ENTRY(aCpu, NKern::EThread, q, 4);
   1.581 +		CHECK_FIRST_ENTRY(aCpu, NKern::EThread, q, 3);
   1.582 +		CHECK_FIRST_ENTRY(aCpu, NKern::EThread, q, 2);
   1.583 +		CHECK_FIRST_ENTRY(aCpu, NKern::EThread, q, 1);
   1.584 +		CHECK_EMPTY();
   1.585 +		pauser.Pause();
   1.586 +		CHECK_EMPTY();
   1.587 +		TEST_RESULT(!d1->Queued(), "");
   1.588 +		QUEUE_DFC(d1, mode, TRUE);
   1.589 +		TEST_RESULT(d1->Queued(), "");
   1.590 +		QUEUE_DFC(d1, mode, FALSE);
   1.591 +		TEST_RESULT(d1->Queued(), "");
   1.592 +		QUEUE_DFC(d2, mode, TRUE);
   1.593 +		QUEUE_DFC(d3, mode, TRUE);
   1.594 +		QUEUE_DFC(d4, mode, TRUE);
   1.595 +		CHECK_EMPTY();
   1.596 +		TEST_RESULT(d1->Cancel(), "");
   1.597 +		TEST_RESULT(!d1->Queued(), "");
   1.598 +		pauser.Release();
   1.599 +		pauser.Pause();
   1.600 +		pauser.Release();
   1.601 +		CHECK_FIRST_ENTRY(aCpu, NKern::EThread, q, 4);
   1.602 +		CHECK_FIRST_ENTRY(aCpu, NKern::EThread, q, 2);
   1.603 +		CHECK_FIRST_ENTRY(aCpu, NKern::EThread, q, 3);
   1.604 +		CHECK_EMPTY();
   1.605 +		}
   1.606 +
   1.607 +	delete d4;
   1.608 +	delete d3;
   1.609 +	delete d2;
   1.610 +	delete d1;
   1.611 +	DestroyDfcQ(q);
   1.612 +	}
   1.613 +
   1.614 +TBool QueueIDfc(TDfc* aDfc, TInt aMode, TBool aExRet)
   1.615 +	{
   1.616 +	if (aMode==0)
   1.617 +		return !aExRet == !aDfc->RawAdd();
   1.618 +	else if (aMode>0)
   1.619 +		{
   1.620 +		TTestDfc::Last = 0xffffffffu;
   1.621 +		TAddDfc adder;
   1.622 +		TInt cpu = (aMode&0xff) - 1;
   1.623 +		adder.Add(aDfc, 1u<<cpu);
   1.624 +		adder.WaitCompletion();
   1.625 +		if (!(aMode&0x100))
   1.626 +			{
   1.627 +			while (TTestDfc::Last != (TUint32)aDfc->iPtr)
   1.628 +				{}
   1.629 +			}
   1.630 +		return TRUE;
   1.631 +		}
   1.632 +	else if (aMode==-1)
   1.633 +		{
   1.634 +		NKern::Lock();
   1.635 +		TBool ret = aDfc->Add();
   1.636 +		NKern::Unlock();
   1.637 +		return !aExRet == !ret;
   1.638 +		}
   1.639 +	return FALSE;
   1.640 +	}
   1.641 +
   1.642 +#define QUEUE_IDFC(dfc, mode, exret)	TEST_RESULT(QueueIDfc(dfc,mode,exret),"")
   1.643 +
   1.644 +void DoIDFCTest1()
   1.645 +	{
   1.646 +	TEST_PRINT("IDFCTest1");
   1.647 +
   1.648 +	TInt num_cpus = NKern::NumberOfCpus();
   1.649 +	TInt this_cpu = NKern::CurrentCpu();
   1.650 +
   1.651 +	TTestDfc* d1 = new TTestDfc(1);
   1.652 +	TEST_OOM(d1);
   1.653 +	TEST_RESULT(d1->IsIDFC(), "");
   1.654 +	TTestDfc* d2 = new TTestDfc(2);
   1.655 +	TEST_OOM(d2);
   1.656 +	TEST_RESULT(d2->IsIDFC(), "");
   1.657 +	TTestDfc* d3 = new TTestDfc(3);
   1.658 +	TEST_OOM(d3);
   1.659 +	TEST_RESULT(d3->IsIDFC(), "");
   1.660 +	TTestDfc* d4 = new TTestDfc(4);
   1.661 +	TEST_OOM(d4);
   1.662 +	TEST_RESULT(d4->IsIDFC(), "");
   1.663 +
   1.664 +	TInt mode;
   1.665 +	for (mode=-1; mode<=num_cpus; ++mode)
   1.666 +		{
   1.667 +		TInt xcpu = (mode>0) ? (mode-1) : this_cpu;
   1.668 +		TEST_PRINT1("Mode %d", mode);
   1.669 +		CHECK_EMPTY();
   1.670 +		TEST_RESULT(!d1->Queued(), "");
   1.671 +		QUEUE_IDFC(d1, mode, TRUE);
   1.672 +		TEST_RESULT(!d1->Queued(), "");
   1.673 +		QUEUE_IDFC(d1, mode, TRUE);
   1.674 +		TEST_RESULT(!d1->Queued(), "");
   1.675 +		QUEUE_IDFC(d2, mode, TRUE);
   1.676 +		QUEUE_IDFC(d3, mode, TRUE);
   1.677 +		QUEUE_IDFC(d4, mode, TRUE);
   1.678 +		CHECK_FIRST_ENTRY(xcpu, NKern::EIDFC, 0, 1);
   1.679 +		CHECK_FIRST_ENTRY(xcpu, NKern::EIDFC, 0, 1);
   1.680 +		CHECK_FIRST_ENTRY(xcpu, NKern::EIDFC, 0, 2);
   1.681 +		CHECK_FIRST_ENTRY(xcpu, NKern::EIDFC, 0, 3);
   1.682 +		CHECK_FIRST_ENTRY(xcpu, NKern::EIDFC, 0, 4);
   1.683 +		CHECK_EMPTY();
   1.684 +		QUEUE_IDFC(d4, mode, TRUE);
   1.685 +		QUEUE_IDFC(d3, mode, TRUE);
   1.686 +		QUEUE_IDFC(d2, mode, TRUE);
   1.687 +		QUEUE_IDFC(d1, mode, TRUE);
   1.688 +		CHECK_FIRST_ENTRY(xcpu, NKern::EIDFC, 0, 4);
   1.689 +		CHECK_FIRST_ENTRY(xcpu, NKern::EIDFC, 0, 3);
   1.690 +		CHECK_FIRST_ENTRY(xcpu, NKern::EIDFC, 0, 2);
   1.691 +		CHECK_FIRST_ENTRY(xcpu, NKern::EIDFC, 0, 1);
   1.692 +		CHECK_EMPTY();
   1.693 +		}
   1.694 +	TInt irq = NKern::DisableAllInterrupts();
   1.695 +	TEST_RESULT(d1->RawAdd(), "");
   1.696 +	TEST_RESULT(d1->Queued(), "");
   1.697 +	CHECK_EMPTY();
   1.698 +	NKern::RestoreInterrupts(irq);
   1.699 +	TEST_RESULT(!d1->Queued(), "");
   1.700 +	CHECK_FIRST_ENTRY(this_cpu, NKern::EIDFC, 0, 1);
   1.701 +
   1.702 +	NKern::Lock();
   1.703 +	TEST_RESULT(d1->Add(), "");
   1.704 +	TEST_RESULT(d3->Add(), "");
   1.705 +	TEST_RESULT(d2->Add(), "");
   1.706 +	TEST_RESULT(d4->Add(), "");
   1.707 +	TEST_RESULT(!d1->Add(), "");
   1.708 +	TEST_RESULT(d1->Queued(), "");
   1.709 +	TEST_RESULT(d2->Queued(), "");
   1.710 +	TEST_RESULT(d3->Queued(), "");
   1.711 +	TEST_RESULT(d4->Queued(), "");
   1.712 +	CHECK_EMPTY();
   1.713 +	NKern::Unlock();
   1.714 +	TEST_RESULT(!d1->Queued(), "");
   1.715 +	TEST_RESULT(!d2->Queued(), "");
   1.716 +	TEST_RESULT(!d3->Queued(), "");
   1.717 +	TEST_RESULT(!d4->Queued(), "");
   1.718 +	CHECK_FIRST_ENTRY(this_cpu, NKern::EIDFC, 0, 1);
   1.719 +	CHECK_FIRST_ENTRY(this_cpu, NKern::EIDFC, 0, 3);
   1.720 +	CHECK_FIRST_ENTRY(this_cpu, NKern::EIDFC, 0, 2);
   1.721 +	CHECK_FIRST_ENTRY(this_cpu, NKern::EIDFC, 0, 4);
   1.722 +	CHECK_EMPTY();
   1.723 +
   1.724 +	NKern::Lock();
   1.725 +	TEST_RESULT(d1->Add(), "");
   1.726 +	TEST_RESULT(d3->Add(), "");
   1.727 +	TEST_RESULT(d2->Add(), "");
   1.728 +	TEST_RESULT(d4->Add(), "");
   1.729 +	TEST_RESULT(d1->Queued(), "");
   1.730 +	TEST_RESULT(d2->Queued(), "");
   1.731 +	TEST_RESULT(d3->Queued(), "");
   1.732 +	TEST_RESULT(d4->Queued(), "");
   1.733 +	TEST_RESULT(d3->Cancel(), "");
   1.734 +	TEST_RESULT(!d3->Queued(), "");
   1.735 +	TEST_RESULT(!d3->Cancel(), "");
   1.736 +	CHECK_EMPTY();
   1.737 +	NKern::Unlock();
   1.738 +	TEST_RESULT(!d1->Queued(), "");
   1.739 +	TEST_RESULT(!d2->Queued(), "");
   1.740 +	TEST_RESULT(!d4->Queued(), "");
   1.741 +	CHECK_FIRST_ENTRY(this_cpu, NKern::EIDFC, 0, 1);
   1.742 +	CHECK_FIRST_ENTRY(this_cpu, NKern::EIDFC, 0, 2);
   1.743 +	CHECK_FIRST_ENTRY(this_cpu, NKern::EIDFC, 0, 4);
   1.744 +	CHECK_EMPTY();
   1.745 +
   1.746 +	NKern::Lock();
   1.747 +	TEST_RESULT(d1->Add(), "");
   1.748 +	TEST_RESULT(d3->Add(), "");
   1.749 +	TEST_RESULT(d2->Add(), "");
   1.750 +	TEST_RESULT(d4->Add(), "");
   1.751 +	TEST_RESULT(d1->Queued(), "");
   1.752 +	TEST_RESULT(d2->Queued(), "");
   1.753 +	TEST_RESULT(d3->Queued(), "");
   1.754 +	TEST_RESULT(d4->Queued(), "");
   1.755 +	TEST_RESULT(d3->Cancel(), "");
   1.756 +	TEST_RESULT(d1->Cancel(), "");
   1.757 +	TEST_RESULT(d2->Cancel(), "");
   1.758 +	TEST_RESULT(d4->Cancel(), "");
   1.759 +	TEST_RESULT(!d1->Queued(), "");
   1.760 +	TEST_RESULT(!d2->Queued(), "");
   1.761 +	TEST_RESULT(!d3->Queued(), "");
   1.762 +	TEST_RESULT(!d4->Queued(), "");
   1.763 +	CHECK_EMPTY();
   1.764 +	NKern::Unlock();
   1.765 +	CHECK_EMPTY();
   1.766 +
   1.767 +	TPauseIDFC pauser;
   1.768 +	TInt cpu;
   1.769 +	for_each_cpu(cpu)
   1.770 +		{
   1.771 +		if (cpu == this_cpu)
   1.772 +			continue;
   1.773 +		mode = cpu + 0x101;
   1.774 +		TEST_PRINT1("CPU %d", cpu);
   1.775 +		pauser.Pause(cpu);
   1.776 +		CHECK_EMPTY();
   1.777 +		TEST_RESULT(!d1->Queued(), "");
   1.778 +		QUEUE_IDFC(d1, mode, TRUE);
   1.779 +		TEST_RESULT(d1->Queued(), "");
   1.780 +		QUEUE_IDFC(d1, mode, FALSE);
   1.781 +		TEST_RESULT(d1->Queued(), "");
   1.782 +		QUEUE_IDFC(d2, mode, TRUE);
   1.783 +		QUEUE_IDFC(d3, mode, TRUE);
   1.784 +		QUEUE_IDFC(d4, mode, TRUE);
   1.785 +		CHECK_EMPTY();
   1.786 +		pauser.Release();
   1.787 +		pauser.Pause(cpu);
   1.788 +		pauser.Release();
   1.789 +		CHECK_FIRST_ENTRY(cpu, NKern::EIDFC, 0, 1);
   1.790 +		CHECK_FIRST_ENTRY(cpu, NKern::EIDFC, 0, 2);
   1.791 +		CHECK_FIRST_ENTRY(cpu, NKern::EIDFC, 0, 3);
   1.792 +		CHECK_FIRST_ENTRY(cpu, NKern::EIDFC, 0, 4);
   1.793 +		CHECK_EMPTY();
   1.794 +		pauser.Pause(cpu);
   1.795 +		CHECK_EMPTY();
   1.796 +		TEST_RESULT(!d1->Queued(), "");
   1.797 +		QUEUE_IDFC(d1, mode, TRUE);
   1.798 +		TEST_RESULT(d1->Queued(), "");
   1.799 +		QUEUE_IDFC(d2, mode, TRUE);
   1.800 +		QUEUE_IDFC(d3, mode, TRUE);
   1.801 +		QUEUE_IDFC(d4, mode, TRUE);
   1.802 +		TEST_RESULT(d1->Cancel(), "");
   1.803 +		TEST_RESULT(!d1->Queued(), "");
   1.804 +		TEST_RESULT(!d1->Cancel(), "");
   1.805 +		CHECK_EMPTY();
   1.806 +		pauser.Release();
   1.807 +		pauser.Pause(cpu);
   1.808 +		pauser.Release();
   1.809 +		CHECK_FIRST_ENTRY(cpu, NKern::EIDFC, 0, 2);
   1.810 +		CHECK_FIRST_ENTRY(cpu, NKern::EIDFC, 0, 3);
   1.811 +		CHECK_FIRST_ENTRY(cpu, NKern::EIDFC, 0, 4);
   1.812 +		CHECK_EMPTY();
   1.813 +		pauser.Pause(cpu);
   1.814 +		CHECK_EMPTY();
   1.815 +		TEST_RESULT(!d1->Queued(), "");
   1.816 +		QUEUE_IDFC(d1, mode, TRUE);
   1.817 +		TEST_RESULT(d1->Queued(), "");
   1.818 +		QUEUE_IDFC(d2, mode, TRUE);
   1.819 +		QUEUE_IDFC(d3, mode, TRUE);
   1.820 +		QUEUE_IDFC(d4, mode, TRUE);
   1.821 +		TEST_RESULT(d1->Cancel(), "");
   1.822 +		TEST_RESULT(!d1->Queued(), "");
   1.823 +		TEST_RESULT(d4->Cancel(), "");
   1.824 +		TEST_RESULT(d2->Cancel(), "");
   1.825 +		TEST_RESULT(d3->Cancel(), "");
   1.826 +		CHECK_EMPTY();
   1.827 +		pauser.Release();
   1.828 +		pauser.Pause(cpu);
   1.829 +		pauser.Release();
   1.830 +		CHECK_EMPTY();
   1.831 +		}
   1.832 +
   1.833 +	delete d4;
   1.834 +	delete d3;
   1.835 +	delete d2;
   1.836 +	delete d1;
   1.837 +	}
   1.838 +
   1.839 +void DoIdleDFCTest1(TInt aCpu)
   1.840 +	{
   1.841 +#ifdef __SMP__
   1.842 +	TEST_PRINT2("IdleDFCTest1 CPU %d (%08x)", aCpu, TheScheduler.iCpusNotIdle);
   1.843 +#else
   1.844 +	TEST_PRINT1("IdleDFCTest1 CPU %d (%08x)", aCpu);
   1.845 +#endif
   1.846 +//	TInt num_cpus = NKern::NumberOfCpus();
   1.847 +	TInt this_cpu = NKern::CurrentCpu();
   1.848 +	TBool same_cpu = (aCpu==this_cpu);
   1.849 +	TDfcQue* q = 0;
   1.850 +	TPauseDFC* pauser = 0;
   1.851 +	if (!same_cpu)
   1.852 +		{
   1.853 +		q = CreateDfcQ("DfcQ3", 1, aCpu);
   1.854 +		TEST_OOM(q);
   1.855 +		pauser = new TPauseDFC(q);
   1.856 +		TEST_OOM(pauser);
   1.857 +		}
   1.858 +
   1.859 +	TTestDfc* d1 = new TTestDfc(1);
   1.860 +	TEST_OOM(d1);
   1.861 +	TEST_RESULT(d1->IsIDFC(), "");
   1.862 +	TTestDfc* d2 = new TTestDfc(2);
   1.863 +	TEST_OOM(d2);
   1.864 +	TEST_RESULT(d2->IsIDFC(), "");
   1.865 +	TTestDfc* d3 = new TTestDfc(3);
   1.866 +	TEST_OOM(d3);
   1.867 +	TEST_RESULT(d3->IsIDFC(), "");
   1.868 +	TTestDfc* d4 = new TTestDfc(4);
   1.869 +	TEST_OOM(d4);
   1.870 +	TEST_RESULT(d4->IsIDFC(), "");
   1.871 +
   1.872 +	TEST_RESULT(!d1->Queued(), "");
   1.873 +	TEST_RESULT(d1->QueueOnIdle(), "");
   1.874 +	TEST_RESULT(d1->Queued(), "");
   1.875 +	TEST_RESULT(!d1->QueueOnIdle(), "");
   1.876 +	CHECK_EMPTY();
   1.877 +	if (pauser)
   1.878 +		pauser->BusyPause();
   1.879 +	NKern::Sleep(1);
   1.880 +	if (pauser)
   1.881 +		TEST_RESULT(d1->Queued(), "");
   1.882 +	else
   1.883 +		{
   1.884 +		TEST_RESULT(!d1->Queued(), "");
   1.885 +		CHECK_FIRST_ENTRY(this_cpu, NKern::EIDFC, 0, 1);
   1.886 +		}
   1.887 +	CHECK_EMPTY();
   1.888 +	TBool ret = d1->QueueOnIdle();
   1.889 +	TEST_RESULT(pauser?!ret:ret, "");
   1.890 +	TEST_RESULT(d1->Queued(), "");
   1.891 +	TEST_RESULT(d1->Cancel(), "");
   1.892 +	TEST_RESULT(!d1->Queued(), "");
   1.893 +	CHECK_EMPTY();
   1.894 +	NKern::Sleep(1);
   1.895 +	CHECK_EMPTY();
   1.896 +	if (pauser)
   1.897 +		pauser->Release();
   1.898 +	TEST_RESULT(d4->QueueOnIdle(), "");
   1.899 +	TEST_RESULT(d3->QueueOnIdle(), "");
   1.900 +	TEST_RESULT(d1->QueueOnIdle(), "");
   1.901 +	TEST_RESULT(d2->QueueOnIdle(), "");
   1.902 +	TEST_RESULT(d3->Cancel(), "");
   1.903 +	CHECK_EMPTY();
   1.904 +	TInt xcpu = this_cpu;
   1.905 +	if (pauser)
   1.906 +		{
   1.907 +		xcpu = aCpu;
   1.908 +		pauser->Pause(1);
   1.909 +		pauser->Release();
   1.910 +		}
   1.911 +	else
   1.912 +		NKern::Sleep(1);
   1.913 +	CHECK_FIRST_ENTRY(xcpu, NKern::EIDFC, 0, 4);
   1.914 +	CHECK_FIRST_ENTRY(xcpu, NKern::EIDFC, 0, 1);
   1.915 +	CHECK_FIRST_ENTRY(xcpu, NKern::EIDFC, 0, 2);
   1.916 +	CHECK_EMPTY();
   1.917 +
   1.918 +	delete d4;
   1.919 +	delete d3;
   1.920 +	delete d2;
   1.921 +	delete d1;
   1.922 +	delete pauser;
   1.923 +	if (q)
   1.924 +		DestroyDfcQ(q);
   1.925 +	}
   1.926 +
   1.927 +TDfc* Dfcs[6];
   1.928 +NFastSemaphore* IdleDFCTest2Fs;
   1.929 +
   1.930 +void IdleDFCTest2Fn(TAny* a)
   1.931 +	{
   1.932 +	TUint32 id = (TUint32)a;
   1.933 +	if (id==1)
   1.934 +		{
   1.935 +		TEST_RESULT(Dfcs[1]->Cancel(), "");
   1.936 +		TEST_RESULT(Dfcs[3]->QueueOnIdle(), "");
   1.937 +		TEST_RESULT(Dfcs[4]->QueueOnIdle(), "");
   1.938 +		TEST_RESULT(Dfcs[5]->QueueOnIdle(), "");
   1.939 +		}
   1.940 +	if (id==1 || id==4)
   1.941 +		IdleDFCTest2Fs->Signal();
   1.942 +	if (id==3)
   1.943 +		{
   1.944 +		TEST_RESULT(Dfcs[5]->Cancel(), "");
   1.945 +		}
   1.946 +	TTestDfc::Run(a);
   1.947 +	}
   1.948 +
   1.949 +void DoIdleDFCTest2()
   1.950 +	{
   1.951 +	TEST_PRINT("IdleDFCTest2");
   1.952 +	NFastSemaphore sem(0);
   1.953 +	TInt this_cpu = NKern::CurrentCpu();
   1.954 +	TInt i;
   1.955 +	for (i=0; i<6; ++i)
   1.956 +		{
   1.957 +		Dfcs[i] = new TDfc(&IdleDFCTest2Fn, (TAny*)(i+1));
   1.958 +		TEST_OOM(Dfcs[i]);
   1.959 +		}
   1.960 +	TEST_RESULT(Dfcs[0]->QueueOnIdle(), "");
   1.961 +	TEST_RESULT(Dfcs[1]->QueueOnIdle(), "");
   1.962 +	TEST_RESULT(Dfcs[2]->QueueOnIdle(), "");
   1.963 +	IdleDFCTest2Fs = &sem;
   1.964 +	CHECK_EMPTY();
   1.965 +	NKern::FSWait(&sem);
   1.966 +	CHECK_FIRST_ENTRY(this_cpu, NKern::EIDFC, 0, 1);
   1.967 +	CHECK_FIRST_ENTRY(this_cpu, NKern::EIDFC, 0, 3);
   1.968 +	CHECK_EMPTY();
   1.969 +	NKern::FSWait(&sem);
   1.970 +	CHECK_FIRST_ENTRY(this_cpu, NKern::EIDFC, 0, 4);
   1.971 +	CHECK_FIRST_ENTRY(this_cpu, NKern::EIDFC, 0, 5);
   1.972 +	CHECK_EMPTY();
   1.973 +	for (i=0; i<6; ++i)
   1.974 +		delete Dfcs[i];
   1.975 +	}
   1.976 +
   1.977 +#ifdef __SMP__
   1.978 +
   1.979 +class TDfcStress;
   1.980 +class TDfcX
   1.981 +	{
   1.982 +public:
   1.983 +	enum
   1.984 +		{
   1.985 +		EFlag_IdleDFC=1,
   1.986 +		EFlag_IDFC=2,
   1.987 +		EFlag_DFC=4,
   1.988 +		EFlag_Timer=8,
   1.989 +		EFlag_Tied=16
   1.990 +		};
   1.991 +public:
   1.992 +	TDfcX();
   1.993 +	~TDfcX();
   1.994 +	static void IDfcFn(TAny*);
   1.995 +	static void DfcFn(TAny*);
   1.996 +	static void TimerIsrFn(TAny*);
   1.997 +	static void TimerDfcFn(TAny*);
   1.998 +	void Update();
   1.999 +	TBool Add(TAny* a=0);
  1.1000 +	TBool Cancel(TAny* a=0);
  1.1001 +	TBool Enque(TAny* a=0);
  1.1002 +	TBool QueueOnIdle(TAny* a=0);
  1.1003 +	TBool SafeAdd();
  1.1004 +	TBool SafeCancel();
  1.1005 +	TBool SafeEnque();
  1.1006 +	TBool SafeQueueOnIdle();
  1.1007 +	void CreateDfcOrTimer();
  1.1008 +	void GetDesc(char* aDesc);
  1.1009 +	inline TBool IsIDFC()
  1.1010 +		{return (iFlags & (EFlag_IDFC|EFlag_Timer)) == EFlag_IDFC;}
  1.1011 +	inline TBool IsIdler()
  1.1012 +		{return iFlags & EFlag_IdleDFC;}
  1.1013 +	void ThreadActivity();
  1.1014 +public:
  1.1015 +	union
  1.1016 +		{
  1.1017 +		TDfc* volatile iDfc;
  1.1018 +		NTimer* volatile iTimer;
  1.1019 +		};
  1.1020 +	TDfcQue* iDfcQ;
  1.1021 +	TUint32 iQueueCount;
  1.1022 +	TUint32 iRunCount[KMaxCpus];
  1.1023 +	TUint32 iCancelCount;
  1.1024 +	TUint32 iExclusionFailCount;
  1.1025 +	TUint32 iId;
  1.1026 +	TUint32 iFlags;
  1.1027 +	TDfcStress* iS;
  1.1028 +	TUint64 iTimeQueued;
  1.1029 +	TUint64 iMaxTime;
  1.1030 +	TUint64 iSumTime;
  1.1031 +	TSpinLock iSpinLock;
  1.1032 +	NSchedulable* iXTied;
  1.1033 +	volatile TUint32* iExclusionCheck;
  1.1034 +	};
  1.1035 +
  1.1036 +TDfcX::TDfcX()
  1.1037 +	: iSpinLock(TSpinLock::EOrderGenericIrqLow1)
  1.1038 +	{
  1.1039 +	memclr(this,sizeof(TDfcX));
  1.1040 +	new (&iSpinLock) TSpinLock(TSpinLock::EOrderGenericIrqLow1);
  1.1041 +	}
  1.1042 +
  1.1043 +TDfcX::~TDfcX()
  1.1044 +	{
  1.1045 +	TAny* p = __e32_atomic_swp_ord_ptr(&iDfc, 0);
  1.1046 +	if (p)
  1.1047 +		{
  1.1048 +		if (iFlags & EFlag_Timer)
  1.1049 +			delete ((NTimer*)p);
  1.1050 +		else
  1.1051 +			delete ((TDfc*)p);
  1.1052 +		}
  1.1053 +	}
  1.1054 +
  1.1055 +class TDfcStress
  1.1056 +	{
  1.1057 +public:
  1.1058 +	enum
  1.1059 +		{
  1.1060 +		EMode_Wait			=0x00000001u,
  1.1061 +		EMode_AllowCancel	=0x00000002u,
  1.1062 +		EMode_AllowIdle		=0x00000004u,
  1.1063 +		EMode_AllowEnque	=0x00000008u,
  1.1064 +		EMode_Recycle		=0x00000010u,
  1.1065 +		EMode_UseTied		=0x00000020u,
  1.1066 +		EMode_Migrate		=0x00000040u,
  1.1067 +		EMode_SelfMigrate	=0x00000080u,
  1.1068 +		EMode_Exit			=0x80000000u
  1.1069 +		};
  1.1070 +public:
  1.1071 +	enum {EMaxDfc=48, EMaxDfcQ=8};
  1.1072 +
  1.1073 +	TDfcStress();
  1.1074 +	static TDfcStress* New(TInt aNumDfc, TInt aNumDfcQ, TBool aTimerTest);
  1.1075 +	void Create();
  1.1076 +	static void DoThreadFn(TAny*);
  1.1077 +	void ThreadFn();
  1.1078 +	static void BackStopFn(TAny*);
  1.1079 +	void Run();
  1.1080 +	void Close();
  1.1081 +	void DoTestPhase(TInt aMode, TInt aTime, TInt aCount);
  1.1082 +	void GetModeText(char* aName);
  1.1083 +public:
  1.1084 +	TDfcX* NewDfc(TUint32 aId, TUint32 aFlags, TInt aDfcQ);
  1.1085 +	TDfcX* NewIDfc(TUint32 aId, TUint32 aFlags, NSchedulable* aTied=0);
  1.1086 +	TDfcX* NewTimer(TUint32 aId, TUint32 aFlags, TInt aDfcQ, NSchedulable* aTied);
  1.1087 +	void CreateDfc(TUint32 aId);
  1.1088 +public:
  1.1089 +	TInt iNumDfc;
  1.1090 +	TDfcX* iDfcX[EMaxDfc];
  1.1091 +	TInt iNumDfcQ;
  1.1092 +	TBool iTimerTest;
  1.1093 +	TDfcQue* iDfcQ[EMaxDfcQ];
  1.1094 +	NThread* iThread[KMaxCpus];
  1.1095 +	volatile TBool iStop;
  1.1096 +	volatile TInt iRunning;
  1.1097 +	volatile TInt iMode;
  1.1098 +	NFastSemaphore* iExitSem;
  1.1099 +	TDfcX* volatile iGarbage;
  1.1100 +	TUint32 iRandomTimeLimit;
  1.1101 +	TDfc* iBackStopIdleDfc;
  1.1102 +	TDfcQue* iBackStopIdleDfcQ;
  1.1103 +	};
  1.1104 +
  1.1105 +void TDfcX::Update()
  1.1106 +	{
  1.1107 +	TUint32 exc0 = 0;
  1.1108 +	TUint32 exc1 = 0;
  1.1109 +	if (iExclusionCheck)
  1.1110 +		exc0 = *iExclusionCheck;
  1.1111 +	TInt cpu = NKern::CurrentCpu();
  1.1112 +	__e32_atomic_add_ord32(&iRunCount[cpu], 1);
  1.1113 +	TInt ctx = NKern::CurrentContext();
  1.1114 +	TBool is_idfc = IsIDFC();
  1.1115 +	TBool is_timer = iFlags & EFlag_Timer;
  1.1116 +	TBool is_tied = iFlags & EFlag_Tied;
  1.1117 +	if ((is_idfc||is_timer) && is_tied && !(iS->iMode & (TDfcStress::EMode_Migrate|TDfcStress::EMode_SelfMigrate)))
  1.1118 +		{
  1.1119 +		TInt cpu = NKern::CurrentCpu();
  1.1120 +		TInt xcpu = iXTied->iCpuAffinity;
  1.1121 +		if (cpu != xcpu)
  1.1122 +			{
  1.1123 +			__crash();
  1.1124 +			}
  1.1125 +		}
  1.1126 +	TInt irq=0;
  1.1127 +	if ((ctx!=NKern::EThread) && (iS->iMode & TDfcStress::EMode_AllowCancel))
  1.1128 +		irq = iSpinLock.LockIrqSave();
  1.1129 +	TUint64 now = fast_counter();
  1.1130 +	TUint64 delta = now - iTimeQueued;
  1.1131 +	if (TInt64(delta)>=0)
  1.1132 +		{
  1.1133 +		if (delta > iMaxTime)
  1.1134 +			iMaxTime = delta;
  1.1135 +		iSumTime += delta;
  1.1136 +		}
  1.1137 +	if ((ctx!=NKern::EThread) && (iS->iMode & TDfcStress::EMode_AllowCancel))
  1.1138 +		iSpinLock.UnlockIrqRestore(irq);
  1.1139 +	if (IsIdler())
  1.1140 +		{
  1.1141 +		TInt i;
  1.1142 +		NKern::Lock();
  1.1143 +		for (i=0; i<KMaxCpus; ++i)
  1.1144 +			{
  1.1145 +			NThread* t = iS->iThread[i];
  1.1146 +			if (t)
  1.1147 +				t->iRequestSemaphore.Reset();
  1.1148 +			}
  1.1149 +		NKern::Unlock();
  1.1150 +		iS->iBackStopIdleDfc->Cancel();
  1.1151 +		}
  1.1152 +	if (iExclusionCheck)
  1.1153 +		exc1 = *iExclusionCheck;
  1.1154 +	if (exc0!=exc1)
  1.1155 +		__e32_atomic_add_ord32(&iExclusionFailCount, 1);
  1.1156 +	}
  1.1157 +
  1.1158 +void TDfcStress::BackStopFn(TAny* a)
  1.1159 +	{
  1.1160 +	TDfcStress* s = (TDfcStress*)a;
  1.1161 +	TInt i;
  1.1162 +	NKern::Lock();
  1.1163 +	for (i=0; i<KMaxCpus; ++i)
  1.1164 +		{
  1.1165 +		NThread* t = s->iThread[i];
  1.1166 +		if (t)
  1.1167 +			t->iRequestSemaphore.Reset();
  1.1168 +		}
  1.1169 +	NKern::Unlock();
  1.1170 +	}
  1.1171 +
  1.1172 +void TDfcX::IDfcFn(TAny* a)
  1.1173 +	{
  1.1174 +	TDfcX* d = (TDfcX*)a;
  1.1175 +	d->Update();
  1.1176 +	}
  1.1177 +
  1.1178 +void TDfcX::DfcFn(TAny* a)
  1.1179 +	{
  1.1180 +	TDfcX* d = (TDfcX*)a;
  1.1181 +	d->ThreadActivity();
  1.1182 +	d->Update();
  1.1183 +	d->ThreadActivity();
  1.1184 +	}
  1.1185 +
  1.1186 +void TDfcX::TimerDfcFn(TAny* a)
  1.1187 +	{
  1.1188 +	TDfcX* d = (TDfcX*)a;
  1.1189 +	d->ThreadActivity();
  1.1190 +	d->Update();
  1.1191 +	d->ThreadActivity();
  1.1192 +	}
  1.1193 +
  1.1194 +void TDfcX::TimerIsrFn(TAny* a)
  1.1195 +	{
  1.1196 +	TDfcX* d = (TDfcX*)a;
  1.1197 +	d->Update();
  1.1198 +	}
  1.1199 +
  1.1200 +void TDfcX::ThreadActivity()
  1.1201 +	{
  1.1202 +	TInt ncpus = NKern::NumberOfCpus();
  1.1203 +	TInt ocpu = NKern::CurrentCpu();
  1.1204 +	NThread* pC = NKern::CurrentThread();
  1.1205 +	volatile TUint32* pX = (volatile TUint32*)&pC->iRunCount32[1];	// HACK!
  1.1206 +	TInt cpu = ocpu;
  1.1207 +	TInt i;
  1.1208 +	if ((iS->iMode & TDfcStress::EMode_SelfMigrate) && !pC->iEvents.IsEmpty())
  1.1209 +		{
  1.1210 +		for (i=0; i<ncpus; ++i)
  1.1211 +			{
  1.1212 +			++*pX;
  1.1213 +			if (++cpu == ncpus)
  1.1214 +				cpu = 0;
  1.1215 +			NKern::ThreadSetCpuAffinity(pC, cpu);
  1.1216 +			}
  1.1217 +		}
  1.1218 +	else
  1.1219 +		{
  1.1220 +		++*pX;
  1.1221 +		++*pX;
  1.1222 +		++*pX;
  1.1223 +		++*pX;
  1.1224 +		++*pX;
  1.1225 +		++*pX;
  1.1226 +		++*pX;
  1.1227 +		++*pX;
  1.1228 +		}
  1.1229 +	++*pX;
  1.1230 +	++*pX;
  1.1231 +	++*pX;
  1.1232 +	}
  1.1233 +
  1.1234 +TBool TDfcX::Add(TAny* a)
  1.1235 +	{
  1.1236 +	TBool is_timer = iFlags & EFlag_Timer;
  1.1237 +	if (!a)
  1.1238 +		a = iDfc;
  1.1239 +	TUint64 time = fast_counter();
  1.1240 +	TBool ok;
  1.1241 +	if (is_timer)
  1.1242 +		ok = ((NTimer*)a)->OneShot(1) == KErrNone;
  1.1243 +	else
  1.1244 +		ok = ((TDfc*)a)->Add();
  1.1245 +	if (ok)
  1.1246 +		{
  1.1247 +		iTimeQueued = time;
  1.1248 +		__e32_atomic_add_ord32(&iQueueCount, 1);
  1.1249 +		}
  1.1250 +	return ok;
  1.1251 +	}
  1.1252 +
  1.1253 +TBool TDfcX::Cancel(TAny* a)
  1.1254 +	{
  1.1255 +	TBool is_timer = iFlags & EFlag_Timer;
  1.1256 +	if (!a)
  1.1257 +		a = iDfc;
  1.1258 +	TBool ok;
  1.1259 +	if (is_timer)
  1.1260 +		ok = ((NTimer*)a)->Cancel();
  1.1261 +	else
  1.1262 +		ok = ((TDfc*)a)->Cancel();
  1.1263 +	if (ok)
  1.1264 +		__e32_atomic_add_ord32(&iCancelCount, 1);
  1.1265 +	return ok;
  1.1266 +	}
  1.1267 +
  1.1268 +TBool TDfcX::Enque(TAny* a)
  1.1269 +	{
  1.1270 +	TBool is_timer = iFlags & EFlag_Timer;
  1.1271 +	if (!a)
  1.1272 +		a = iDfc;
  1.1273 +	TUint64 time = fast_counter();
  1.1274 +	TBool ok;
  1.1275 +	if (is_timer)
  1.1276 +		ok = ((NTimer*)a)->Again(2) == KErrNone;
  1.1277 +	else
  1.1278 +		ok = ((TDfc*)a)->Enque();
  1.1279 +	if (ok)
  1.1280 +		{
  1.1281 +		iTimeQueued = time;
  1.1282 +		__e32_atomic_add_ord32(&iQueueCount, 1);
  1.1283 +		}
  1.1284 +	return ok;
  1.1285 +	}
  1.1286 +
  1.1287 +TBool TDfcX::QueueOnIdle(TAny* a)
  1.1288 +	{
  1.1289 +	TBool is_timer = iFlags & EFlag_Timer;
  1.1290 +	if (is_timer)
  1.1291 +		return FALSE;
  1.1292 +	if (!a)
  1.1293 +		a = iDfc;
  1.1294 +	TUint64 time = fast_counter();
  1.1295 +	TBool ok = ((TDfc*)a)->QueueOnIdle();
  1.1296 +	if (ok)
  1.1297 +		{
  1.1298 +		iTimeQueued = time;
  1.1299 +		__e32_atomic_add_ord32(&iQueueCount, 1);
  1.1300 +		}
  1.1301 +	return ok;
  1.1302 +	}
  1.1303 +
  1.1304 +TBool TDfcX::SafeAdd()
  1.1305 +	{
  1.1306 +	TBool ret = FALSE;
  1.1307 +	TUint32 x = set_bit0_if_nonnull((TUint32&)iDfc);
  1.1308 +	if (x && !(x&1))
  1.1309 +		{
  1.1310 +		TDfc* p = (TDfc*)x;
  1.1311 +		ret = Add(p);
  1.1312 +		flip_bit0((TUint32&)iDfc);
  1.1313 +		}
  1.1314 +	return ret;
  1.1315 +	}
  1.1316 +
  1.1317 +TBool TDfcX::SafeEnque()
  1.1318 +	{
  1.1319 +	TBool ret = FALSE;
  1.1320 +	TUint32 x = set_bit0_if_nonnull((TUint32&)iDfc);
  1.1321 +	if (x && !(x&1))
  1.1322 +		{
  1.1323 +		TDfc* p = (TDfc*)x;
  1.1324 +		ret = Enque(p);
  1.1325 +		flip_bit0((TUint32&)iDfc);
  1.1326 +		}
  1.1327 +	return ret;
  1.1328 +	}
  1.1329 +
  1.1330 +TBool TDfcX::SafeQueueOnIdle()
  1.1331 +	{
  1.1332 +	TBool ret = FALSE;
  1.1333 +	TUint32 x = set_bit0_if_nonnull((TUint32&)iDfc);
  1.1334 +	if (x && !(x&1))
  1.1335 +		{
  1.1336 +		TDfc* p = (TDfc*)x;
  1.1337 +		ret = QueueOnIdle(p);
  1.1338 +		flip_bit0((TUint32&)iDfc);
  1.1339 +		}
  1.1340 +	return ret;
  1.1341 +	}
  1.1342 +
  1.1343 +TBool TDfcX::SafeCancel()
  1.1344 +	{
  1.1345 +	TBool ret = FALSE;
  1.1346 +	TUint32 x = swap_out_if_bit0_clear((TUint32&)iDfc);
  1.1347 +	if (x && !(x&1))
  1.1348 +		{
  1.1349 +		if (iFlags & EFlag_Timer)
  1.1350 +			{
  1.1351 +			NTimer* p = (NTimer*)x;
  1.1352 +			ret = Cancel(p);
  1.1353 +			p->~NTimer();
  1.1354 +			memset(p, 0xbb, sizeof(NTimer));
  1.1355 +			free(p);
  1.1356 +			}
  1.1357 +		else
  1.1358 +			{
  1.1359 +			TDfc* p = (TDfc*)x;
  1.1360 +			ret = Cancel(p);
  1.1361 +			p->~TDfc();
  1.1362 +			memset(p, 0xbb, sizeof(TDfc));
  1.1363 +			free(p);
  1.1364 +			}
  1.1365 +		CreateDfcOrTimer();
  1.1366 +		}
  1.1367 +	return ret;
  1.1368 +	}
  1.1369 +
  1.1370 +void TDfcX::GetDesc(char* a)
  1.1371 +	{
  1.1372 +	memset(a, 0x20, 8);
  1.1373 +	if (iFlags & EFlag_Timer)
  1.1374 +		*a++ = 'T';
  1.1375 +	if (iFlags & EFlag_IDFC)
  1.1376 +		*a++ = 'I';
  1.1377 +	if (iFlags & EFlag_DFC)
  1.1378 +		*a++ = 'D';
  1.1379 +	if (iFlags & EFlag_IdleDFC)
  1.1380 +		*a++ = 'i';
  1.1381 +	if (iFlags & EFlag_Tied)
  1.1382 +		*a++ = 't';
  1.1383 +	}
  1.1384 +
  1.1385 +TDfcStress::TDfcStress()
  1.1386 +	{
  1.1387 +	memclr(this, sizeof(*this));
  1.1388 +	}
  1.1389 +
  1.1390 +TDfcX* TDfcStress::NewDfc(TUint32 aId, TUint32 aFlags, TInt aDfcQ)
  1.1391 +	{
  1.1392 +	TDfcX* d = new TDfcX;
  1.1393 +	TEST_OOM(d);
  1.1394 +	d->iId = aId;
  1.1395 +	d->iFlags = aFlags;
  1.1396 +	d->iS = this;
  1.1397 +
  1.1398 +	d->iDfcQ = iDfcQ[aDfcQ];
  1.1399 +	d->CreateDfcOrTimer();
  1.1400 +	return d;
  1.1401 +	}
  1.1402 +
  1.1403 +TDfcX* TDfcStress::NewIDfc(TUint32 aId, TUint32 aFlags, NSchedulable* aTied)
  1.1404 +	{
  1.1405 +	TDfcX* d = new TDfcX;
  1.1406 +	TEST_OOM(d);
  1.1407 +	d->iId = aId;
  1.1408 +	d->iFlags = aFlags;
  1.1409 +	d->iS = this;
  1.1410 +
  1.1411 +	d->iXTied = aTied;
  1.1412 +	d->CreateDfcOrTimer();
  1.1413 +	return d;
  1.1414 +	}
  1.1415 +
  1.1416 +TDfcX* TDfcStress::NewTimer(TUint32 aId, TUint32 aFlags, TInt aDfcQ, NSchedulable* aTied)
  1.1417 +	{
  1.1418 +	TDfcX* d = new TDfcX;
  1.1419 +	TEST_OOM(d);
  1.1420 +	d->iId = aId;
  1.1421 +	d->iFlags = aFlags;
  1.1422 +	d->iS = this;
  1.1423 +
  1.1424 +	d->iDfcQ = (aFlags & TDfcX::EFlag_DFC) ? iDfcQ[aDfcQ] : 0;
  1.1425 +	d->iXTied = (aFlags & TDfcX::EFlag_Tied) ? aTied : 0;
  1.1426 +	d->CreateDfcOrTimer();
  1.1427 +	return d;
  1.1428 +	}
  1.1429 +
  1.1430 +
  1.1431 +void TDfcX::CreateDfcOrTimer()
  1.1432 +	{
  1.1433 +//	volatile TUint32* xc = 0;
  1.1434 +	NThreadBase* t = iS->iDfcQ[0]->iThread;
  1.1435 +	volatile TUint32* xc = &t->iRunCount32[1];	// HACK!
  1.1436 +	if (!(iFlags & EFlag_Timer))
  1.1437 +		{
  1.1438 +		TDfc* d = 0;
  1.1439 +		if (!(iFlags & EFlag_IDFC))
  1.1440 +			{
  1.1441 +			d = new TDfc(&TDfcX::DfcFn, this, iDfcQ, 1);
  1.1442 +			xc = (volatile TUint32*)&iDfcQ->iThread->iRunCount32[1];
  1.1443 +			}
  1.1444 +		else if (iFlags & EFlag_Tied)
  1.1445 +			{
  1.1446 +			d = new TDfc(iXTied, &TDfcX::IDfcFn, this);
  1.1447 +			xc = (volatile TUint32*)&iXTied->iRunCount32[1];
  1.1448 +			}
  1.1449 +		else
  1.1450 +			d = new TDfc(&TDfcX::IDfcFn, this);
  1.1451 +		__NK_ASSERT_ALWAYS(d!=0);
  1.1452 +		__e32_atomic_store_rel_ptr(&iDfc, d);
  1.1453 +		}
  1.1454 +	else
  1.1455 +		{
  1.1456 +		NTimer* tmr = 0;
  1.1457 +		if (iFlags & EFlag_DFC)
  1.1458 +			{
  1.1459 +			tmr = new NTimer(&TDfcX::TimerDfcFn, this, iDfcQ, 1);
  1.1460 +			xc = (volatile TUint32*)&iDfcQ->iThread->iRunCount32[1];
  1.1461 +			}
  1.1462 +		else if (iFlags & EFlag_Tied)
  1.1463 +			{
  1.1464 +			tmr = new NTimer(iXTied, &TDfcX::TimerIsrFn, this);
  1.1465 +			xc = (volatile TUint32*)&iXTied->iRunCount32[1];
  1.1466 +			}
  1.1467 +		else
  1.1468 +			tmr = new NTimer(&TDfcX::TimerIsrFn, this);
  1.1469 +		__NK_ASSERT_ALWAYS(tmr!=0);
  1.1470 +		__e32_atomic_store_rel_ptr(&iTimer, tmr);
  1.1471 +		}
  1.1472 +	iExclusionCheck = xc;
  1.1473 +	}
  1.1474 +
  1.1475 +TDfcStress* TDfcStress::New(TInt aNumDfc, TInt aNumDfcQ, TBool aTimerTest)
  1.1476 +	{
  1.1477 +	TDfcStress* p = new TDfcStress;
  1.1478 +	TEST_OOM(p);
  1.1479 +	p->iTimerTest = aTimerTest;
  1.1480 +	p->iNumDfc = aNumDfc;
  1.1481 +	p->iNumDfcQ = aNumDfcQ;
  1.1482 +	p->Create();
  1.1483 +	return p;
  1.1484 +	}
  1.1485 +
  1.1486 +void TDfcStress::Create()
  1.1487 +	{
  1.1488 +DEBUGPRINT("TDfcStress @ %08x", this);
  1.1489 +	TInt i;
  1.1490 +	TInt num_cpus = NKern::NumberOfCpus();
  1.1491 +	TInt cpu = 0;
  1.1492 +	iExitSem = new NFastSemaphore(0);
  1.1493 +	TEST_OOM(iExitSem);
  1.1494 +	for (i=0; i<iNumDfcQ; ++i)
  1.1495 +		{
  1.1496 +		char c[8] = "DFCQ*";
  1.1497 +		c[4] = (char)('0'+i);
  1.1498 +		TDfcQue* q = CreateDfcQ(c, 32, cpu);
  1.1499 +		TEST_OOM(q);
  1.1500 +		iDfcQ[i] = q;
  1.1501 +		if (++cpu == num_cpus)
  1.1502 +			cpu = 0;
  1.1503 +		NThreadBase* t = q->iThread;
  1.1504 +DEBUGPRINT("DfcQ %2d @ %08x Thread @%08x Stack %08x+%08x", i, iDfcQ[i], t, t->iStackBase, t->iStackSize);
  1.1505 +		}
  1.1506 +	iBackStopIdleDfcQ = CreateDfcQ("BackStop", 1, 0);
  1.1507 +	TEST_OOM(iBackStopIdleDfcQ);
  1.1508 +	iBackStopIdleDfc = new TDfc(&BackStopFn, this, iBackStopIdleDfcQ, 1);
  1.1509 +	TEST_OOM(iBackStopIdleDfc);
  1.1510 +	for (i=0; i<num_cpus; ++i)
  1.1511 +		{
  1.1512 +		char c[8] = "THRD*";
  1.1513 +		c[4] = (char)('0'+i);
  1.1514 +		NThread* t = CreateUnresumedThreadSignalOnExit(c, &DoThreadFn, 11, this, 0, -1, iExitSem, i);
  1.1515 +		TEST_OOM(t);
  1.1516 +		iThread[i] = t;
  1.1517 +DEBUGPRINT("Thread %2d @ %08x (Stack %08x+%08x)", i, iThread[i], t->iStackBase, t->iStackSize);
  1.1518 +		}
  1.1519 +	for (i=0; i<iNumDfc; ++i)
  1.1520 +		{
  1.1521 +		CreateDfc(i);
  1.1522 +DEBUGPRINT("DfcX %2d @ %08x (DFC @ %08x)", i, iDfcX[i], iDfcX[i]->iDfc);
  1.1523 +		}
  1.1524 +	}
  1.1525 +
  1.1526 +void TDfcStress::CreateDfc(TUint32 aId)
  1.1527 +	{
  1.1528 +	TUint32 type = aId & 7;
  1.1529 +	TUint32 q = aId % iNumDfcQ;
  1.1530 +	TDfcX* d = 0;
  1.1531 +	switch (type)
  1.1532 +		{
  1.1533 +		case 0:
  1.1534 +		case 1:
  1.1535 +		case 2:
  1.1536 +		case 3:
  1.1537 +			if (iTimerTest)
  1.1538 +				d = NewTimer(aId, TDfcX::EFlag_Timer|TDfcX::EFlag_DFC, q, 0);
  1.1539 +			else
  1.1540 +				d = NewDfc(aId, TDfcX::EFlag_DFC, q);
  1.1541 +			break;
  1.1542 +		case 4:
  1.1543 +		case 5:
  1.1544 +			if (iTimerTest)
  1.1545 +				d = NewTimer(aId, TDfcX::EFlag_Timer|TDfcX::EFlag_Tied, 0, iDfcQ[iNumDfcQ-1-(type&1)]->iThread);
  1.1546 +			else
  1.1547 +				{
  1.1548 +				if (aId>=16 && aId<32 && iNumDfcQ>2)
  1.1549 +					d = NewIDfc(aId, TDfcX::EFlag_IDFC|TDfcX::EFlag_Tied, iDfcQ[2]->iThread);
  1.1550 +				else
  1.1551 +					d = NewIDfc(aId, TDfcX::EFlag_IDFC);
  1.1552 +				}
  1.1553 +			break;
  1.1554 +		case 6:
  1.1555 +		case 7:
  1.1556 +			if (iTimerTest)
  1.1557 +				d = NewTimer(aId, TDfcX::EFlag_Timer, 0, 0);
  1.1558 +			else
  1.1559 +				d = NewDfc(aId, TDfcX::EFlag_DFC|TDfcX::EFlag_IdleDFC, q);
  1.1560 +			break;
  1.1561 +		};
  1.1562 +	__e32_atomic_store_rel_ptr(&iDfcX[aId], d);
  1.1563 +	}
  1.1564 +
  1.1565 +void TDfcStress::Close()
  1.1566 +	{
  1.1567 +	TInt i;
  1.1568 +
  1.1569 +	// delete DFCs before the DFC queues they might be on
  1.1570 +	for (i=0; i<iNumDfc; ++i)
  1.1571 +		{
  1.1572 +		TDfcX* d = iDfcX[i];
  1.1573 +		delete d;
  1.1574 +		}
  1.1575 +	delete iBackStopIdleDfc;
  1.1576 +
  1.1577 +	for (i=0; i<iNumDfcQ; ++i)
  1.1578 +		DestroyDfcQ(iDfcQ[i]);
  1.1579 +	DestroyDfcQ(iBackStopIdleDfcQ);
  1.1580 +
  1.1581 +	delete iExitSem;
  1.1582 +	delete this;
  1.1583 +	}
  1.1584 +
  1.1585 +void TDfcStress::DoThreadFn(TAny* a)
  1.1586 +	{
  1.1587 +	((TDfcStress*)a)->ThreadFn();
  1.1588 +	}
  1.1589 +
  1.1590 +void append(char*& a, const char* s)
  1.1591 +	{
  1.1592 +	while(*s)
  1.1593 +		*a++ = *s++;
  1.1594 +	*a=0;
  1.1595 +	}
  1.1596 +
  1.1597 +void TDfcStress::GetModeText(char* a)
  1.1598 +	{
  1.1599 +	memclr(a,128);
  1.1600 +	if (iMode==0)
  1.1601 +		{
  1.1602 +		append(a, "Add only");
  1.1603 +		return;
  1.1604 +		}
  1.1605 +	if (iMode & EMode_Wait)
  1.1606 +		append(a, "Wait ");
  1.1607 +	if (iMode & EMode_AllowCancel)
  1.1608 +		append(a, "Cancel ");
  1.1609 +	if (iMode & EMode_AllowIdle)
  1.1610 +		append(a, "Idle ");
  1.1611 +	if (iMode & EMode_AllowEnque)
  1.1612 +		append(a, "Enque ");
  1.1613 +	if (iMode & EMode_Recycle)
  1.1614 +		append(a, "Recycle ");
  1.1615 +	if (iMode & EMode_Migrate)
  1.1616 +		append(a, "Migrate ");
  1.1617 +	if (iMode & EMode_SelfMigrate)
  1.1618 +		append(a, "SelfMigrate ");
  1.1619 +	}
  1.1620 +
  1.1621 +/*
  1.1622 +Test Mode:
  1.1623 +
  1.1624 +Bit 31	If set causes thread to exit
  1.1625 +Bit 0	If set does random wait after each operation
  1.1626 +Bit 1	Allows Cancel operations if set
  1.1627 +Bit 2	Allows idle operations if set
  1.1628 +Bit 3	Test Enque() as well as Add()
  1.1629 +Bit 4	Use SafeXXX operations
  1.1630 +Bit 5	Use tied IDFCs
  1.1631 +Bit 6	Migrate threads with things tied to them
  1.1632 +Bit 7	Threads with things tied to them migrate themselves during execution
  1.1633 +
  1.1634 +*/
  1.1635 +void TDfcStress::ThreadFn()
  1.1636 +	{
  1.1637 +	TBool finish = FALSE;
  1.1638 +	TUint32 seed[2];
  1.1639 +	seed[0] = NKern::CurrentCpu() ^ 0xddb3d743;
  1.1640 +	seed[1] = 0;
  1.1641 +	FOREVER
  1.1642 +		{
  1.1643 +		if (iStop)
  1.1644 +			{
  1.1645 +			__e32_atomic_add_ord32(&iRunning, (TUint32)(-1));
  1.1646 +			while (iStop)
  1.1647 +				{
  1.1648 +				if (iMode<0)
  1.1649 +					{
  1.1650 +					finish = TRUE;
  1.1651 +					break;
  1.1652 +					}
  1.1653 +				}
  1.1654 +			if (finish)
  1.1655 +				break;
  1.1656 +			else
  1.1657 +				__e32_atomic_add_ord32(&iRunning, 1);
  1.1658 +			}
  1.1659 +		if (iMode & EMode_Wait)
  1.1660 +			{
  1.1661 +			TUint32 wait = random(seed);
  1.1662 +			wait %= iRandomTimeLimit;
  1.1663 +			wait += 1;
  1.1664 +			fcfspin(wait);
  1.1665 +			}
  1.1666 +		TUint32 action = random(seed);
  1.1667 +		TUint32 action2 = random(seed);
  1.1668 +		if (action & 0xff000000)
  1.1669 +			{
  1.1670 +			// queue or cancel a DFC or timer
  1.1671 +			TBool cancel = action2 & 2;
  1.1672 +			TUint32 id = action % iNumDfc;
  1.1673 +			TDfcX* d = iDfcX[id];
  1.1674 +			if (iMode & EMode_Recycle)
  1.1675 +				{
  1.1676 +				TBool isIDFC = d->IsIDFC();
  1.1677 +				TBool isIdler = d->IsIdler();
  1.1678 +				if (cancel)
  1.1679 +					d->SafeCancel();
  1.1680 +				else if (isIdler)
  1.1681 +					d->SafeQueueOnIdle();
  1.1682 +				else if ((iMode & EMode_AllowEnque) && (action2 & 1) && !isIDFC)
  1.1683 +					d->SafeEnque();
  1.1684 +				else
  1.1685 +					{
  1.1686 +					NKern::Lock();
  1.1687 +					d->SafeAdd();
  1.1688 +					NKern::Unlock();
  1.1689 +					}
  1.1690 +				}
  1.1691 +			else
  1.1692 +				{
  1.1693 +				if (cancel && (iMode & EMode_AllowCancel))
  1.1694 +					{
  1.1695 +					d->Cancel();
  1.1696 +					}
  1.1697 +				else if (!d->IsIdler())
  1.1698 +					{
  1.1699 +					if ((iMode & EMode_AllowEnque) && (action2 & 1) && !d->IsIDFC())
  1.1700 +						{
  1.1701 +						d->Enque();
  1.1702 +						}
  1.1703 +					else
  1.1704 +						{
  1.1705 +						NKern::Lock();
  1.1706 +						d->Add();
  1.1707 +						NKern::Unlock();
  1.1708 +						}
  1.1709 +					}
  1.1710 +				else
  1.1711 +					{
  1.1712 +					d->QueueOnIdle();
  1.1713 +					}
  1.1714 +				}
  1.1715 +			continue;
  1.1716 +			}
  1.1717 +		if (iMode & EMode_AllowIdle)
  1.1718 +			{
  1.1719 +			iBackStopIdleDfc->QueueOnIdle();
  1.1720 +			NKern::WaitForAnyRequest();
  1.1721 +			}
  1.1722 +		}
  1.1723 +	}
  1.1724 +
  1.1725 +void StopTimeout(TAny*)
  1.1726 +	{
  1.1727 +	__crash();
  1.1728 +	}
  1.1729 +
  1.1730 +void TDfcStress::DoTestPhase(TInt aMode, TInt aTime, TInt aCount)
  1.1731 +	{
  1.1732 +	char mode_text[128];
  1.1733 +	TInt i;
  1.1734 +	TUint32 maxavg = 0;
  1.1735 +	TInt n;
  1.1736 +	iMode = aMode;
  1.1737 +	iStop = FALSE;
  1.1738 +	GetModeText(mode_text);
  1.1739 +	TEST_PRINT1("Testing with: %s", mode_text);
  1.1740 +	for (i=0; i<aCount; ++i)
  1.1741 +		{
  1.1742 +		NKern::Sleep(aTime);
  1.1743 +		DebugPrint(".",1);
  1.1744 +		}
  1.1745 +	DebugPrint("\r\n",2);
  1.1746 +	TEST_PRINT("Stopping ...");
  1.1747 +	iStop = TRUE;
  1.1748 +	NTimer timer(&StopTimeout, 0);
  1.1749 +	timer.OneShot(2000);
  1.1750 +	BackStopFn(this);
  1.1751 +	n = 0;
  1.1752 +	while (iRunning && ++n<=100)
  1.1753 +		NKern::Sleep(10);
  1.1754 +	if (iRunning)
  1.1755 +		{
  1.1756 +		__crash();
  1.1757 +		}
  1.1758 +	iBackStopIdleDfc->Cancel();
  1.1759 +	timer.Cancel();
  1.1760 +	TEST_PRINT("Threads stopped");
  1.1761 +	for (i=0; i<iNumDfcQ; ++i)
  1.1762 +		{
  1.1763 +		TUint32 ev = iDfcQ[i]->iThread->iEventState;
  1.1764 +		DEBUGPRINT("DfcThread %d EventState = %08x", i, ev);
  1.1765 +		TEST_RESULT(!(ev & NSchedulable::EEventCountMask), "");
  1.1766 +		}
  1.1767 +	for (i=0; i<NKern::NumberOfCpus(); ++i)
  1.1768 +		{
  1.1769 +		TUint32 ev = iThread[i]->iEventState;
  1.1770 +		DEBUGPRINT("Thread    %d EventState = %08x", i, ev);
  1.1771 +		TEST_RESULT(!(ev & NSchedulable::EEventCountMask), "");
  1.1772 +		}
  1.1773 +	NKern::Sleep(10);
  1.1774 +	for (i=0; i<iNumDfc; ++i)
  1.1775 +		{
  1.1776 +		TDfcX* d = iDfcX[i];
  1.1777 +		d->Cancel();
  1.1778 +		TUint32 qc = d->iQueueCount;
  1.1779 +		TUint32* rc = d->iRunCount;
  1.1780 +		TUint32 totrc = rc[0] + rc[1] + rc[2] + rc[3] + rc[4] + rc[5] + rc[6] + rc[7];
  1.1781 +		TUint32 cc = d->iCancelCount;
  1.1782 +		TUint32 f = d->iFlags;
  1.1783 +//		TUint32 imm = d->IsIDFC()?1:0;
  1.1784 +		TUint32 max = d->iMaxTime;
  1.1785 +		TUint32 avg = 0;
  1.1786 +		TUint32 xfc = d->iExclusionFailCount;
  1.1787 +		if (totrc)
  1.1788 +			avg = TUint32(d->iSumTime / TUint64(totrc));
  1.1789 +		if (avg > maxavg)
  1.1790 +			maxavg = avg;
  1.1791 +		char desc[16];
  1.1792 +		memclr(desc,16);
  1.1793 +		d->GetDesc(desc);
  1.1794 +		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]);
  1.1795 +		TInt diff = (TInt)(qc - (totrc+cc));
  1.1796 +		TEST_RESULT1(diff==0, "Counts mismatched, diff=%d", diff);
  1.1797 +		TEST_RESULT(!(f&TDfcX::EFlag_Tied) || xfc==0, "Exclusion Failure!");
  1.1798 +		d->iQueueCount = 0;
  1.1799 +		memclr(d->iRunCount, sizeof(d->iRunCount));
  1.1800 +		d->iCancelCount = 0;
  1.1801 +		d->iMaxTime = 0;
  1.1802 +		d->iSumTime = 0;
  1.1803 +		}
  1.1804 +	if (!iRandomTimeLimit)
  1.1805 +		iRandomTimeLimit = maxavg + (maxavg>>1);
  1.1806 +	}
  1.1807 +
  1.1808 +void TDfcStress::Run()
  1.1809 +	{
  1.1810 +	TInt i;
  1.1811 +	NThread* t;
  1.1812 +	iStop = FALSE;
  1.1813 +	iMode = 0;
  1.1814 +	TInt num_cpus = NKern::NumberOfCpus();
  1.1815 +	iRunning = num_cpus;
  1.1816 +	for (i=0; i<KMaxCpus; ++i)
  1.1817 +		{
  1.1818 +		t = iThread[i];
  1.1819 +		if (t)
  1.1820 +			NKern::ThreadResume(t);
  1.1821 +		}
  1.1822 +	TEST_PRINT("Threads resumed");
  1.1823 +
  1.1824 +
  1.1825 +	DoTestPhase(0x00, 10000, 1);
  1.1826 +	if (iTimerTest)
  1.1827 +		{
  1.1828 +		const TInt N = 20;
  1.1829 +		DoTestPhase(EMode_AllowCancel|EMode_AllowEnque|EMode_Recycle, 10000, N);
  1.1830 +		DoTestPhase(EMode_AllowCancel|EMode_AllowEnque|EMode_Wait|EMode_Recycle, 10000, N);
  1.1831 +		DoTestPhase(EMode_AllowCancel|EMode_AllowEnque|EMode_Recycle|EMode_SelfMigrate, 10000, N);
  1.1832 +		DoTestPhase(EMode_AllowCancel|EMode_AllowEnque|EMode_Wait|EMode_Recycle|EMode_SelfMigrate, 10000, N);
  1.1833 +		DoTestPhase(EMode_AllowCancel|EMode_AllowEnque, 10000, N);
  1.1834 +		DoTestPhase(EMode_AllowCancel|EMode_AllowEnque|EMode_Wait, 10000, N);
  1.1835 +		DoTestPhase(EMode_AllowCancel|EMode_AllowEnque|EMode_SelfMigrate, 10000, N);
  1.1836 +		DoTestPhase(EMode_AllowCancel|EMode_AllowEnque|EMode_Wait|EMode_SelfMigrate, 10000, N);
  1.1837 +		}
  1.1838 +	else
  1.1839 +		{
  1.1840 +		DoTestPhase(EMode_AllowCancel|EMode_AllowEnque, 10000, 20);
  1.1841 +		DoTestPhase(EMode_AllowCancel|EMode_AllowIdle|EMode_AllowEnque, 10000, 20);
  1.1842 +		DoTestPhase(EMode_AllowIdle|EMode_AllowEnque, 10000, 20);
  1.1843 +		DoTestPhase(EMode_AllowCancel|EMode_AllowIdle, 10000, 20);
  1.1844 +		DoTestPhase(EMode_AllowCancel|EMode_Wait, 10000, 20);
  1.1845 +		DoTestPhase(EMode_AllowCancel, 10000, 20);
  1.1846 +		DoTestPhase(EMode_AllowCancel|EMode_AllowIdle|EMode_AllowEnque|EMode_Recycle, 10000, 20);
  1.1847 +		}
  1.1848 +
  1.1849 +	iMode = EMode_Exit;
  1.1850 +	TEST_PRINT("Terminating threads");
  1.1851 +	for (i=0; i<num_cpus; ++i)
  1.1852 +		NKern::FSWait(iExitSem);
  1.1853 +	TEST_PRINT("Done");
  1.1854 +	}
  1.1855 +
  1.1856 +void DoStressTest(TBool aTimerTest)
  1.1857 +	{
  1.1858 +	TEST_PRINT("Stress test...");
  1.1859 +	TInt ndfcs=0;
  1.1860 +	TInt ndfcq=0;
  1.1861 +	switch (NKern::NumberOfCpus())
  1.1862 +		{
  1.1863 +		case 1:	ndfcs=16; ndfcq=2; break;
  1.1864 +		case 2:	ndfcs=16; ndfcq=2; break;
  1.1865 +		case 3:	ndfcs=24; ndfcq=2; break;
  1.1866 +		case 4:	ndfcs=32; ndfcq=3; break;
  1.1867 +		case 5:	ndfcs=32; ndfcq=3; break;
  1.1868 +		case 6:	ndfcs=48; ndfcq=4; break;
  1.1869 +		case 7:	ndfcs=48; ndfcq=4; break;
  1.1870 +		case 8:	ndfcs=48; ndfcq=4; break;
  1.1871 +		default:
  1.1872 +			__NK_ASSERT_ALWAYS(0);
  1.1873 +			break;
  1.1874 +		}
  1.1875 +	TDfcStress* ds = TDfcStress::New(ndfcs, ndfcq, aTimerTest);
  1.1876 +	ds->Run();
  1.1877 +	ds->Close();
  1.1878 +	}
  1.1879 +
  1.1880 +#endif
  1.1881 +
  1.1882 +void TestDFCs()
  1.1883 +	{
  1.1884 +	TEST_PRINT("Testing DFCs...");
  1.1885 +
  1.1886 +	TTestDfc::Buffer = CircBuf::New(TTestDfc::EBufferSlots);
  1.1887 +	TInt cpu;
  1.1888 +	(void)cpu;
  1.1889 +#ifdef __SMP__
  1.1890 +	DoStressTest(TRUE);
  1.1891 +#endif
  1.1892 +
  1.1893 +	DoDFCTest1();
  1.1894 +	DoDFCTest2();
  1.1895 +	for_each_cpu(cpu)
  1.1896 +		{
  1.1897 +		DoDFCTest3(cpu);
  1.1898 +		}
  1.1899 +	DoIDFCTest1();
  1.1900 +	for_each_cpu(cpu)
  1.1901 +		{
  1.1902 +		DoIdleDFCTest1(cpu);
  1.1903 +		}
  1.1904 +	DoIdleDFCTest2();
  1.1905 +
  1.1906 +#ifdef __SMP__
  1.1907 +	DoStressTest(FALSE);
  1.1908 +#endif
  1.1909 +
  1.1910 +	delete TTestDfc::Buffer;
  1.1911 +	TTestDfc::Buffer = 0;
  1.1912 +	}