os/kernelhwsrv/kerneltest/e32test/system/t_atomic_common.cpp
changeset 0 bde4ae8d615e
     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 +