1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/kernelhwsrv/kerneltest/e32test/nkernsa/testipi.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,241 @@
1.4 +// Copyright (c) 2006-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\testipi.cpp
1.18 +//
1.19 +//
1.20 +
1.21 +#include <nktest/nkutils.h>
1.22 +
1.23 +#ifdef __SMP__
1.24 +
1.25 +class TTestIPI : public TGenericIPI
1.26 + {
1.27 +public:
1.28 + TTestIPI();
1.29 + static TTestIPI* New();
1.30 + static void Isr(TGenericIPI*);
1.31 + void Inc(TInt aCpu, TInt aInc=1) {iExpected[aCpu] += aInc;}
1.32 + void IncM(TUint32 aMask);
1.33 + void Check();
1.34 +public:
1.35 + TInt iCount[KMaxCpus];
1.36 + TInt iExpected[KMaxCpus];
1.37 + };
1.38 +
1.39 +TTestIPI::TTestIPI()
1.40 + {
1.41 + memclr(iCount, sizeof(iCount));
1.42 + memclr(iExpected, sizeof(iExpected));
1.43 + }
1.44 +
1.45 +TTestIPI* TTestIPI::New()
1.46 + {
1.47 + TTestIPI* p = new TTestIPI;
1.48 + TEST_OOM(p);
1.49 + return p;
1.50 + }
1.51 +
1.52 +void TTestIPI::Isr(TGenericIPI* a)
1.53 + {
1.54 + TTestIPI& ipi = *(TTestIPI*)a;
1.55 + TInt cpu = NKern::CurrentCpu();
1.56 + ++ipi.iCount[cpu];
1.57 + }
1.58 +
1.59 +void TTestIPI::IncM(TUint32 aMask)
1.60 + {
1.61 + TInt i;
1.62 + for(i=0; i<KMaxCpus; ++i)
1.63 + {
1.64 + if (aMask & (1<<i))
1.65 + ++iExpected[i];
1.66 + }
1.67 + }
1.68 +
1.69 +void TTestIPI::Check()
1.70 + {
1.71 + TInt i;
1.72 + for(i=0; i<KMaxCpus; ++i)
1.73 + {
1.74 + TEST_RESULT3(iCount[i]==iExpected[i], "CPU %d Count %d Expected %d", i, iCount[i], iExpected[i]);
1.75 + }
1.76 + }
1.77 +
1.78 +void IPITestThread1(TAny*)
1.79 + {
1.80 + TInt cpu;
1.81 + TUint32 all_cpus = ~(0xffffffffu << NKern::NumberOfCpus());
1.82 +
1.83 + for_each_cpu(cpu)
1.84 + {
1.85 + TEST_PRINT("ipi1");
1.86 + TTestIPI ipi;
1.87 + ipi.Queue(&TTestIPI::Isr, 1u<<cpu);
1.88 + ipi.WaitCompletion();
1.89 + ipi.Inc(cpu);
1.90 + ipi.Check();
1.91 +
1.92 + TEST_PRINT("ipi2");
1.93 + TTestIPI ipi2;
1.94 + TUint32 m = all_cpus & ~(1u<<cpu);
1.95 + ipi2.Queue(&TTestIPI::Isr, m);
1.96 + ipi2.WaitCompletion();
1.97 + ipi2.IncM(m);
1.98 + ipi2.Check();
1.99 + }
1.100 +
1.101 + TEST_PRINT("ipi3");
1.102 + TTestIPI ipi3;
1.103 + ipi3.QueueAll(&TTestIPI::Isr);
1.104 + ipi3.WaitCompletion();
1.105 + ipi3.IncM(all_cpus);
1.106 + ipi3.Check();
1.107 +
1.108 + TEST_PRINT("ipi4");
1.109 + TTestIPI ipi4;
1.110 + ipi4.QueueAllOther(&TTestIPI::Isr);
1.111 + ipi4.WaitCompletion();
1.112 + ipi4.IncM(all_cpus & ~(1u<<NKern::CurrentCpu()) );
1.113 + ipi4.Check();
1.114 + }
1.115 +
1.116 +void DoIPITest1()
1.117 + {
1.118 + TInt cpu;
1.119 + for_each_cpu(cpu)
1.120 + {
1.121 + CreateThreadAndWaitForExit("IPITest1", &IPITestThread1, 12, 0, 0, -1, cpu);
1.122 + }
1.123 + }
1.124 +
1.125 +
1.126 +class TTestIPI2 : public TGenericIPI
1.127 + {
1.128 +public:
1.129 + TTestIPI2(TInt aId);
1.130 + static TTestIPI2* New(TInt aId);
1.131 + static void Isr(TGenericIPI*);
1.132 + static void Thread(TAny*);
1.133 +public:
1.134 + TInt iId;
1.135 +public:
1.136 + enum {EMaxIPI=32};
1.137 + enum {EBufSize=256};
1.138 + static volatile TInt NextPos;
1.139 + static volatile TUint32 Buffer[EBufSize];
1.140 + static volatile TUint32 PauseHere;
1.141 + };
1.142 +
1.143 +volatile TInt TTestIPI2::NextPos;
1.144 +volatile TUint32 TTestIPI2::Buffer[TTestIPI2::EBufSize];
1.145 +volatile TUint32 TTestIPI2::PauseHere;
1.146 +
1.147 +__ASSERT_COMPILE(TTestIPI2::EBufSize >= TTestIPI2::EMaxIPI*KMaxCpus);
1.148 +
1.149 +TTestIPI2::TTestIPI2(TInt aId)
1.150 + : iId(aId)
1.151 + {
1.152 + }
1.153 +
1.154 +TTestIPI2* TTestIPI2::New(TInt aId)
1.155 + {
1.156 + TTestIPI2* p = new TTestIPI2(aId);
1.157 + TEST_OOM(p);
1.158 + return p;
1.159 + }
1.160 +
1.161 +void TTestIPI2::Isr(TGenericIPI* a)
1.162 + {
1.163 + TTestIPI2& ipi = *(TTestIPI2*)a;
1.164 + TUint32 cpu = NKern::CurrentCpu();
1.165 + TUint32 x = (cpu<<16) | ipi.iId;
1.166 + TInt pos = __e32_atomic_tas_ord32(&NextPos, EBufSize, 0, 1);
1.167 + if (pos < EBufSize)
1.168 + Buffer[pos] = x;
1.169 + while (PauseHere == x)
1.170 + {}
1.171 + }
1.172 +
1.173 +void TTestIPI2::Thread(TAny*)
1.174 + {
1.175 + TTestIPI2* ipi[EMaxIPI];
1.176 + TUint32 all_cpus = ~(0xffffffffu << NKern::NumberOfCpus());
1.177 + TInt this_cpu = NKern::CurrentCpu();
1.178 + TInt pause_cpu = this_cpu + 1;
1.179 + if (pause_cpu >= NKern::NumberOfCpus())
1.180 + pause_cpu = 0;
1.181 + if (pause_cpu == this_cpu)
1.182 + pause_cpu = -1;
1.183 + TUint32 this_cpu_mask = 1u<<this_cpu;
1.184 + TUint32 pause_cpu_mask = (pause_cpu>=0) ? (1u<<pause_cpu) : 0;
1.185 + TUint32 other_cpus = all_cpus & ~(this_cpu_mask | pause_cpu_mask);
1.186 + TInt num_other_cpus = __e32_bit_count_32(other_cpus);
1.187 + TInt i;
1.188 + for(i=0; i<EMaxIPI; ++i)
1.189 + ipi[i] = New(i+1);
1.190 +
1.191 + NextPos = 0;
1.192 + PauseHere = 0;
1.193 + if (pause_cpu >= 0)
1.194 + PauseHere = (pause_cpu<<16) | (EMaxIPI/2);
1.195 +
1.196 + TEST_PRINT3("this_cpu=%d pause_cpu=%d PauseHere=%x", this_cpu, pause_cpu, PauseHere);
1.197 +
1.198 + TInt irq = NKern::DisableAllInterrupts();
1.199 + for (i=0; i<EMaxIPI; ++i)
1.200 + ipi[i]->QueueAll(&Isr);
1.201 +
1.202 + TInt expected1 = num_other_cpus*EMaxIPI + EMaxIPI/2;
1.203 + while (NextPos != expected1)
1.204 + {}
1.205 +
1.206 + PauseHere = 0;
1.207 + TInt expected2 = num_other_cpus*EMaxIPI + EMaxIPI;
1.208 + while (NextPos != expected2)
1.209 + {}
1.210 + NKern::RestoreInterrupts(irq);
1.211 + ipi[EMaxIPI-1]->WaitCompletion();
1.212 +
1.213 + for(i=0; i<NextPos; ++i)
1.214 + {
1.215 + TEST_PRINT1("%08x", Buffer[i]);
1.216 + }
1.217 +
1.218 + for(i=0; i<EMaxIPI; ++i)
1.219 + delete ipi[i];
1.220 + }
1.221 +
1.222 +void DoIPITest2()
1.223 + {
1.224 + TInt cpu;
1.225 + for_each_cpu(cpu)
1.226 + {
1.227 + CreateThreadAndWaitForExit("IPITest2", &TTestIPI2::Thread, 12, 0, 0, -1, cpu);
1.228 + }
1.229 + }
1.230 +
1.231 +
1.232 +void TestIPI()
1.233 + {
1.234 + TEST_PRINT("Testing generic IPIs...");
1.235 +
1.236 + DoIPITest1();
1.237 + DoIPITest2();
1.238 + }
1.239 +
1.240 +#else // __SMP__
1.241 +void TestIPI()
1.242 + {
1.243 + }
1.244 +#endif // __SMP__