|
1 // Copyright (c) 2008-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\system\t_atomic_common.cpp |
|
15 // |
|
16 // |
|
17 |
|
18 #ifdef __KERNEL_MODE__ |
|
19 #include <kernel/kernel.h> |
|
20 #else |
|
21 #define __E32TEST_EXTENSION__ |
|
22 |
|
23 #include <e32test.h> |
|
24 |
|
25 extern RTest test; |
|
26 |
|
27 #define __INCLUDE_FUNC_NAMES__ |
|
28 #endif |
|
29 |
|
30 #define __INCLUDE_ATOMIC_FUNCTIONS__ |
|
31 #define __INCLUDE_CONTROL_FUNCTIONS__ |
|
32 #define __INCLUDE_FUNCTION_ATTRIBUTES__ |
|
33 |
|
34 #include "t_atomic.h" |
|
35 |
|
36 #define DEBUGPRINTVAR(x) \ |
|
37 { \ |
|
38 const TUint8* p = (const TUint8*)&(x); \ |
|
39 DEBUGPRINT("Line %d: " #x "=%02x %02x %02x %02x %02x %02x %02x %02x", __LINE__, p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); \ |
|
40 } |
|
41 |
|
42 extern "C" { |
|
43 |
|
44 // Simulated versions of atomic functions without the atomicity |
|
45 #define __LOAD(T) return *(T*)a |
|
46 #define __STORE(T) *(T*)a=v; return v |
|
47 #define __SWP(T) T oldv=*(T*)a; *(T*)a=v; return oldv |
|
48 #define __CAS(T) if (*(T*)a==*q) {*(T*)a=v; return 1;} *q=*(T*)a; return 0 |
|
49 #define __ADD(T) T oldv=*(T*)a; *(T*)a=(T)(oldv+v); return oldv |
|
50 #define __AND(T) T oldv=*(T*)a; *(T*)a=(T)(oldv&v); return oldv |
|
51 #define __IOR(T) T oldv=*(T*)a; *(T*)a=(T)(oldv|v); return oldv |
|
52 #define __XOR(T) T oldv=*(T*)a; *(T*)a=(T)(oldv^v); return oldv |
|
53 #define __AXO(T) T oldv=*(T*)a; *(T*)a=(T)((oldv&u)^v); return oldv |
|
54 #define __TA(T) T oldv=*(T*)a; *(T*)a=(T)(oldv+((oldv>=t)?u:v)); return oldv |
|
55 |
|
56 TUint8 __nonatomic_load8(const volatile TAny* a) |
|
57 { |
|
58 __LOAD(TUint8); |
|
59 } |
|
60 |
|
61 TUint8 __nonatomic_store8(volatile TAny* a, TUint8 v) |
|
62 { |
|
63 __STORE(TUint8); |
|
64 } |
|
65 |
|
66 TUint8 __nonatomic_swp8(volatile TAny* a, TUint8 v) |
|
67 { |
|
68 __SWP(TUint8); |
|
69 } |
|
70 |
|
71 TBool __nonatomic_cas8(volatile TAny* a, TUint8* q, TUint8 v) |
|
72 { |
|
73 __CAS(TUint8); |
|
74 } |
|
75 |
|
76 TUint8 __nonatomic_add8(volatile TAny* a, TUint8 v) |
|
77 { |
|
78 __ADD(TUint8); |
|
79 } |
|
80 |
|
81 TUint8 __nonatomic_and8(volatile TAny* a, TUint8 v) |
|
82 { |
|
83 __AND(TUint8); |
|
84 } |
|
85 |
|
86 TUint8 __nonatomic_ior8(volatile TAny* a, TUint8 v) |
|
87 { |
|
88 __IOR(TUint8); |
|
89 } |
|
90 |
|
91 TUint8 __nonatomic_xor8(volatile TAny* a, TUint8 v) |
|
92 { |
|
93 __XOR(TUint8); |
|
94 } |
|
95 |
|
96 TUint8 __nonatomic_axo8(volatile TAny* a, TUint8 u, TUint8 v) |
|
97 { |
|
98 __AXO(TUint8); |
|
99 } |
|
100 |
|
101 TUint8 __nonatomic_tau8(volatile TAny* a, TUint8 t, TUint8 u, TUint8 v) |
|
102 { |
|
103 __TA(TUint8); |
|
104 } |
|
105 |
|
106 TInt8 __nonatomic_tas8(volatile TAny* a, TInt8 t, TInt8 u, TInt8 v) |
|
107 { |
|
108 __TA(TInt8); |
|
109 } |
|
110 |
|
111 |
|
112 TUint16 __nonatomic_load16(const volatile TAny* a) |
|
113 { |
|
114 __LOAD(TUint16); |
|
115 } |
|
116 |
|
117 TUint16 __nonatomic_store16(volatile TAny* a, TUint16 v) |
|
118 { |
|
119 __STORE(TUint16); |
|
120 } |
|
121 |
|
122 TUint16 __nonatomic_swp16(volatile TAny* a, TUint16 v) |
|
123 { |
|
124 __SWP(TUint16); |
|
125 } |
|
126 |
|
127 TBool __nonatomic_cas16(volatile TAny* a, TUint16* q, TUint16 v) |
|
128 { |
|
129 __CAS(TUint16); |
|
130 } |
|
131 |
|
132 TUint16 __nonatomic_add16(volatile TAny* a, TUint16 v) |
|
133 { |
|
134 __ADD(TUint16); |
|
135 } |
|
136 |
|
137 TUint16 __nonatomic_and16(volatile TAny* a, TUint16 v) |
|
138 { |
|
139 __AND(TUint16); |
|
140 } |
|
141 |
|
142 TUint16 __nonatomic_ior16(volatile TAny* a, TUint16 v) |
|
143 { |
|
144 __IOR(TUint16); |
|
145 } |
|
146 |
|
147 TUint16 __nonatomic_xor16(volatile TAny* a, TUint16 v) |
|
148 { |
|
149 __XOR(TUint16); |
|
150 } |
|
151 |
|
152 TUint16 __nonatomic_axo16(volatile TAny* a, TUint16 u, TUint16 v) |
|
153 { |
|
154 __AXO(TUint16); |
|
155 } |
|
156 |
|
157 TUint16 __nonatomic_tau16(volatile TAny* a, TUint16 t, TUint16 u, TUint16 v) |
|
158 { |
|
159 __TA(TUint16); |
|
160 } |
|
161 |
|
162 TInt16 __nonatomic_tas16(volatile TAny* a, TInt16 t, TInt16 u, TInt16 v) |
|
163 { |
|
164 __TA(TInt16); |
|
165 } |
|
166 |
|
167 |
|
168 TUint32 __nonatomic_load32(const volatile TAny* a) |
|
169 { |
|
170 __LOAD(TUint32); |
|
171 } |
|
172 |
|
173 TUint32 __nonatomic_store32(volatile TAny* a, TUint32 v) |
|
174 { |
|
175 __STORE(TUint32); |
|
176 } |
|
177 |
|
178 TUint32 __nonatomic_swp32(volatile TAny* a, TUint32 v) |
|
179 { |
|
180 __SWP(TUint32); |
|
181 } |
|
182 |
|
183 TBool __nonatomic_cas32(volatile TAny* a, TUint32* q, TUint32 v) |
|
184 { |
|
185 __CAS(TUint32); |
|
186 } |
|
187 |
|
188 TUint32 __nonatomic_add32(volatile TAny* a, TUint32 v) |
|
189 { |
|
190 __ADD(TUint32); |
|
191 } |
|
192 |
|
193 TUint32 __nonatomic_and32(volatile TAny* a, TUint32 v) |
|
194 { |
|
195 __AND(TUint32); |
|
196 } |
|
197 |
|
198 TUint32 __nonatomic_ior32(volatile TAny* a, TUint32 v) |
|
199 { |
|
200 __IOR(TUint32); |
|
201 } |
|
202 |
|
203 TUint32 __nonatomic_xor32(volatile TAny* a, TUint32 v) |
|
204 { |
|
205 __XOR(TUint32); |
|
206 } |
|
207 |
|
208 TUint32 __nonatomic_axo32(volatile TAny* a, TUint32 u, TUint32 v) |
|
209 { |
|
210 __AXO(TUint32); |
|
211 } |
|
212 |
|
213 TUint32 __nonatomic_tau32(volatile TAny* a, TUint32 t, TUint32 u, TUint32 v) |
|
214 { |
|
215 __TA(TUint32); |
|
216 } |
|
217 |
|
218 TInt32 __nonatomic_tas32(volatile TAny* a, TInt32 t, TInt32 u, TInt32 v) |
|
219 { |
|
220 __TA(TInt32); |
|
221 } |
|
222 |
|
223 |
|
224 TUint64 __nonatomic_load64(const volatile TAny* a) |
|
225 { |
|
226 __LOAD(TUint64); |
|
227 } |
|
228 |
|
229 TUint64 __nonatomic_store64(volatile TAny* a, TUint64 v) |
|
230 { |
|
231 __STORE(TUint64); |
|
232 } |
|
233 |
|
234 TUint64 __nonatomic_swp64(volatile TAny* a, TUint64 v) |
|
235 { |
|
236 __SWP(TUint64); |
|
237 } |
|
238 |
|
239 TBool __nonatomic_cas64(volatile TAny* a, TUint64* q, TUint64 v) |
|
240 { |
|
241 __CAS(TUint64); |
|
242 } |
|
243 |
|
244 TUint64 __nonatomic_add64(volatile TAny* a, TUint64 v) |
|
245 { |
|
246 __ADD(TUint64); |
|
247 } |
|
248 |
|
249 TUint64 __nonatomic_and64(volatile TAny* a, TUint64 v) |
|
250 { |
|
251 __AND(TUint64); |
|
252 } |
|
253 |
|
254 TUint64 __nonatomic_ior64(volatile TAny* a, TUint64 v) |
|
255 { |
|
256 __IOR(TUint64); |
|
257 } |
|
258 |
|
259 TUint64 __nonatomic_xor64(volatile TAny* a, TUint64 v) |
|
260 { |
|
261 __XOR(TUint64); |
|
262 } |
|
263 |
|
264 TUint64 __nonatomic_axo64(volatile TAny* a, TUint64 u, TUint64 v) |
|
265 { |
|
266 __AXO(TUint64); |
|
267 } |
|
268 |
|
269 TUint64 __nonatomic_tau64(volatile TAny* a, TUint64 t, TUint64 u, TUint64 v) |
|
270 { |
|
271 __TA(TUint64); |
|
272 } |
|
273 |
|
274 TInt64 __nonatomic_tas64(volatile TAny* a, TInt64 t, TInt64 u, TInt64 v) |
|
275 { |
|
276 __TA(TInt64); |
|
277 } |
|
278 |
|
279 } // extern "C" |
|
280 |
|
281 |
|
282 #define DEBUGPRINTxyrc() \ |
|
283 DEBUGPRINTVAR(x); \ |
|
284 DEBUGPRINTVAR(y); \ |
|
285 DEBUGPRINTVAR(r); \ |
|
286 DEBUGPRINTVAR(c) |
|
287 |
|
288 template<class T> TInt DoLoadTest(TInt aIndex, TAny* aPtr, T aInitialValue) |
|
289 { |
|
290 #ifdef __EXTRA_DEBUG__ |
|
291 DEBUGPRINT("DoLoadTest %d %08x", aIndex, aPtr); |
|
292 #endif |
|
293 typename TLoadFn<T>::F atomic = (typename TLoadFn<T>::F)AtomicFuncPtr[aIndex]; |
|
294 typename TLoadFn<T>::F control = (typename TLoadFn<T>::F)ControlFuncPtr[aIndex]; |
|
295 T& x = *(T*)aPtr; |
|
296 x = aInitialValue; |
|
297 T y = aInitialValue; |
|
298 T r = atomic(&x); |
|
299 T c = control(&y); |
|
300 if (r!=c || x!=y) |
|
301 { |
|
302 DEBUGPRINTxyrc(); |
|
303 return __LINE__; |
|
304 } |
|
305 return 0; |
|
306 } |
|
307 |
|
308 template<class T> TInt DoRmw1Test(TInt aIndex, TAny* aPtr, T aInitialValue, T a1) |
|
309 { |
|
310 #ifdef __EXTRA_DEBUG__ |
|
311 DEBUGPRINT("DoRmw1Test %d %08x", aIndex, aPtr); |
|
312 #endif |
|
313 typename TRmw1Fn<T>::F atomic = (typename TRmw1Fn<T>::F)AtomicFuncPtr[aIndex]; |
|
314 typename TRmw1Fn<T>::F control = (typename TRmw1Fn<T>::F)ControlFuncPtr[aIndex]; |
|
315 T& x = *(T*)aPtr; |
|
316 x = aInitialValue; |
|
317 T y = aInitialValue; |
|
318 T r = atomic(&x,a1); |
|
319 T c = control(&y,a1); |
|
320 if (r!=c || x!=y) |
|
321 { |
|
322 DEBUGPRINTxyrc(); |
|
323 return __LINE__; |
|
324 } |
|
325 return 0; |
|
326 } |
|
327 |
|
328 template<class T> TInt DoRmw2Test(TInt aIndex, TAny* aPtr, T aInitialValue, T a1, T a2) |
|
329 { |
|
330 #ifdef __EXTRA_DEBUG__ |
|
331 DEBUGPRINT("DoRmw2Test %d %08x", aIndex, aPtr); |
|
332 #endif |
|
333 typename TRmw2Fn<T>::F atomic = (typename TRmw2Fn<T>::F)AtomicFuncPtr[aIndex]; |
|
334 typename TRmw2Fn<T>::F control = (typename TRmw2Fn<T>::F)ControlFuncPtr[aIndex]; |
|
335 T& x = *(T*)aPtr; |
|
336 x = aInitialValue; |
|
337 T y = aInitialValue; |
|
338 T r = atomic(&x,a1,a2); |
|
339 T c = control(&y,a1,a2); |
|
340 if (r!=c || x!=y) |
|
341 { |
|
342 DEBUGPRINTxyrc(); |
|
343 return __LINE__; |
|
344 } |
|
345 return 0; |
|
346 } |
|
347 |
|
348 template<class T> TInt DoRmw3Test(TInt aIndex, TAny* aPtr, T aInitialValue, T a1, T a2, T a3) |
|
349 { |
|
350 #ifdef __EXTRA_DEBUG__ |
|
351 DEBUGPRINT("DoRmw3Test %d %08x", aIndex, aPtr); |
|
352 #endif |
|
353 typename TRmw3Fn<T>::F atomic = (typename TRmw3Fn<T>::F)AtomicFuncPtr[aIndex]; |
|
354 typename TRmw3Fn<T>::F control = (typename TRmw3Fn<T>::F)ControlFuncPtr[aIndex]; |
|
355 T& x = *(T*)aPtr; |
|
356 x = aInitialValue; |
|
357 T y = aInitialValue; |
|
358 T r = atomic(&x,a1,a2,a3); |
|
359 T c = control(&y,a1,a2,a3); |
|
360 if (r!=c || x!=y) |
|
361 { |
|
362 DEBUGPRINTxyrc(); |
|
363 return __LINE__; |
|
364 } |
|
365 return 0; |
|
366 } |
|
367 |
|
368 template<class T> TInt DoCasTest(TInt aIndex, TAny* aPtr, T aInitialValue, T aExpectedValue, T aFinalValue) |
|
369 { |
|
370 #ifdef __EXTRA_DEBUG__ |
|
371 DEBUGPRINT("DoCasTest %d %08x", aIndex, aPtr); |
|
372 #endif |
|
373 typename TCasFn<T>::F atomic = (typename TCasFn<T>::F)AtomicFuncPtr[aIndex]; |
|
374 typename TCasFn<T>::F control = (typename TCasFn<T>::F)ControlFuncPtr[aIndex]; |
|
375 T& x = *(T*)aPtr; |
|
376 x = aInitialValue; |
|
377 T ex = aExpectedValue; |
|
378 T y = aInitialValue; |
|
379 T ey = aExpectedValue; |
|
380 TBool r = atomic(&x,&ex,aFinalValue); |
|
381 TBool c = control(&y,&ey,aFinalValue); |
|
382 TInt line = 0; |
|
383 if (r && !c) |
|
384 line = __LINE__; |
|
385 else if (!r && c) |
|
386 line = __LINE__; |
|
387 else if (x!=y) |
|
388 line = __LINE__; |
|
389 else if (ex!=ey) |
|
390 line = __LINE__; |
|
391 else if (r && x!=aFinalValue) |
|
392 line = __LINE__; |
|
393 else if (!r && ex!=aInitialValue) |
|
394 line = __LINE__; |
|
395 if (line) |
|
396 { |
|
397 DEBUGPRINT("r=%d",r); |
|
398 DEBUGPRINTVAR(x); |
|
399 DEBUGPRINTVAR(ex); |
|
400 DEBUGPRINT("c=%d",c); |
|
401 DEBUGPRINTVAR(y); |
|
402 DEBUGPRINTVAR(ey); |
|
403 } |
|
404 return line; |
|
405 } |
|
406 |
|
407 |
|
408 |
|
409 TEnclosed::TEnclosed(TInt aSize) |
|
410 { |
|
411 iOffset = -1; |
|
412 iSize = aSize; |
|
413 iData = (TUint64*)((T_UintPtr(i_Data) + 7) &~ 7); // align up to next 8 byte boundary |
|
414 iBackup = iData + 8; |
|
415 } |
|
416 |
|
417 TAny* TEnclosed::Ptr() |
|
418 { |
|
419 return ((TUint8*)iData + iOffset); |
|
420 } |
|
421 |
|
422 TInt TEnclosed::Next() |
|
423 { |
|
424 const TInt KLimit[8] = {8, 16, 0, 32, 0, 0, 0, 32}; |
|
425 if (iOffset<0) |
|
426 iOffset = 0; |
|
427 else |
|
428 { |
|
429 TInt r = Verify(); |
|
430 if (r!=0) |
|
431 return r; |
|
432 iOffset += iSize; |
|
433 } |
|
434 if (iOffset >= KLimit[iSize-1]) |
|
435 return KErrEof; |
|
436 Init(); |
|
437 return KErrNone; |
|
438 } |
|
439 |
|
440 void TEnclosed::Init() |
|
441 { |
|
442 TUint32 x = iOffset+1; |
|
443 x |= (x<<8); |
|
444 x |= (x<<16); |
|
445 TUint32* d = (TUint32*)iData; |
|
446 TUint32* b = (TUint32*)iBackup; |
|
447 TInt i; |
|
448 for (i=0; i<16; ++i) |
|
449 { |
|
450 *d++ = x; |
|
451 *b++ = x; |
|
452 x = 69069*x + 41; |
|
453 } |
|
454 } |
|
455 |
|
456 TInt TEnclosed::Verify() |
|
457 { |
|
458 TUint8* d = (TUint8*)iData; |
|
459 const TUint8* b = (const TUint8*)iBackup; |
|
460 TInt i; |
|
461 for (i=0; i<iSize; ++i) |
|
462 d[iOffset+i] = b[iOffset+i]; |
|
463 if (memcompare(b,64,d,64)) |
|
464 { |
|
465 DEBUGPRINT("FAIL! iOffset=%02x, sizeof(T)=%1d", iOffset, iSize); |
|
466 for (i=0; i<64; ++i) |
|
467 { |
|
468 if (d[i]!=b[i]) |
|
469 { |
|
470 DEBUGPRINT("d[%02x]=%02x b[%02x]=%02x", i, d[i], i, b[i]); |
|
471 } |
|
472 } |
|
473 return __LINE__; |
|
474 } |
|
475 return 0; |
|
476 } |
|
477 |
|
478 |
|
479 TInt TDGBase::Execute() |
|
480 { |
|
481 PFV af0 = AtomicFuncPtr[iIndex]; |
|
482 PFV cf0 = ControlFuncPtr[iIndex]; |
|
483 if (!af0 || !cf0) |
|
484 return __LINE__; |
|
485 TUint attr = FuncAttr[iIndex]; |
|
486 TInt type = ATTR_TO_TYPE(attr); |
|
487 TInt size = ATTR_TO_SIZE(attr); |
|
488 TInt func = ATTR_TO_FUNC(attr); |
|
489 if (type==EFuncTypeInvalid) |
|
490 return __LINE__; |
|
491 #ifdef __EXTRA_DEBUG__ |
|
492 TInt ord = ATTR_TO_ORD(attr); |
|
493 DEBUGPRINT("A=%08x T=%d O=%d S=%d F=%d", attr, type, ord, size, func); |
|
494 #endif |
|
495 TEnclosed enc(size); |
|
496 TInt res = 0; |
|
497 while ( (res = enc.Next()) == KErrNone ) |
|
498 { |
|
499 #ifdef __EXTRA_DEBUG__ |
|
500 DEBUGPRINT("Offset %02x", enc.Offset()); |
|
501 #endif |
|
502 TAny* ptr = enc.Ptr(); |
|
503 switch (type) |
|
504 { |
|
505 case EFuncTypeLoad: |
|
506 { |
|
507 switch (size) |
|
508 { |
|
509 case 1: res = DoLoadTest<TUint8>(iIndex, ptr, (TUint8)i0); break; |
|
510 case 2: res = DoLoadTest<TUint16>(iIndex, ptr, (TUint16)i0); break; |
|
511 case 4: res = DoLoadTest<TUint32>(iIndex, ptr, (TUint32)i0); break; |
|
512 case 8: res = DoLoadTest<TUint64>(iIndex, ptr, i0); break; |
|
513 default: res = __LINE__; break; |
|
514 } |
|
515 break; |
|
516 } |
|
517 case EFuncTypeRmw1: |
|
518 { |
|
519 switch (size) |
|
520 { |
|
521 case 1: res = DoRmw1Test<TUint8>(iIndex, ptr, (TUint8)i0, (TUint8)i1); break; |
|
522 case 2: res = DoRmw1Test<TUint16>(iIndex, ptr, (TUint16)i0, (TUint16)i1); break; |
|
523 case 4: res = DoRmw1Test<TUint32>(iIndex, ptr, (TUint32)i0, (TUint32)i1); break; |
|
524 case 8: res = DoRmw1Test<TUint64>(iIndex, ptr, i0, i1); break; |
|
525 default: res = __LINE__; break; |
|
526 } |
|
527 break; |
|
528 } |
|
529 case EFuncTypeRmw2: |
|
530 { |
|
531 switch (size) |
|
532 { |
|
533 case 1: res = DoRmw2Test<TUint8>(iIndex, ptr, (TUint8)i0, (TUint8)i1, (TUint8)i2); break; |
|
534 case 2: res = DoRmw2Test<TUint16>(iIndex, ptr, (TUint16)i0, (TUint16)i1, (TUint16)i2); break; |
|
535 case 4: res = DoRmw2Test<TUint32>(iIndex, ptr, (TUint32)i0, (TUint32)i1, (TUint32)i2); break; |
|
536 case 8: res = DoRmw2Test<TUint64>(iIndex, ptr, i0, i1, i2); break; |
|
537 default: res = __LINE__; break; |
|
538 } |
|
539 break; |
|
540 } |
|
541 case EFuncTypeRmw3: |
|
542 { |
|
543 if (func==EAtomicFuncTAU) |
|
544 { |
|
545 switch (size) |
|
546 { |
|
547 case 1: res = DoRmw3Test<TUint8>(iIndex, ptr, (TUint8)i0, (TUint8)i1, (TUint8)i2, (TUint8)i3); break; |
|
548 case 2: res = DoRmw3Test<TUint16>(iIndex, ptr, (TUint16)i0, (TUint16)i1, (TUint16)i2, (TUint16)i3); break; |
|
549 case 4: res = DoRmw3Test<TUint32>(iIndex, ptr, (TUint32)i0, (TUint32)i1, (TUint32)i2, (TUint32)i3); break; |
|
550 case 8: res = DoRmw3Test<TUint64>(iIndex, ptr, i0, i1, i2, i3); break; |
|
551 default: res = __LINE__; break; |
|
552 } |
|
553 } |
|
554 else if (func==EAtomicFuncTAS) |
|
555 { |
|
556 switch (size) |
|
557 { |
|
558 case 1: res = DoRmw3Test<TInt8>(iIndex, ptr, (TInt8)i0, (TInt8)i1, (TInt8)i2, (TInt8)i3); break; |
|
559 case 2: res = DoRmw3Test<TInt16>(iIndex, ptr, (TInt16)i0, (TInt16)i1, (TInt16)i2, (TInt16)i3); break; |
|
560 case 4: res = DoRmw3Test<TInt32>(iIndex, ptr, (TInt32)i0, (TInt32)i1, (TInt32)i2, (TInt32)i3); break; |
|
561 case 8: res = DoRmw3Test<TInt64>(iIndex, ptr, i0, i1, i2, i3); break; |
|
562 default: res = __LINE__; break; |
|
563 } |
|
564 } |
|
565 else |
|
566 res = __LINE__; |
|
567 break; |
|
568 } |
|
569 case EFuncTypeCas: |
|
570 { |
|
571 switch (size) |
|
572 { |
|
573 case 1: res = DoCasTest<TUint8>(iIndex, ptr, (TUint8)i0, (TUint8)i1, (TUint8)i2); break; |
|
574 case 2: res = DoCasTest<TUint16>(iIndex, ptr, (TUint16)i0, (TUint16)i1, (TUint16)i2); break; |
|
575 case 4: res = DoCasTest<TUint32>(iIndex, ptr, (TUint32)i0, (TUint32)i1, (TUint32)i2); break; |
|
576 case 8: res = DoCasTest<TUint64>(iIndex, ptr, i0, i1, i2); break; |
|
577 default: res = __LINE__; break; |
|
578 } |
|
579 break; |
|
580 } |
|
581 default: |
|
582 res = __LINE__; |
|
583 break; |
|
584 } |
|
585 if (res) |
|
586 return res; |
|
587 } |
|
588 if (res == KErrEof) |
|
589 res = 0; |
|
590 return res; |
|
591 } |
|
592 |
|
593 #ifndef __KERNEL_MODE__ |
|
594 void TDGBase::Dump(const char* aTitle) |
|
595 { |
|
596 TPtrC8 fname8((const TText8*)FuncName[iIndex]); |
|
597 TBuf<64> fname; |
|
598 fname.Copy(fname8); |
|
599 DEBUGPRINT(aTitle); |
|
600 DEBUGPRINT("iIndex=%d (%S)", iIndex, &fname); |
|
601 DEBUGPRINT("i0 = %08x %08x", I64HIGH(i0), I64LOW(i0)); |
|
602 DEBUGPRINT("i1 = %08x %08x", I64HIGH(i1), I64LOW(i1)); |
|
603 DEBUGPRINT("i2 = %08x %08x", I64HIGH(i2), I64LOW(i2)); |
|
604 DEBUGPRINT("i3 = %08x %08x", I64HIGH(i3), I64LOW(i3)); |
|
605 } |
|
606 #endif |
|
607 |
|
608 template<class T> TInt DoSwap(TAny* aPtr, TPerThread* aT, TAtomicAction& aA, T*) |
|
609 { |
|
610 typename TRmw1Fn<T>::F atomic = (typename TRmw1Fn<T>::F)AtomicFuncPtr[aA.iIndex]; |
|
611 T newv = (T)aA.i0; |
|
612 T orig = atomic(aPtr, newv); |
|
613 T xr = (T)(newv ^ orig); |
|
614 aT->iXor ^= xr; |
|
615 T diff = (T)(newv - orig); |
|
616 aT->iDiff += diff; |
|
617 return 0; |
|
618 } |
|
619 |
|
620 template<class T> TInt DoAdd(TAny* aPtr, TPerThread* aT, TAtomicAction& aA, T*) |
|
621 { |
|
622 typename TRmw1Fn<T>::F atomic = (typename TRmw1Fn<T>::F)AtomicFuncPtr[aA.iIndex]; |
|
623 T arg = (T)aA.i0; |
|
624 T orig = atomic(aPtr, arg); |
|
625 T xr = (T)((arg+orig) ^ orig); |
|
626 aT->iXor ^= xr; |
|
627 aT->iDiff += arg; |
|
628 return 0; |
|
629 } |
|
630 |
|
631 template<class T> TInt DoXor(TAny* aPtr, TPerThread* aT, TAtomicAction& aA, T*) |
|
632 { |
|
633 typename TRmw1Fn<T>::F atomic = (typename TRmw1Fn<T>::F)AtomicFuncPtr[aA.iIndex]; |
|
634 T arg = (T)aA.i0; |
|
635 T orig = atomic(aPtr, arg); |
|
636 T diff = (T)((arg^orig) - orig); |
|
637 aT->iDiff += diff; |
|
638 aT->iXor ^= arg; |
|
639 return 0; |
|
640 } |
|
641 |
|
642 template<class T> TInt DoAndOr(TAny* aPtr, TPerThread* aT, TAtomicAction& aA, T*) |
|
643 { |
|
644 typename TRmw1Fn<T>::F atomic_and = (typename TRmw1Fn<T>::F)AtomicFuncPtr[aA.iIndex]; |
|
645 typename TRmw1Fn<T>::F atomic_or = (typename TRmw1Fn<T>::F)AtomicFuncPtr[aA.iIndex+4]; |
|
646 T aarg = (T)aA.i0; |
|
647 T oarg = (T)aA.i1; |
|
648 T aorig = atomic_and(aPtr, aarg); |
|
649 T oorig = atomic_or(aPtr, oarg); |
|
650 T adiff = (T)((aorig & aarg) - aorig); |
|
651 T odiff = (T)((oorig | oarg) - oorig); |
|
652 aT->iDiff += adiff + odiff; |
|
653 T axor = (T)((aorig & aarg) ^ aorig); |
|
654 T oxor = (T)((oorig | oarg) ^ oorig); |
|
655 aT->iXor ^= axor ^ oxor; |
|
656 return 0; |
|
657 } |
|
658 |
|
659 template<class T> TInt DoAxo(TAny* aPtr, TPerThread* aT, TAtomicAction& aA, T*) |
|
660 { |
|
661 typename TRmw2Fn<T>::F atomic = (typename TRmw2Fn<T>::F)AtomicFuncPtr[aA.iIndex]; |
|
662 T aarg = (T)aA.i0; |
|
663 T xarg = (T)aA.i1; |
|
664 T orig = atomic(aPtr, aarg, xarg); |
|
665 T newv = (T)((orig & aarg) ^ xarg); |
|
666 aT->iDiff += (newv - orig); |
|
667 aT->iXor ^= (newv ^ orig); |
|
668 return 0; |
|
669 } |
|
670 |
|
671 template<class T> TInt DoThAdd(TAny* aPtr, TPerThread* aT, TAtomicAction& aA, T*) |
|
672 { |
|
673 typename TRmw3Fn<T>::F atomic = (typename TRmw3Fn<T>::F)AtomicFuncPtr[aA.iIndex]; |
|
674 T thr = (T)aA.i0; |
|
675 T arg1 = (T)aA.i1; |
|
676 T arg2 = (T)aA.i2; |
|
677 T orig = atomic(aPtr, thr, arg1, arg2); |
|
678 T newv = (T)((orig >= thr) ? (orig + arg1) : (orig + arg2)); |
|
679 aT->iDiff += (orig >= thr) ? arg1 : arg2; |
|
680 aT->iXor ^= (newv ^ orig); |
|
681 return 0; |
|
682 } |
|
683 |
|
684 template<class T> TInt DoCas(TAny* aPtr, TPerThread* aT, TAtomicAction& aA, T*) |
|
685 { |
|
686 typename TCasFn<T>::F atomic = (typename TCasFn<T>::F)AtomicFuncPtr[aA.iIndex]; |
|
687 T orig = *(const volatile T*)aPtr; |
|
688 T newv; |
|
689 TBool done = FALSE; |
|
690 TUint32 fails = 0xffffffffu; |
|
691 do { |
|
692 ++fails; |
|
693 newv = Transform<T>::F(orig); |
|
694 done = atomic(aPtr, &orig, newv); |
|
695 } while(!done); |
|
696 aT->iFailCount += fails; |
|
697 ++aT->iDiff; |
|
698 aT->iXor ^= (newv ^ orig); |
|
699 return 0; |
|
700 } |
|
701 |
|
702 volatile TUint Dummy; |
|
703 extern "C" TInt DoAtomicAction(TAny* aPtr, TPerThread* aT, TAtomicAction& aA) |
|
704 { |
|
705 TUint x = TUint(aT)*0x9E3779B9u; |
|
706 x = (x>>8)&15; |
|
707 while(x--) |
|
708 ++Dummy; |
|
709 TInt r = KErrNotSupported; |
|
710 TUint attr = FuncAttr[aA.iIndex]; |
|
711 TUint func = ATTR_TO_FUNC(attr); |
|
712 TUint size = ATTR_TO_SIZE(attr); |
|
713 switch (size) |
|
714 { |
|
715 case 1: |
|
716 { |
|
717 TUint8 xx; |
|
718 TUint8* dummy = &xx; |
|
719 TInt8 yy; |
|
720 TInt8* sdummy = &yy; |
|
721 switch (func) |
|
722 { |
|
723 case EAtomicFuncSWP: r=DoSwap<TUint8>(aPtr, aT, aA, dummy); break; |
|
724 case EAtomicFuncADD: r=DoAdd<TUint8>(aPtr, aT, aA, dummy); break; |
|
725 case EAtomicFuncAND: r=DoAndOr<TUint8>(aPtr, aT, aA, dummy); break; |
|
726 case EAtomicFuncXOR: r=DoXor<TUint8>(aPtr, aT, aA, dummy); break; |
|
727 case EAtomicFuncAXO: r=DoAxo<TUint8>(aPtr, aT, aA, dummy); break; |
|
728 case EAtomicFuncTAU: r=DoThAdd<TUint8>(aPtr, aT, aA, dummy); break; |
|
729 case EAtomicFuncTAS: r=DoThAdd<TInt8>(aPtr, aT, aA, sdummy); break; |
|
730 case EAtomicFuncCAS: r=DoCas<TUint8>(aPtr, aT, aA, dummy); break; |
|
731 default: break; |
|
732 } |
|
733 break; |
|
734 } |
|
735 case 2: |
|
736 { |
|
737 TUint16 xx; |
|
738 TUint16* dummy = &xx; |
|
739 TInt16 yy; |
|
740 TInt16* sdummy = &yy; |
|
741 switch (func) |
|
742 { |
|
743 case EAtomicFuncSWP: r=DoSwap<TUint16>(aPtr, aT, aA, dummy); break; |
|
744 case EAtomicFuncADD: r=DoAdd<TUint16>(aPtr, aT, aA, dummy); break; |
|
745 case EAtomicFuncAND: r=DoAndOr<TUint16>(aPtr, aT, aA, dummy); break; |
|
746 case EAtomicFuncXOR: r=DoXor<TUint16>(aPtr, aT, aA, dummy); break; |
|
747 case EAtomicFuncAXO: r=DoAxo<TUint16>(aPtr, aT, aA, dummy); break; |
|
748 case EAtomicFuncTAU: r=DoThAdd<TUint16>(aPtr, aT, aA, dummy); break; |
|
749 case EAtomicFuncTAS: r=DoThAdd<TInt16>(aPtr, aT, aA, sdummy); break; |
|
750 case EAtomicFuncCAS: r=DoCas<TUint16>(aPtr, aT, aA, dummy); break; |
|
751 default: break; |
|
752 } |
|
753 break; |
|
754 } |
|
755 case 4: |
|
756 { |
|
757 TUint32 xx; |
|
758 TUint32* dummy = &xx; |
|
759 TInt32 yy; |
|
760 TInt32* sdummy = &yy; |
|
761 switch (func) |
|
762 { |
|
763 case EAtomicFuncSWP: r=DoSwap<TUint32>(aPtr, aT, aA, dummy); break; |
|
764 case EAtomicFuncADD: r=DoAdd<TUint32>(aPtr, aT, aA, dummy); break; |
|
765 case EAtomicFuncAND: r=DoAndOr<TUint32>(aPtr, aT, aA, dummy); break; |
|
766 case EAtomicFuncXOR: r=DoXor<TUint32>(aPtr, aT, aA, dummy); break; |
|
767 case EAtomicFuncAXO: r=DoAxo<TUint32>(aPtr, aT, aA, dummy); break; |
|
768 case EAtomicFuncTAU: r=DoThAdd<TUint32>(aPtr, aT, aA, dummy); break; |
|
769 case EAtomicFuncTAS: r=DoThAdd<TInt32>(aPtr, aT, aA, sdummy); break; |
|
770 case EAtomicFuncCAS: r=DoCas<TUint32>(aPtr, aT, aA, dummy); break; |
|
771 default: break; |
|
772 } |
|
773 break; |
|
774 } |
|
775 case 8: |
|
776 { |
|
777 TUint64A xx; |
|
778 TUint64* dummy = &xx; |
|
779 TInt64A yy; |
|
780 TInt64* sdummy = &yy; |
|
781 switch (func) |
|
782 { |
|
783 case EAtomicFuncSWP: r=DoSwap<TUint64>(aPtr, aT, aA, dummy); break; |
|
784 case EAtomicFuncADD: r=DoAdd<TUint64>(aPtr, aT, aA, dummy); break; |
|
785 case EAtomicFuncAND: r=DoAndOr<TUint64>(aPtr, aT, aA, dummy); break; |
|
786 case EAtomicFuncXOR: r=DoXor<TUint64>(aPtr, aT, aA, dummy); break; |
|
787 case EAtomicFuncAXO: r=DoAxo<TUint64>(aPtr, aT, aA, dummy); break; |
|
788 case EAtomicFuncTAU: r=DoThAdd<TUint64>(aPtr, aT, aA, dummy); break; |
|
789 case EAtomicFuncTAS: r=DoThAdd<TInt64>(aPtr, aT, aA, sdummy); break; |
|
790 case EAtomicFuncCAS: r=DoCas<TUint64>(aPtr, aT, aA, dummy); break; |
|
791 default: break; |
|
792 } |
|
793 break; |
|
794 } |
|
795 default: |
|
796 break; |
|
797 } |
|
798 ++aT->iCount; |
|
799 return r; |
|
800 } |
|
801 |
|
802 |
|
803 |