kerneltest/e32test/nkernsa/testipi.cpp
changeset 0 a41df078684a
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     1 // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of the License "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // e32test\nkernsa\testipi.cpp
       
    15 // 
       
    16 //
       
    17 
       
    18 #include <nktest/nkutils.h>
       
    19 
       
    20 #ifdef __SMP__
       
    21 
       
    22 class TTestIPI : public TGenericIPI
       
    23 	{
       
    24 public:
       
    25 	TTestIPI();
       
    26 	static TTestIPI* New();
       
    27 	static void Isr(TGenericIPI*);
       
    28 	void Inc(TInt aCpu, TInt aInc=1) {iExpected[aCpu] += aInc;}
       
    29 	void IncM(TUint32 aMask);
       
    30 	void Check();
       
    31 public:
       
    32 	TInt iCount[KMaxCpus];
       
    33 	TInt iExpected[KMaxCpus];
       
    34 	};
       
    35 
       
    36 TTestIPI::TTestIPI()
       
    37 	{
       
    38 	memclr(iCount, sizeof(iCount));
       
    39 	memclr(iExpected, sizeof(iExpected));
       
    40 	}
       
    41 
       
    42 TTestIPI* TTestIPI::New()
       
    43 	{
       
    44 	TTestIPI* p = new TTestIPI;
       
    45 	TEST_OOM(p);
       
    46 	return p;
       
    47 	}
       
    48 
       
    49 void TTestIPI::Isr(TGenericIPI* a)
       
    50 	{
       
    51 	TTestIPI& ipi = *(TTestIPI*)a;
       
    52 	TInt cpu = NKern::CurrentCpu();
       
    53 	++ipi.iCount[cpu];
       
    54 	}
       
    55 
       
    56 void TTestIPI::IncM(TUint32 aMask)
       
    57 	{
       
    58 	TInt i;
       
    59 	for(i=0; i<KMaxCpus; ++i)
       
    60 		{
       
    61 		if (aMask & (1<<i))
       
    62 			++iExpected[i];
       
    63 		}
       
    64 	}
       
    65 
       
    66 void TTestIPI::Check()
       
    67 	{
       
    68 	TInt i;
       
    69 	for(i=0; i<KMaxCpus; ++i)
       
    70 		{
       
    71 		TEST_RESULT3(iCount[i]==iExpected[i], "CPU %d Count %d Expected %d", i, iCount[i], iExpected[i]);
       
    72 		}
       
    73 	}
       
    74 
       
    75 void IPITestThread1(TAny*)
       
    76 	{
       
    77 	TInt cpu;
       
    78 	TUint32 all_cpus = ~(0xffffffffu << NKern::NumberOfCpus());
       
    79 
       
    80 	for_each_cpu(cpu)
       
    81 		{
       
    82 		TEST_PRINT("ipi1");
       
    83 		TTestIPI ipi;
       
    84 		ipi.Queue(&TTestIPI::Isr, 1u<<cpu);
       
    85 		ipi.WaitCompletion();
       
    86 		ipi.Inc(cpu);
       
    87 		ipi.Check();
       
    88 
       
    89 		TEST_PRINT("ipi2");
       
    90 		TTestIPI ipi2;
       
    91 		TUint32 m = all_cpus & ~(1u<<cpu);
       
    92 		ipi2.Queue(&TTestIPI::Isr, m);
       
    93 		ipi2.WaitCompletion();
       
    94 		ipi2.IncM(m);
       
    95 		ipi2.Check();
       
    96 		}
       
    97 
       
    98 	TEST_PRINT("ipi3");
       
    99 	TTestIPI ipi3;
       
   100 	ipi3.QueueAll(&TTestIPI::Isr);
       
   101 	ipi3.WaitCompletion();
       
   102 	ipi3.IncM(all_cpus);
       
   103 	ipi3.Check();
       
   104 
       
   105 	TEST_PRINT("ipi4");
       
   106 	TTestIPI ipi4;
       
   107 	ipi4.QueueAllOther(&TTestIPI::Isr);
       
   108 	ipi4.WaitCompletion();
       
   109 	ipi4.IncM(all_cpus & ~(1u<<NKern::CurrentCpu()) );
       
   110 	ipi4.Check();
       
   111 	}
       
   112 
       
   113 void DoIPITest1()
       
   114 	{
       
   115 	TInt cpu;
       
   116 	for_each_cpu(cpu)
       
   117 		{
       
   118 		CreateThreadAndWaitForExit("IPITest1", &IPITestThread1, 12, 0, 0, -1, cpu);
       
   119 		}
       
   120 	}
       
   121 
       
   122 
       
   123 class TTestIPI2 : public TGenericIPI
       
   124 	{
       
   125 public:
       
   126 	TTestIPI2(TInt aId);
       
   127 	static TTestIPI2* New(TInt aId);
       
   128 	static void Isr(TGenericIPI*);
       
   129 	static void Thread(TAny*);
       
   130 public:
       
   131 	TInt iId;
       
   132 public:
       
   133 	enum {EMaxIPI=32};
       
   134 	enum {EBufSize=256};
       
   135 	static volatile TInt NextPos;
       
   136 	static volatile TUint32 Buffer[EBufSize];
       
   137 	static volatile TUint32 PauseHere;
       
   138 	};
       
   139 
       
   140 volatile TInt TTestIPI2::NextPos;
       
   141 volatile TUint32 TTestIPI2::Buffer[TTestIPI2::EBufSize];
       
   142 volatile TUint32 TTestIPI2::PauseHere;
       
   143 
       
   144 __ASSERT_COMPILE(TTestIPI2::EBufSize >= TTestIPI2::EMaxIPI*KMaxCpus);
       
   145 
       
   146 TTestIPI2::TTestIPI2(TInt aId)
       
   147 	: iId(aId)
       
   148 	{
       
   149 	}
       
   150 
       
   151 TTestIPI2* TTestIPI2::New(TInt aId)
       
   152 	{
       
   153 	TTestIPI2* p = new TTestIPI2(aId);
       
   154 	TEST_OOM(p);
       
   155 	return p;
       
   156 	}
       
   157 
       
   158 void TTestIPI2::Isr(TGenericIPI* a)
       
   159 	{
       
   160 	TTestIPI2& ipi = *(TTestIPI2*)a;
       
   161 	TUint32 cpu = NKern::CurrentCpu();
       
   162 	TUint32 x = (cpu<<16) | ipi.iId;
       
   163 	TInt pos = __e32_atomic_tas_ord32(&NextPos, EBufSize, 0, 1);
       
   164 	if (pos < EBufSize)
       
   165 		Buffer[pos] = x;
       
   166 	while (PauseHere == x)
       
   167 		{}
       
   168 	}
       
   169 
       
   170 void TTestIPI2::Thread(TAny*)
       
   171 	{
       
   172 	TTestIPI2* ipi[EMaxIPI];
       
   173 	TUint32 all_cpus = ~(0xffffffffu << NKern::NumberOfCpus());
       
   174 	TInt this_cpu = NKern::CurrentCpu();
       
   175 	TInt pause_cpu = this_cpu + 1;
       
   176 	if (pause_cpu >= NKern::NumberOfCpus())
       
   177 		pause_cpu = 0;
       
   178 	if (pause_cpu == this_cpu)
       
   179 		pause_cpu = -1;
       
   180 	TUint32 this_cpu_mask = 1u<<this_cpu;
       
   181 	TUint32 pause_cpu_mask = (pause_cpu>=0) ? (1u<<pause_cpu) : 0;
       
   182 	TUint32 other_cpus = all_cpus & ~(this_cpu_mask | pause_cpu_mask);
       
   183 	TInt num_other_cpus = __e32_bit_count_32(other_cpus);
       
   184 	TInt i;
       
   185 	for(i=0; i<EMaxIPI; ++i)
       
   186 		ipi[i] = New(i+1);
       
   187 
       
   188 	NextPos = 0;
       
   189 	PauseHere = 0;
       
   190 	if (pause_cpu >= 0)
       
   191 		PauseHere = (pause_cpu<<16) | (EMaxIPI/2);
       
   192 
       
   193 	TEST_PRINT3("this_cpu=%d pause_cpu=%d PauseHere=%x", this_cpu, pause_cpu, PauseHere);
       
   194 
       
   195 	TInt irq = NKern::DisableAllInterrupts();
       
   196 	for (i=0; i<EMaxIPI; ++i)
       
   197 		ipi[i]->QueueAll(&Isr);
       
   198 
       
   199 	TInt expected1 = num_other_cpus*EMaxIPI + EMaxIPI/2;
       
   200 	while (NextPos != expected1)
       
   201 		{}
       
   202 
       
   203 	PauseHere = 0;
       
   204 	TInt expected2 = num_other_cpus*EMaxIPI + EMaxIPI;
       
   205 	while (NextPos != expected2)
       
   206 		{}
       
   207 	NKern::RestoreInterrupts(irq);
       
   208 	ipi[EMaxIPI-1]->WaitCompletion();
       
   209 
       
   210 	for(i=0; i<NextPos; ++i)
       
   211 		{
       
   212 		TEST_PRINT1("%08x", Buffer[i]);
       
   213 		}
       
   214 
       
   215 	for(i=0; i<EMaxIPI; ++i)
       
   216 		delete ipi[i];
       
   217 	}
       
   218 
       
   219 void DoIPITest2()
       
   220 	{
       
   221 	TInt cpu;
       
   222 	for_each_cpu(cpu)
       
   223 		{
       
   224 		CreateThreadAndWaitForExit("IPITest2", &TTestIPI2::Thread, 12, 0, 0, -1, cpu);
       
   225 		}
       
   226 	}
       
   227 
       
   228 
       
   229 void TestIPI()
       
   230 	{
       
   231 	TEST_PRINT("Testing generic IPIs...");
       
   232 
       
   233 	DoIPITest1();
       
   234 	DoIPITest2();
       
   235 	}
       
   236 
       
   237 #else	// __SMP__
       
   238 void TestIPI()
       
   239 	{
       
   240 	}
       
   241 #endif	// __SMP__