Update contrib.
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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // e32test\system\t_atomic.h
18 #include <e32atomics.h>
21 #pragma warning( disable : 4244 ) /* conversion to shorter type - possible loss of data */
24 const TInt KMaxThreads = 8;
26 #ifdef __KERNEL_MODE__
27 #include <kernel/kernel.h>
29 #define DEBUGPRINT Kern::Printf
31 extern void UPrintf(const char*, ...);
33 #define DEBUGPRINT UPrintf
36 #undef __INT64_ALIGNED__
37 #if (defined(__GNUC__) && (__GNUC__ >= 3)) || defined(__EABI__)
38 #define __INT64_ALIGNED__
41 #ifdef __INT64_ALIGNED__
42 typedef TUint64 TUint64A;
43 typedef TInt64 TInt64A;
49 inline const TUint64* operator&() const
50 { return ((const TUint64*)((T_UintPtr(this)+7)&~7)); }
51 inline TUint64* operator&()
52 { return ((TUint64*)((T_UintPtr(this)+7)&~7)); }
60 inline const TInt64* operator&() const
61 { return ((const TInt64*)((T_UintPtr(this)+7)&~7)); }
62 inline TInt64* operator&()
63 { return ((TInt64*)((T_UintPtr(this)+7)&~7)); }
73 void Dump(const char*);
84 TUint64 i0; // first parameter to operation
85 TUint64 i1; // second parameter to operation
86 TUint64 i2; // third parameter to operation
87 TInt iIndex; // index of atomic function
88 TInt iThread; // thread identifier
93 TUint64 iDiff; // accumulated difference
94 TUint64 iXor; // accumulated XOR
95 TUint64 iFailCount; // failure count for CAS operations
96 TUint64 iCount; // iteration count
99 extern "C" TInt DoAtomicAction(TAny* aPtr, TPerThread* aT, TAtomicAction& aA);
135 #define FUNCS_PER_SIZE (TUint(EAtomicFuncN)*4)
136 #define TOTAL_FUNCS (FUNCS_PER_SIZE*4)
137 #define INDEXES_PER_SIZE (16*4)
138 #define TOTAL_INDEXES (INDEXES_PER_SIZE*4)
140 #define FUNCATTR(func,size,ord,type) ((TUint(func)<<24)|(TUint(size)<<16)|(TUint(ord)<<8)|(TUint(type)))
141 #define ATTR_TO_TYPE(attr) ((attr)&0xff)
142 #define ATTR_TO_ORD(attr) (((attr)>>8)&0xff)
143 #define ATTR_TO_SIZE(attr) (((attr)>>16)&0xff)
144 #define ATTR_TO_FUNC(attr) (((attr)>>24)&0xff)
145 #define FUNCATTR2(func,size,type) \
146 FUNCATTR(func,size,EOrderRelaxed,type), FUNCATTR(func,size,EOrderAcquire,type), FUNCATTR(func,size,EOrderRelease,type), FUNCATTR(func,size,EOrderOrdered,type)
147 #define FUNCATTR2A(func,size,type) \
148 0, FUNCATTR(func,size,EOrderAcquire,type), 0, 0
149 #define FUNCATTR2B(func,size,type) \
150 0, 0, FUNCATTR(func,size,EOrderRelease,type), FUNCATTR(func,size,EOrderOrdered,type)
151 #define FUNCATTR3(size) \
152 FUNCATTR2A(EAtomicFuncLOAD,size,EFuncTypeLoad), \
153 FUNCATTR2B(EAtomicFuncSTORE,size,EFuncTypeRmw1), \
154 FUNCATTR2(EAtomicFuncSWP,size,EFuncTypeRmw1), \
155 FUNCATTR2(EAtomicFuncADD,size,EFuncTypeRmw1), \
156 FUNCATTR2(EAtomicFuncAND,size,EFuncTypeRmw1), \
157 FUNCATTR2(EAtomicFuncIOR,size,EFuncTypeRmw1), \
158 FUNCATTR2(EAtomicFuncXOR,size,EFuncTypeRmw1), \
159 FUNCATTR2(EAtomicFuncAXO,size,EFuncTypeRmw2), \
160 FUNCATTR2(EAtomicFuncTAU,size,EFuncTypeRmw3), \
161 FUNCATTR2(EAtomicFuncTAS,size,EFuncTypeRmw3), \
162 FUNCATTR2(EAtomicFuncCAS,size,EFuncTypeCas), \
170 #define __DO_STRINGIFY__(x) #x
171 #define __STRINGIFY__(x) __DO_STRINGIFY__(x)
172 #define __concat3__(a,b,c) a##b##c
173 #define __concat5__(a,b,c,d,e) a##b##c##d##e
174 #define FUNCNAME(func,size,ord) __STRINGIFY__(__concat3__(func,size,ord))
175 #define ATOMICFUNC(func,size,ord) __concat5__(__e32_atomic_,func,_,ord,size)
176 #define CONTROLFUNC(func,size,ord) __concat3__(__nonatomic_,func,size)
177 #define FUNCNAME2(func,size) FUNCNAME(func,size,rlx), FUNCNAME(func,size,acq), FUNCNAME(func,size,rel), FUNCNAME(func,size,ord)
178 #define FUNCNAME3(size) \
179 FUNCNAME2(load,size), \
180 FUNCNAME2(store,size), \
181 FUNCNAME2(swp,size), \
182 FUNCNAME2(add,size), \
183 FUNCNAME2(and,size), \
184 FUNCNAME2(ior,size), \
185 FUNCNAME2(xor,size), \
186 FUNCNAME2(axo,size), \
187 FUNCNAME2(tau,size), \
188 FUNCNAME2(tas,size), \
189 FUNCNAME2(cas,size), \
197 #define ATOMICFUNC2(func,size) (PFV)&ATOMICFUNC(func,size,rlx), (PFV)&ATOMICFUNC(func,size,acq), (PFV)&ATOMICFUNC(func,size,rel), (PFV)&ATOMICFUNC(func,size,ord)
198 #define ATOMICFUNC2A(func,size) 0, (PFV)&ATOMICFUNC(func,size,acq), 0, 0
199 #define ATOMICFUNC2B(func,size) 0, 0, (PFV)&ATOMICFUNC(func,size,rel), (PFV)&ATOMICFUNC(func,size,ord)
200 #define ATOMICFUNC3(size) \
201 ATOMICFUNC2A(load,size), \
202 ATOMICFUNC2B(store,size), \
203 ATOMICFUNC2(swp,size), \
204 ATOMICFUNC2(add,size), \
205 ATOMICFUNC2(and,size), \
206 ATOMICFUNC2(ior,size), \
207 ATOMICFUNC2(xor,size), \
208 ATOMICFUNC2(axo,size), \
209 ATOMICFUNC2(tau,size), \
210 ATOMICFUNC2(tas,size), \
211 ATOMICFUNC2(cas,size), \
219 #define CONTROLFUNC2(func,size) (PFV)&CONTROLFUNC(func,size,rlx), (PFV)&CONTROLFUNC(func,size,acq), (PFV)&CONTROLFUNC(func,size,rel), (PFV)&CONTROLFUNC(func,size,ord)
220 #define CONTROLFUNC2A(func,size) 0, (PFV)&CONTROLFUNC(func,size,acq), 0, 0
221 #define CONTROLFUNC2B(func,size) 0, 0, (PFV)&CONTROLFUNC(func,size,rel), (PFV)&CONTROLFUNC(func,size,ord)
222 #define CONTROLFUNC3(size) \
223 CONTROLFUNC2A(load,size), \
224 CONTROLFUNC2B(store,size), \
225 CONTROLFUNC2(swp,size), \
226 CONTROLFUNC2(add,size), \
227 CONTROLFUNC2(and,size), \
228 CONTROLFUNC2(ior,size), \
229 CONTROLFUNC2(xor,size), \
230 CONTROLFUNC2(axo,size), \
231 CONTROLFUNC2(tau,size), \
232 CONTROLFUNC2(tas,size), \
233 CONTROLFUNC2(cas,size), \
241 #ifdef __INCLUDE_FUNC_NAMES__
242 extern "C" const char* FuncName[] =
251 typedef void (*PFV)();
253 #ifdef __INCLUDE_ATOMIC_FUNCTIONS__
254 extern "C" const PFV AtomicFuncPtr[] =
263 #ifdef __INCLUDE_CONTROL_FUNCTIONS__
266 // Simulated versions of atomic functions without the atomicity
267 extern TUint8 __nonatomic_load8(const volatile TAny* a);
268 extern TUint8 __nonatomic_store8(volatile TAny* a, TUint8 v);
269 extern TUint8 __nonatomic_swp8(volatile TAny* a, TUint8 v);
270 extern TBool __nonatomic_cas8(volatile TAny* a, TUint8* q, TUint8 v);
271 extern TUint8 __nonatomic_add8(volatile TAny* a, TUint8 v);
272 extern TUint8 __nonatomic_and8(volatile TAny* a, TUint8 v);
273 extern TUint8 __nonatomic_ior8(volatile TAny* a, TUint8 v);
274 extern TUint8 __nonatomic_xor8(volatile TAny* a, TUint8 v);
275 extern TUint8 __nonatomic_axo8(volatile TAny* a, TUint8 u, TUint8 v);
276 extern TUint8 __nonatomic_tau8(volatile TAny* a, TUint8 t, TUint8 u, TUint8 v);
277 extern TInt8 __nonatomic_tas8(volatile TAny* a, TInt8 t, TInt8 u, TInt8 v);
279 extern TUint16 __nonatomic_load16(const volatile TAny* a);
280 extern TUint16 __nonatomic_store16(volatile TAny* a, TUint16 v);
281 extern TUint16 __nonatomic_swp16(volatile TAny* a, TUint16 v);
282 extern TBool __nonatomic_cas16(volatile TAny* a, TUint16* q, TUint16 v);
283 extern TUint16 __nonatomic_add16(volatile TAny* a, TUint16 v);
284 extern TUint16 __nonatomic_and16(volatile TAny* a, TUint16 v);
285 extern TUint16 __nonatomic_ior16(volatile TAny* a, TUint16 v);
286 extern TUint16 __nonatomic_xor16(volatile TAny* a, TUint16 v);
287 extern TUint16 __nonatomic_axo16(volatile TAny* a, TUint16 u, TUint16 v);
288 extern TUint16 __nonatomic_tau16(volatile TAny* a, TUint16 t, TUint16 u, TUint16 v);
289 extern TInt16 __nonatomic_tas16(volatile TAny* a, TInt16 t, TInt16 u, TInt16 v);
291 extern TUint32 __nonatomic_load32(const volatile TAny* a);
292 extern TUint32 __nonatomic_store32(volatile TAny* a, TUint32 v);
293 extern TUint32 __nonatomic_swp32(volatile TAny* a, TUint32 v);
294 extern TBool __nonatomic_cas32(volatile TAny* a, TUint32* q, TUint32 v);
295 extern TUint32 __nonatomic_add32(volatile TAny* a, TUint32 v);
296 extern TUint32 __nonatomic_and32(volatile TAny* a, TUint32 v);
297 extern TUint32 __nonatomic_ior32(volatile TAny* a, TUint32 v);
298 extern TUint32 __nonatomic_xor32(volatile TAny* a, TUint32 v);
299 extern TUint32 __nonatomic_axo32(volatile TAny* a, TUint32 u, TUint32 v);
300 extern TUint32 __nonatomic_tau32(volatile TAny* a, TUint32 t, TUint32 u, TUint32 v);
301 extern TInt32 __nonatomic_tas32(volatile TAny* a, TInt32 t, TInt32 u, TInt32 v);
303 extern TUint64 __nonatomic_load64(const volatile TAny* a);
304 extern TUint64 __nonatomic_store64(volatile TAny* a, TUint64 v);
305 extern TUint64 __nonatomic_swp64(volatile TAny* a, TUint64 v);
306 extern TBool __nonatomic_cas64(volatile TAny* a, TUint64* q, TUint64 v);
307 extern TUint64 __nonatomic_add64(volatile TAny* a, TUint64 v);
308 extern TUint64 __nonatomic_and64(volatile TAny* a, TUint64 v);
309 extern TUint64 __nonatomic_ior64(volatile TAny* a, TUint64 v);
310 extern TUint64 __nonatomic_xor64(volatile TAny* a, TUint64 v);
311 extern TUint64 __nonatomic_axo64(volatile TAny* a, TUint64 u, TUint64 v);
312 extern TUint64 __nonatomic_tau64(volatile TAny* a, TUint64 t, TUint64 u, TUint64 v);
313 extern TInt64 __nonatomic_tas64(volatile TAny* a, TInt64 t, TInt64 u, TInt64 v);
318 extern "C" const PFV ControlFuncPtr[] =
327 #ifdef __INCLUDE_FUNCTION_ATTRIBUTES__
328 extern "C" const TUint FuncAttr[] =
338 struct TLoadFn // load
340 typedef T (*F)(const volatile TAny*);
344 struct TRmw1Fn // store, swp, add, and, ior, xor
346 typedef T (*F)(volatile TAny*, T);
350 struct TRmw2Fn // axo
352 typedef T (*F)(volatile TAny*, T, T);
356 struct TRmw3Fn // tau, tas
358 typedef T (*F)(volatile TAny*, T, T, T);
364 typedef TBool (*F)(volatile TAny*, T*, T);
370 TEnclosed(TInt aSize);
375 TInt Offset() const {return iOffset;}
390 static T F(T aOrig); // return Ax+B mod M (M=2^n, n=number of bits in T)
391 static T Pow(T aBase, TUint64 aExp); // return aBase^aExp mod M
392 static T PowerSum(T aBase, TUint64 aExp); // return 1 + T + T^2 + ... + T^(aExp-1) mod M
393 static T F_iter(T aOrig, TUint64 aCount); // return result of applying F iterated aCount times to aOrig
396 TEMPLATE_SPECIALIZATION inline TUint8 Transform<TUint8>::A()
398 TEMPLATE_SPECIALIZATION inline TUint8 Transform<TUint8>::B()
401 TEMPLATE_SPECIALIZATION inline TUint16 Transform<TUint16>::A()
403 TEMPLATE_SPECIALIZATION inline TUint16 Transform<TUint16>::B()
406 TEMPLATE_SPECIALIZATION inline TUint32 Transform<TUint32>::A()
408 TEMPLATE_SPECIALIZATION inline TUint32 Transform<TUint32>::B()
411 TEMPLATE_SPECIALIZATION inline TUint64 Transform<TUint64>::A()
412 { return UI64LIT(2862933555777941757); }
413 TEMPLATE_SPECIALIZATION inline TUint64 Transform<TUint64>::B()
414 { return UI64LIT(104917093); }
417 T Transform<T>::F(T aOrig)
419 return (T)(aOrig * Transform<T>::A() + Transform<T>::B());
423 T Transform<T>::Pow(T aBase, TUint64 aExp)
430 result *= multiplier;
433 multiplier *= multiplier;
439 T Transform<T>::PowerSum(T aBase, TUint64 aExp)
448 result *= multiplier;
454 inter *= (multiplier + 1);
455 multiplier *= multiplier;
462 T Transform<T>::F_iter(T aOrig, TUint64 aCount)
464 return (T)(Pow(A(),aCount)*aOrig + PowerSum(A(),aCount)*B());
470 _LIT(KAtomicTestLddName,"D_ATOMIC");
472 class RTestAtomic : public RBusLogicalChannel
480 ESetCurrentThreadTimeslice=3,
482 EGetKernelMemoryAddress=5,
486 #ifndef __KERNEL_MODE__
489 { return DoCreate(KAtomicTestLddName,TVersion(),KNullUnit,NULL,NULL); }
491 inline TInt TDGExecuteK(TDGBase& a)
492 { return DoControl(ETDGExecuteK, &a); }
493 inline TInt Initialise(TUint64 aValue)
494 { return DoControl(EInitialise, &aValue); }
495 inline TUint64 Retrieve()
496 { TUint64 x; DoControl(ERetrieve, &x); return x; }
497 inline TInt SetCurrentThreadTimeslice(TInt aTimeslice)
498 { return DoControl(ESetCurrentThreadTimeslice, (TAny*)aTimeslice); }
499 inline TInt SwitchExecTables(TInt aThread)
500 { return DoControl(ESwitchExecTables, (TAny*)aThread); }
501 inline TAny* KernelMemoryAddress()
502 { return (TAny*)DoControl(EGetKernelMemoryAddress); }
504 static TInt GetThreadInfo(TPerThread& aInfo);
505 static TInt SetThreadInfo(const TPerThread& aInfo);
506 static TInt AtomicAction(TAtomicAction& aAction);
507 static TInt RestoreExecTable();