|
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__ |