1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/kernelhwsrv/kerneltest/e32test/system/t_atomic_common.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,803 @@
1.4 +// Copyright (c) 2008-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\system\t_atomic_common.cpp
1.18 +//
1.19 +//
1.20 +
1.21 +#ifdef __KERNEL_MODE__
1.22 +#include <kernel/kernel.h>
1.23 +#else
1.24 +#define __E32TEST_EXTENSION__
1.25 +
1.26 +#include <e32test.h>
1.27 +
1.28 +extern RTest test;
1.29 +
1.30 +#define __INCLUDE_FUNC_NAMES__
1.31 +#endif
1.32 +
1.33 +#define __INCLUDE_ATOMIC_FUNCTIONS__
1.34 +#define __INCLUDE_CONTROL_FUNCTIONS__
1.35 +#define __INCLUDE_FUNCTION_ATTRIBUTES__
1.36 +
1.37 +#include "t_atomic.h"
1.38 +
1.39 +#define DEBUGPRINTVAR(x) \
1.40 + { \
1.41 + const TUint8* p = (const TUint8*)&(x); \
1.42 + 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]); \
1.43 + }
1.44 +
1.45 +extern "C" {
1.46 +
1.47 +// Simulated versions of atomic functions without the atomicity
1.48 +#define __LOAD(T) return *(T*)a
1.49 +#define __STORE(T) *(T*)a=v; return v
1.50 +#define __SWP(T) T oldv=*(T*)a; *(T*)a=v; return oldv
1.51 +#define __CAS(T) if (*(T*)a==*q) {*(T*)a=v; return 1;} *q=*(T*)a; return 0
1.52 +#define __ADD(T) T oldv=*(T*)a; *(T*)a=(T)(oldv+v); return oldv
1.53 +#define __AND(T) T oldv=*(T*)a; *(T*)a=(T)(oldv&v); return oldv
1.54 +#define __IOR(T) T oldv=*(T*)a; *(T*)a=(T)(oldv|v); return oldv
1.55 +#define __XOR(T) T oldv=*(T*)a; *(T*)a=(T)(oldv^v); return oldv
1.56 +#define __AXO(T) T oldv=*(T*)a; *(T*)a=(T)((oldv&u)^v); return oldv
1.57 +#define __TA(T) T oldv=*(T*)a; *(T*)a=(T)(oldv+((oldv>=t)?u:v)); return oldv
1.58 +
1.59 +TUint8 __nonatomic_load8(const volatile TAny* a)
1.60 + {
1.61 + __LOAD(TUint8);
1.62 + }
1.63 +
1.64 +TUint8 __nonatomic_store8(volatile TAny* a, TUint8 v)
1.65 + {
1.66 + __STORE(TUint8);
1.67 + }
1.68 +
1.69 +TUint8 __nonatomic_swp8(volatile TAny* a, TUint8 v)
1.70 + {
1.71 + __SWP(TUint8);
1.72 + }
1.73 +
1.74 +TBool __nonatomic_cas8(volatile TAny* a, TUint8* q, TUint8 v)
1.75 + {
1.76 + __CAS(TUint8);
1.77 + }
1.78 +
1.79 +TUint8 __nonatomic_add8(volatile TAny* a, TUint8 v)
1.80 + {
1.81 + __ADD(TUint8);
1.82 + }
1.83 +
1.84 +TUint8 __nonatomic_and8(volatile TAny* a, TUint8 v)
1.85 + {
1.86 + __AND(TUint8);
1.87 + }
1.88 +
1.89 +TUint8 __nonatomic_ior8(volatile TAny* a, TUint8 v)
1.90 + {
1.91 + __IOR(TUint8);
1.92 + }
1.93 +
1.94 +TUint8 __nonatomic_xor8(volatile TAny* a, TUint8 v)
1.95 + {
1.96 + __XOR(TUint8);
1.97 + }
1.98 +
1.99 +TUint8 __nonatomic_axo8(volatile TAny* a, TUint8 u, TUint8 v)
1.100 + {
1.101 + __AXO(TUint8);
1.102 + }
1.103 +
1.104 +TUint8 __nonatomic_tau8(volatile TAny* a, TUint8 t, TUint8 u, TUint8 v)
1.105 + {
1.106 + __TA(TUint8);
1.107 + }
1.108 +
1.109 +TInt8 __nonatomic_tas8(volatile TAny* a, TInt8 t, TInt8 u, TInt8 v)
1.110 + {
1.111 + __TA(TInt8);
1.112 + }
1.113 +
1.114 +
1.115 +TUint16 __nonatomic_load16(const volatile TAny* a)
1.116 + {
1.117 + __LOAD(TUint16);
1.118 + }
1.119 +
1.120 +TUint16 __nonatomic_store16(volatile TAny* a, TUint16 v)
1.121 + {
1.122 + __STORE(TUint16);
1.123 + }
1.124 +
1.125 +TUint16 __nonatomic_swp16(volatile TAny* a, TUint16 v)
1.126 + {
1.127 + __SWP(TUint16);
1.128 + }
1.129 +
1.130 +TBool __nonatomic_cas16(volatile TAny* a, TUint16* q, TUint16 v)
1.131 + {
1.132 + __CAS(TUint16);
1.133 + }
1.134 +
1.135 +TUint16 __nonatomic_add16(volatile TAny* a, TUint16 v)
1.136 + {
1.137 + __ADD(TUint16);
1.138 + }
1.139 +
1.140 +TUint16 __nonatomic_and16(volatile TAny* a, TUint16 v)
1.141 + {
1.142 + __AND(TUint16);
1.143 + }
1.144 +
1.145 +TUint16 __nonatomic_ior16(volatile TAny* a, TUint16 v)
1.146 + {
1.147 + __IOR(TUint16);
1.148 + }
1.149 +
1.150 +TUint16 __nonatomic_xor16(volatile TAny* a, TUint16 v)
1.151 + {
1.152 + __XOR(TUint16);
1.153 + }
1.154 +
1.155 +TUint16 __nonatomic_axo16(volatile TAny* a, TUint16 u, TUint16 v)
1.156 + {
1.157 + __AXO(TUint16);
1.158 + }
1.159 +
1.160 +TUint16 __nonatomic_tau16(volatile TAny* a, TUint16 t, TUint16 u, TUint16 v)
1.161 + {
1.162 + __TA(TUint16);
1.163 + }
1.164 +
1.165 +TInt16 __nonatomic_tas16(volatile TAny* a, TInt16 t, TInt16 u, TInt16 v)
1.166 + {
1.167 + __TA(TInt16);
1.168 + }
1.169 +
1.170 +
1.171 +TUint32 __nonatomic_load32(const volatile TAny* a)
1.172 + {
1.173 + __LOAD(TUint32);
1.174 + }
1.175 +
1.176 +TUint32 __nonatomic_store32(volatile TAny* a, TUint32 v)
1.177 + {
1.178 + __STORE(TUint32);
1.179 + }
1.180 +
1.181 +TUint32 __nonatomic_swp32(volatile TAny* a, TUint32 v)
1.182 + {
1.183 + __SWP(TUint32);
1.184 + }
1.185 +
1.186 +TBool __nonatomic_cas32(volatile TAny* a, TUint32* q, TUint32 v)
1.187 + {
1.188 + __CAS(TUint32);
1.189 + }
1.190 +
1.191 +TUint32 __nonatomic_add32(volatile TAny* a, TUint32 v)
1.192 + {
1.193 + __ADD(TUint32);
1.194 + }
1.195 +
1.196 +TUint32 __nonatomic_and32(volatile TAny* a, TUint32 v)
1.197 + {
1.198 + __AND(TUint32);
1.199 + }
1.200 +
1.201 +TUint32 __nonatomic_ior32(volatile TAny* a, TUint32 v)
1.202 + {
1.203 + __IOR(TUint32);
1.204 + }
1.205 +
1.206 +TUint32 __nonatomic_xor32(volatile TAny* a, TUint32 v)
1.207 + {
1.208 + __XOR(TUint32);
1.209 + }
1.210 +
1.211 +TUint32 __nonatomic_axo32(volatile TAny* a, TUint32 u, TUint32 v)
1.212 + {
1.213 + __AXO(TUint32);
1.214 + }
1.215 +
1.216 +TUint32 __nonatomic_tau32(volatile TAny* a, TUint32 t, TUint32 u, TUint32 v)
1.217 + {
1.218 + __TA(TUint32);
1.219 + }
1.220 +
1.221 +TInt32 __nonatomic_tas32(volatile TAny* a, TInt32 t, TInt32 u, TInt32 v)
1.222 + {
1.223 + __TA(TInt32);
1.224 + }
1.225 +
1.226 +
1.227 +TUint64 __nonatomic_load64(const volatile TAny* a)
1.228 + {
1.229 + __LOAD(TUint64);
1.230 + }
1.231 +
1.232 +TUint64 __nonatomic_store64(volatile TAny* a, TUint64 v)
1.233 + {
1.234 + __STORE(TUint64);
1.235 + }
1.236 +
1.237 +TUint64 __nonatomic_swp64(volatile TAny* a, TUint64 v)
1.238 + {
1.239 + __SWP(TUint64);
1.240 + }
1.241 +
1.242 +TBool __nonatomic_cas64(volatile TAny* a, TUint64* q, TUint64 v)
1.243 + {
1.244 + __CAS(TUint64);
1.245 + }
1.246 +
1.247 +TUint64 __nonatomic_add64(volatile TAny* a, TUint64 v)
1.248 + {
1.249 + __ADD(TUint64);
1.250 + }
1.251 +
1.252 +TUint64 __nonatomic_and64(volatile TAny* a, TUint64 v)
1.253 + {
1.254 + __AND(TUint64);
1.255 + }
1.256 +
1.257 +TUint64 __nonatomic_ior64(volatile TAny* a, TUint64 v)
1.258 + {
1.259 + __IOR(TUint64);
1.260 + }
1.261 +
1.262 +TUint64 __nonatomic_xor64(volatile TAny* a, TUint64 v)
1.263 + {
1.264 + __XOR(TUint64);
1.265 + }
1.266 +
1.267 +TUint64 __nonatomic_axo64(volatile TAny* a, TUint64 u, TUint64 v)
1.268 + {
1.269 + __AXO(TUint64);
1.270 + }
1.271 +
1.272 +TUint64 __nonatomic_tau64(volatile TAny* a, TUint64 t, TUint64 u, TUint64 v)
1.273 + {
1.274 + __TA(TUint64);
1.275 + }
1.276 +
1.277 +TInt64 __nonatomic_tas64(volatile TAny* a, TInt64 t, TInt64 u, TInt64 v)
1.278 + {
1.279 + __TA(TInt64);
1.280 + }
1.281 +
1.282 +} // extern "C"
1.283 +
1.284 +
1.285 +#define DEBUGPRINTxyrc() \
1.286 + DEBUGPRINTVAR(x); \
1.287 + DEBUGPRINTVAR(y); \
1.288 + DEBUGPRINTVAR(r); \
1.289 + DEBUGPRINTVAR(c)
1.290 +
1.291 +template<class T> TInt DoLoadTest(TInt aIndex, TAny* aPtr, T aInitialValue)
1.292 + {
1.293 +#ifdef __EXTRA_DEBUG__
1.294 + DEBUGPRINT("DoLoadTest %d %08x", aIndex, aPtr);
1.295 +#endif
1.296 + typename TLoadFn<T>::F atomic = (typename TLoadFn<T>::F)AtomicFuncPtr[aIndex];
1.297 + typename TLoadFn<T>::F control = (typename TLoadFn<T>::F)ControlFuncPtr[aIndex];
1.298 + T& x = *(T*)aPtr;
1.299 + x = aInitialValue;
1.300 + T y = aInitialValue;
1.301 + T r = atomic(&x);
1.302 + T c = control(&y);
1.303 + if (r!=c || x!=y)
1.304 + {
1.305 + DEBUGPRINTxyrc();
1.306 + return __LINE__;
1.307 + }
1.308 + return 0;
1.309 + }
1.310 +
1.311 +template<class T> TInt DoRmw1Test(TInt aIndex, TAny* aPtr, T aInitialValue, T a1)
1.312 + {
1.313 +#ifdef __EXTRA_DEBUG__
1.314 + DEBUGPRINT("DoRmw1Test %d %08x", aIndex, aPtr);
1.315 +#endif
1.316 + typename TRmw1Fn<T>::F atomic = (typename TRmw1Fn<T>::F)AtomicFuncPtr[aIndex];
1.317 + typename TRmw1Fn<T>::F control = (typename TRmw1Fn<T>::F)ControlFuncPtr[aIndex];
1.318 + T& x = *(T*)aPtr;
1.319 + x = aInitialValue;
1.320 + T y = aInitialValue;
1.321 + T r = atomic(&x,a1);
1.322 + T c = control(&y,a1);
1.323 + if (r!=c || x!=y)
1.324 + {
1.325 + DEBUGPRINTxyrc();
1.326 + return __LINE__;
1.327 + }
1.328 + return 0;
1.329 + }
1.330 +
1.331 +template<class T> TInt DoRmw2Test(TInt aIndex, TAny* aPtr, T aInitialValue, T a1, T a2)
1.332 + {
1.333 +#ifdef __EXTRA_DEBUG__
1.334 + DEBUGPRINT("DoRmw2Test %d %08x", aIndex, aPtr);
1.335 +#endif
1.336 + typename TRmw2Fn<T>::F atomic = (typename TRmw2Fn<T>::F)AtomicFuncPtr[aIndex];
1.337 + typename TRmw2Fn<T>::F control = (typename TRmw2Fn<T>::F)ControlFuncPtr[aIndex];
1.338 + T& x = *(T*)aPtr;
1.339 + x = aInitialValue;
1.340 + T y = aInitialValue;
1.341 + T r = atomic(&x,a1,a2);
1.342 + T c = control(&y,a1,a2);
1.343 + if (r!=c || x!=y)
1.344 + {
1.345 + DEBUGPRINTxyrc();
1.346 + return __LINE__;
1.347 + }
1.348 + return 0;
1.349 + }
1.350 +
1.351 +template<class T> TInt DoRmw3Test(TInt aIndex, TAny* aPtr, T aInitialValue, T a1, T a2, T a3)
1.352 + {
1.353 +#ifdef __EXTRA_DEBUG__
1.354 + DEBUGPRINT("DoRmw3Test %d %08x", aIndex, aPtr);
1.355 +#endif
1.356 + typename TRmw3Fn<T>::F atomic = (typename TRmw3Fn<T>::F)AtomicFuncPtr[aIndex];
1.357 + typename TRmw3Fn<T>::F control = (typename TRmw3Fn<T>::F)ControlFuncPtr[aIndex];
1.358 + T& x = *(T*)aPtr;
1.359 + x = aInitialValue;
1.360 + T y = aInitialValue;
1.361 + T r = atomic(&x,a1,a2,a3);
1.362 + T c = control(&y,a1,a2,a3);
1.363 + if (r!=c || x!=y)
1.364 + {
1.365 + DEBUGPRINTxyrc();
1.366 + return __LINE__;
1.367 + }
1.368 + return 0;
1.369 + }
1.370 +
1.371 +template<class T> TInt DoCasTest(TInt aIndex, TAny* aPtr, T aInitialValue, T aExpectedValue, T aFinalValue)
1.372 + {
1.373 +#ifdef __EXTRA_DEBUG__
1.374 + DEBUGPRINT("DoCasTest %d %08x", aIndex, aPtr);
1.375 +#endif
1.376 + typename TCasFn<T>::F atomic = (typename TCasFn<T>::F)AtomicFuncPtr[aIndex];
1.377 + typename TCasFn<T>::F control = (typename TCasFn<T>::F)ControlFuncPtr[aIndex];
1.378 + T& x = *(T*)aPtr;
1.379 + x = aInitialValue;
1.380 + T ex = aExpectedValue;
1.381 + T y = aInitialValue;
1.382 + T ey = aExpectedValue;
1.383 + TBool r = atomic(&x,&ex,aFinalValue);
1.384 + TBool c = control(&y,&ey,aFinalValue);
1.385 + TInt line = 0;
1.386 + if (r && !c)
1.387 + line = __LINE__;
1.388 + else if (!r && c)
1.389 + line = __LINE__;
1.390 + else if (x!=y)
1.391 + line = __LINE__;
1.392 + else if (ex!=ey)
1.393 + line = __LINE__;
1.394 + else if (r && x!=aFinalValue)
1.395 + line = __LINE__;
1.396 + else if (!r && ex!=aInitialValue)
1.397 + line = __LINE__;
1.398 + if (line)
1.399 + {
1.400 + DEBUGPRINT("r=%d",r);
1.401 + DEBUGPRINTVAR(x);
1.402 + DEBUGPRINTVAR(ex);
1.403 + DEBUGPRINT("c=%d",c);
1.404 + DEBUGPRINTVAR(y);
1.405 + DEBUGPRINTVAR(ey);
1.406 + }
1.407 + return line;
1.408 + }
1.409 +
1.410 +
1.411 +
1.412 +TEnclosed::TEnclosed(TInt aSize)
1.413 + {
1.414 + iOffset = -1;
1.415 + iSize = aSize;
1.416 + iData = (TUint64*)((T_UintPtr(i_Data) + 7) &~ 7); // align up to next 8 byte boundary
1.417 + iBackup = iData + 8;
1.418 + }
1.419 +
1.420 +TAny* TEnclosed::Ptr()
1.421 + {
1.422 + return ((TUint8*)iData + iOffset);
1.423 + }
1.424 +
1.425 +TInt TEnclosed::Next()
1.426 + {
1.427 + const TInt KLimit[8] = {8, 16, 0, 32, 0, 0, 0, 32};
1.428 + if (iOffset<0)
1.429 + iOffset = 0;
1.430 + else
1.431 + {
1.432 + TInt r = Verify();
1.433 + if (r!=0)
1.434 + return r;
1.435 + iOffset += iSize;
1.436 + }
1.437 + if (iOffset >= KLimit[iSize-1])
1.438 + return KErrEof;
1.439 + Init();
1.440 + return KErrNone;
1.441 + }
1.442 +
1.443 +void TEnclosed::Init()
1.444 + {
1.445 + TUint32 x = iOffset+1;
1.446 + x |= (x<<8);
1.447 + x |= (x<<16);
1.448 + TUint32* d = (TUint32*)iData;
1.449 + TUint32* b = (TUint32*)iBackup;
1.450 + TInt i;
1.451 + for (i=0; i<16; ++i)
1.452 + {
1.453 + *d++ = x;
1.454 + *b++ = x;
1.455 + x = 69069*x + 41;
1.456 + }
1.457 + }
1.458 +
1.459 +TInt TEnclosed::Verify()
1.460 + {
1.461 + TUint8* d = (TUint8*)iData;
1.462 + const TUint8* b = (const TUint8*)iBackup;
1.463 + TInt i;
1.464 + for (i=0; i<iSize; ++i)
1.465 + d[iOffset+i] = b[iOffset+i];
1.466 + if (memcompare(b,64,d,64))
1.467 + {
1.468 + DEBUGPRINT("FAIL! iOffset=%02x, sizeof(T)=%1d", iOffset, iSize);
1.469 + for (i=0; i<64; ++i)
1.470 + {
1.471 + if (d[i]!=b[i])
1.472 + {
1.473 + DEBUGPRINT("d[%02x]=%02x b[%02x]=%02x", i, d[i], i, b[i]);
1.474 + }
1.475 + }
1.476 + return __LINE__;
1.477 + }
1.478 + return 0;
1.479 + }
1.480 +
1.481 +
1.482 +TInt TDGBase::Execute()
1.483 + {
1.484 + PFV af0 = AtomicFuncPtr[iIndex];
1.485 + PFV cf0 = ControlFuncPtr[iIndex];
1.486 + if (!af0 || !cf0)
1.487 + return __LINE__;
1.488 + TUint attr = FuncAttr[iIndex];
1.489 + TInt type = ATTR_TO_TYPE(attr);
1.490 + TInt size = ATTR_TO_SIZE(attr);
1.491 + TInt func = ATTR_TO_FUNC(attr);
1.492 + if (type==EFuncTypeInvalid)
1.493 + return __LINE__;
1.494 +#ifdef __EXTRA_DEBUG__
1.495 + TInt ord = ATTR_TO_ORD(attr);
1.496 + DEBUGPRINT("A=%08x T=%d O=%d S=%d F=%d", attr, type, ord, size, func);
1.497 +#endif
1.498 + TEnclosed enc(size);
1.499 + TInt res = 0;
1.500 + while ( (res = enc.Next()) == KErrNone )
1.501 + {
1.502 +#ifdef __EXTRA_DEBUG__
1.503 + DEBUGPRINT("Offset %02x", enc.Offset());
1.504 +#endif
1.505 + TAny* ptr = enc.Ptr();
1.506 + switch (type)
1.507 + {
1.508 + case EFuncTypeLoad:
1.509 + {
1.510 + switch (size)
1.511 + {
1.512 + case 1: res = DoLoadTest<TUint8>(iIndex, ptr, (TUint8)i0); break;
1.513 + case 2: res = DoLoadTest<TUint16>(iIndex, ptr, (TUint16)i0); break;
1.514 + case 4: res = DoLoadTest<TUint32>(iIndex, ptr, (TUint32)i0); break;
1.515 + case 8: res = DoLoadTest<TUint64>(iIndex, ptr, i0); break;
1.516 + default: res = __LINE__; break;
1.517 + }
1.518 + break;
1.519 + }
1.520 + case EFuncTypeRmw1:
1.521 + {
1.522 + switch (size)
1.523 + {
1.524 + case 1: res = DoRmw1Test<TUint8>(iIndex, ptr, (TUint8)i0, (TUint8)i1); break;
1.525 + case 2: res = DoRmw1Test<TUint16>(iIndex, ptr, (TUint16)i0, (TUint16)i1); break;
1.526 + case 4: res = DoRmw1Test<TUint32>(iIndex, ptr, (TUint32)i0, (TUint32)i1); break;
1.527 + case 8: res = DoRmw1Test<TUint64>(iIndex, ptr, i0, i1); break;
1.528 + default: res = __LINE__; break;
1.529 + }
1.530 + break;
1.531 + }
1.532 + case EFuncTypeRmw2:
1.533 + {
1.534 + switch (size)
1.535 + {
1.536 + case 1: res = DoRmw2Test<TUint8>(iIndex, ptr, (TUint8)i0, (TUint8)i1, (TUint8)i2); break;
1.537 + case 2: res = DoRmw2Test<TUint16>(iIndex, ptr, (TUint16)i0, (TUint16)i1, (TUint16)i2); break;
1.538 + case 4: res = DoRmw2Test<TUint32>(iIndex, ptr, (TUint32)i0, (TUint32)i1, (TUint32)i2); break;
1.539 + case 8: res = DoRmw2Test<TUint64>(iIndex, ptr, i0, i1, i2); break;
1.540 + default: res = __LINE__; break;
1.541 + }
1.542 + break;
1.543 + }
1.544 + case EFuncTypeRmw3:
1.545 + {
1.546 + if (func==EAtomicFuncTAU)
1.547 + {
1.548 + switch (size)
1.549 + {
1.550 + case 1: res = DoRmw3Test<TUint8>(iIndex, ptr, (TUint8)i0, (TUint8)i1, (TUint8)i2, (TUint8)i3); break;
1.551 + case 2: res = DoRmw3Test<TUint16>(iIndex, ptr, (TUint16)i0, (TUint16)i1, (TUint16)i2, (TUint16)i3); break;
1.552 + case 4: res = DoRmw3Test<TUint32>(iIndex, ptr, (TUint32)i0, (TUint32)i1, (TUint32)i2, (TUint32)i3); break;
1.553 + case 8: res = DoRmw3Test<TUint64>(iIndex, ptr, i0, i1, i2, i3); break;
1.554 + default: res = __LINE__; break;
1.555 + }
1.556 + }
1.557 + else if (func==EAtomicFuncTAS)
1.558 + {
1.559 + switch (size)
1.560 + {
1.561 + case 1: res = DoRmw3Test<TInt8>(iIndex, ptr, (TInt8)i0, (TInt8)i1, (TInt8)i2, (TInt8)i3); break;
1.562 + case 2: res = DoRmw3Test<TInt16>(iIndex, ptr, (TInt16)i0, (TInt16)i1, (TInt16)i2, (TInt16)i3); break;
1.563 + case 4: res = DoRmw3Test<TInt32>(iIndex, ptr, (TInt32)i0, (TInt32)i1, (TInt32)i2, (TInt32)i3); break;
1.564 + case 8: res = DoRmw3Test<TInt64>(iIndex, ptr, i0, i1, i2, i3); break;
1.565 + default: res = __LINE__; break;
1.566 + }
1.567 + }
1.568 + else
1.569 + res = __LINE__;
1.570 + break;
1.571 + }
1.572 + case EFuncTypeCas:
1.573 + {
1.574 + switch (size)
1.575 + {
1.576 + case 1: res = DoCasTest<TUint8>(iIndex, ptr, (TUint8)i0, (TUint8)i1, (TUint8)i2); break;
1.577 + case 2: res = DoCasTest<TUint16>(iIndex, ptr, (TUint16)i0, (TUint16)i1, (TUint16)i2); break;
1.578 + case 4: res = DoCasTest<TUint32>(iIndex, ptr, (TUint32)i0, (TUint32)i1, (TUint32)i2); break;
1.579 + case 8: res = DoCasTest<TUint64>(iIndex, ptr, i0, i1, i2); break;
1.580 + default: res = __LINE__; break;
1.581 + }
1.582 + break;
1.583 + }
1.584 + default:
1.585 + res = __LINE__;
1.586 + break;
1.587 + }
1.588 + if (res)
1.589 + return res;
1.590 + }
1.591 + if (res == KErrEof)
1.592 + res = 0;
1.593 + return res;
1.594 + }
1.595 +
1.596 +#ifndef __KERNEL_MODE__
1.597 +void TDGBase::Dump(const char* aTitle)
1.598 + {
1.599 + TPtrC8 fname8((const TText8*)FuncName[iIndex]);
1.600 + TBuf<64> fname;
1.601 + fname.Copy(fname8);
1.602 + DEBUGPRINT(aTitle);
1.603 + DEBUGPRINT("iIndex=%d (%S)", iIndex, &fname);
1.604 + DEBUGPRINT("i0 = %08x %08x", I64HIGH(i0), I64LOW(i0));
1.605 + DEBUGPRINT("i1 = %08x %08x", I64HIGH(i1), I64LOW(i1));
1.606 + DEBUGPRINT("i2 = %08x %08x", I64HIGH(i2), I64LOW(i2));
1.607 + DEBUGPRINT("i3 = %08x %08x", I64HIGH(i3), I64LOW(i3));
1.608 + }
1.609 +#endif
1.610 +
1.611 +template<class T> TInt DoSwap(TAny* aPtr, TPerThread* aT, TAtomicAction& aA, T*)
1.612 + {
1.613 + typename TRmw1Fn<T>::F atomic = (typename TRmw1Fn<T>::F)AtomicFuncPtr[aA.iIndex];
1.614 + T newv = (T)aA.i0;
1.615 + T orig = atomic(aPtr, newv);
1.616 + T xr = (T)(newv ^ orig);
1.617 + aT->iXor ^= xr;
1.618 + T diff = (T)(newv - orig);
1.619 + aT->iDiff += diff;
1.620 + return 0;
1.621 + }
1.622 +
1.623 +template<class T> TInt DoAdd(TAny* aPtr, TPerThread* aT, TAtomicAction& aA, T*)
1.624 + {
1.625 + typename TRmw1Fn<T>::F atomic = (typename TRmw1Fn<T>::F)AtomicFuncPtr[aA.iIndex];
1.626 + T arg = (T)aA.i0;
1.627 + T orig = atomic(aPtr, arg);
1.628 + T xr = (T)((arg+orig) ^ orig);
1.629 + aT->iXor ^= xr;
1.630 + aT->iDiff += arg;
1.631 + return 0;
1.632 + }
1.633 +
1.634 +template<class T> TInt DoXor(TAny* aPtr, TPerThread* aT, TAtomicAction& aA, T*)
1.635 + {
1.636 + typename TRmw1Fn<T>::F atomic = (typename TRmw1Fn<T>::F)AtomicFuncPtr[aA.iIndex];
1.637 + T arg = (T)aA.i0;
1.638 + T orig = atomic(aPtr, arg);
1.639 + T diff = (T)((arg^orig) - orig);
1.640 + aT->iDiff += diff;
1.641 + aT->iXor ^= arg;
1.642 + return 0;
1.643 + }
1.644 +
1.645 +template<class T> TInt DoAndOr(TAny* aPtr, TPerThread* aT, TAtomicAction& aA, T*)
1.646 + {
1.647 + typename TRmw1Fn<T>::F atomic_and = (typename TRmw1Fn<T>::F)AtomicFuncPtr[aA.iIndex];
1.648 + typename TRmw1Fn<T>::F atomic_or = (typename TRmw1Fn<T>::F)AtomicFuncPtr[aA.iIndex+4];
1.649 + T aarg = (T)aA.i0;
1.650 + T oarg = (T)aA.i1;
1.651 + T aorig = atomic_and(aPtr, aarg);
1.652 + T oorig = atomic_or(aPtr, oarg);
1.653 + T adiff = (T)((aorig & aarg) - aorig);
1.654 + T odiff = (T)((oorig | oarg) - oorig);
1.655 + aT->iDiff += adiff + odiff;
1.656 + T axor = (T)((aorig & aarg) ^ aorig);
1.657 + T oxor = (T)((oorig | oarg) ^ oorig);
1.658 + aT->iXor ^= axor ^ oxor;
1.659 + return 0;
1.660 + }
1.661 +
1.662 +template<class T> TInt DoAxo(TAny* aPtr, TPerThread* aT, TAtomicAction& aA, T*)
1.663 + {
1.664 + typename TRmw2Fn<T>::F atomic = (typename TRmw2Fn<T>::F)AtomicFuncPtr[aA.iIndex];
1.665 + T aarg = (T)aA.i0;
1.666 + T xarg = (T)aA.i1;
1.667 + T orig = atomic(aPtr, aarg, xarg);
1.668 + T newv = (T)((orig & aarg) ^ xarg);
1.669 + aT->iDiff += (newv - orig);
1.670 + aT->iXor ^= (newv ^ orig);
1.671 + return 0;
1.672 + }
1.673 +
1.674 +template<class T> TInt DoThAdd(TAny* aPtr, TPerThread* aT, TAtomicAction& aA, T*)
1.675 + {
1.676 + typename TRmw3Fn<T>::F atomic = (typename TRmw3Fn<T>::F)AtomicFuncPtr[aA.iIndex];
1.677 + T thr = (T)aA.i0;
1.678 + T arg1 = (T)aA.i1;
1.679 + T arg2 = (T)aA.i2;
1.680 + T orig = atomic(aPtr, thr, arg1, arg2);
1.681 + T newv = (T)((orig >= thr) ? (orig + arg1) : (orig + arg2));
1.682 + aT->iDiff += (orig >= thr) ? arg1 : arg2;
1.683 + aT->iXor ^= (newv ^ orig);
1.684 + return 0;
1.685 + }
1.686 +
1.687 +template<class T> TInt DoCas(TAny* aPtr, TPerThread* aT, TAtomicAction& aA, T*)
1.688 + {
1.689 + typename TCasFn<T>::F atomic = (typename TCasFn<T>::F)AtomicFuncPtr[aA.iIndex];
1.690 + T orig = *(const volatile T*)aPtr;
1.691 + T newv;
1.692 + TBool done = FALSE;
1.693 + TUint32 fails = 0xffffffffu;
1.694 + do {
1.695 + ++fails;
1.696 + newv = Transform<T>::F(orig);
1.697 + done = atomic(aPtr, &orig, newv);
1.698 + } while(!done);
1.699 + aT->iFailCount += fails;
1.700 + ++aT->iDiff;
1.701 + aT->iXor ^= (newv ^ orig);
1.702 + return 0;
1.703 + }
1.704 +
1.705 +volatile TUint Dummy;
1.706 +extern "C" TInt DoAtomicAction(TAny* aPtr, TPerThread* aT, TAtomicAction& aA)
1.707 + {
1.708 + TUint x = TUint(aT)*0x9E3779B9u;
1.709 + x = (x>>8)&15;
1.710 + while(x--)
1.711 + ++Dummy;
1.712 + TInt r = KErrNotSupported;
1.713 + TUint attr = FuncAttr[aA.iIndex];
1.714 + TUint func = ATTR_TO_FUNC(attr);
1.715 + TUint size = ATTR_TO_SIZE(attr);
1.716 + switch (size)
1.717 + {
1.718 + case 1:
1.719 + {
1.720 + TUint8 xx;
1.721 + TUint8* dummy = &xx;
1.722 + TInt8 yy;
1.723 + TInt8* sdummy = &yy;
1.724 + switch (func)
1.725 + {
1.726 + case EAtomicFuncSWP: r=DoSwap<TUint8>(aPtr, aT, aA, dummy); break;
1.727 + case EAtomicFuncADD: r=DoAdd<TUint8>(aPtr, aT, aA, dummy); break;
1.728 + case EAtomicFuncAND: r=DoAndOr<TUint8>(aPtr, aT, aA, dummy); break;
1.729 + case EAtomicFuncXOR: r=DoXor<TUint8>(aPtr, aT, aA, dummy); break;
1.730 + case EAtomicFuncAXO: r=DoAxo<TUint8>(aPtr, aT, aA, dummy); break;
1.731 + case EAtomicFuncTAU: r=DoThAdd<TUint8>(aPtr, aT, aA, dummy); break;
1.732 + case EAtomicFuncTAS: r=DoThAdd<TInt8>(aPtr, aT, aA, sdummy); break;
1.733 + case EAtomicFuncCAS: r=DoCas<TUint8>(aPtr, aT, aA, dummy); break;
1.734 + default: break;
1.735 + }
1.736 + break;
1.737 + }
1.738 + case 2:
1.739 + {
1.740 + TUint16 xx;
1.741 + TUint16* dummy = &xx;
1.742 + TInt16 yy;
1.743 + TInt16* sdummy = &yy;
1.744 + switch (func)
1.745 + {
1.746 + case EAtomicFuncSWP: r=DoSwap<TUint16>(aPtr, aT, aA, dummy); break;
1.747 + case EAtomicFuncADD: r=DoAdd<TUint16>(aPtr, aT, aA, dummy); break;
1.748 + case EAtomicFuncAND: r=DoAndOr<TUint16>(aPtr, aT, aA, dummy); break;
1.749 + case EAtomicFuncXOR: r=DoXor<TUint16>(aPtr, aT, aA, dummy); break;
1.750 + case EAtomicFuncAXO: r=DoAxo<TUint16>(aPtr, aT, aA, dummy); break;
1.751 + case EAtomicFuncTAU: r=DoThAdd<TUint16>(aPtr, aT, aA, dummy); break;
1.752 + case EAtomicFuncTAS: r=DoThAdd<TInt16>(aPtr, aT, aA, sdummy); break;
1.753 + case EAtomicFuncCAS: r=DoCas<TUint16>(aPtr, aT, aA, dummy); break;
1.754 + default: break;
1.755 + }
1.756 + break;
1.757 + }
1.758 + case 4:
1.759 + {
1.760 + TUint32 xx;
1.761 + TUint32* dummy = &xx;
1.762 + TInt32 yy;
1.763 + TInt32* sdummy = &yy;
1.764 + switch (func)
1.765 + {
1.766 + case EAtomicFuncSWP: r=DoSwap<TUint32>(aPtr, aT, aA, dummy); break;
1.767 + case EAtomicFuncADD: r=DoAdd<TUint32>(aPtr, aT, aA, dummy); break;
1.768 + case EAtomicFuncAND: r=DoAndOr<TUint32>(aPtr, aT, aA, dummy); break;
1.769 + case EAtomicFuncXOR: r=DoXor<TUint32>(aPtr, aT, aA, dummy); break;
1.770 + case EAtomicFuncAXO: r=DoAxo<TUint32>(aPtr, aT, aA, dummy); break;
1.771 + case EAtomicFuncTAU: r=DoThAdd<TUint32>(aPtr, aT, aA, dummy); break;
1.772 + case EAtomicFuncTAS: r=DoThAdd<TInt32>(aPtr, aT, aA, sdummy); break;
1.773 + case EAtomicFuncCAS: r=DoCas<TUint32>(aPtr, aT, aA, dummy); break;
1.774 + default: break;
1.775 + }
1.776 + break;
1.777 + }
1.778 + case 8:
1.779 + {
1.780 + TUint64A xx;
1.781 + TUint64* dummy = &xx;
1.782 + TInt64A yy;
1.783 + TInt64* sdummy = &yy;
1.784 + switch (func)
1.785 + {
1.786 + case EAtomicFuncSWP: r=DoSwap<TUint64>(aPtr, aT, aA, dummy); break;
1.787 + case EAtomicFuncADD: r=DoAdd<TUint64>(aPtr, aT, aA, dummy); break;
1.788 + case EAtomicFuncAND: r=DoAndOr<TUint64>(aPtr, aT, aA, dummy); break;
1.789 + case EAtomicFuncXOR: r=DoXor<TUint64>(aPtr, aT, aA, dummy); break;
1.790 + case EAtomicFuncAXO: r=DoAxo<TUint64>(aPtr, aT, aA, dummy); break;
1.791 + case EAtomicFuncTAU: r=DoThAdd<TUint64>(aPtr, aT, aA, dummy); break;
1.792 + case EAtomicFuncTAS: r=DoThAdd<TInt64>(aPtr, aT, aA, sdummy); break;
1.793 + case EAtomicFuncCAS: r=DoCas<TUint64>(aPtr, aT, aA, dummy); break;
1.794 + default: break;
1.795 + }
1.796 + break;
1.797 + }
1.798 + default:
1.799 + break;
1.800 + }
1.801 + ++aT->iCount;
1.802 + return r;
1.803 + }
1.804 +
1.805 +
1.806 +