os/kernelhwsrv/kerneltest/e32test/nkernsa/testipi.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     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__