?? atomicbase.h
字號:
#endif#define HXAtomicIncINT32(p) _HXAtomicIncRetUINT32((UINT32*)(p))#define HXAtomicDecINT32(p) _HXAtomicDecRetUINT32((UINT32*)(p))#define HXAtomicIncRetINT32(p) _HXAtomicIncRetUINT32((UINT32*)(p))#define HXAtomicDecRetINT32(p) _HXAtomicDecRetUINT32((UINT32*)(p))#define HXAtomicAddINT32(p,n) _HXAtomicAddRetUINT32((UINT32*)(p),(INT32)(n))#define HXAtomicSubINT32(p,n) _HXAtomicSubRetUINT32((UINT32*)(p),(INT32)(n))#define HXAtomicAddRetINT32(p,n) _HXAtomicAddRetUINT32((UINT32*)(p),(INT32)(n))#define HXAtomicSubRetINT32(p,n) _HXAtomicSubRetUINT32((UINT32*)(p),(INT32)(n))#define HXAtomicIncUINT32(p) _HXAtomicIncRetUINT32((p))#define HXAtomicDecUINT32(p) _HXAtomicDecRetUINT32((p))#define HXAtomicIncRetUINT32(p) _HXAtomicIncRetUINT32((p))#define HXAtomicDecRetUINT32(p) _HXAtomicDecRetUINT32((p))#define HXAtomicAddUINT32(p,n) _HXAtomicAddRetUINT32((p),(n))#define HXAtomicSubUINT32(p,n) _HXAtomicSubRetUINT32((p),(n))#define HXAtomicAddRetUINT32(p,n) _HXAtomicAddRetUINT32((p),(n))#define HXAtomicSubRetUINT32(p,n) _HXAtomicSubRetUINT32((p),(n))/*********************************************************************** * Tru64 (OSF1) / Alpha (Native compiler) * * Implementation Notes: * * The Alpha CPU provides instructions to load-lock a value, * modify it, and attempt to write it back. If the value has * been modified by someone else since the load-lock occurred, * the write will fail and you can check the status code to * know whether you need to retry or not. * */#elif defined (__alpha)#include <c_asm.h>/* Increment by 1 and return new value */inline INT32HXAtomicIncRetINT32(INT32* pNum){ return asm ( "10: ldl_l %t0, (%a0);" // Load-lock value into a register " addl %t0, 1, %t0;" // Increment value " or %t0, %zero, %v0;" // set new value for return. " stl_c %t0, (%a0);" // Save new value into *pNum " beq %t0, 10b;" // Retry if sequence failed , pNum);}/* Decrement by 1 and return new value */inline INT32HXAtomicDecRetINT32(INT32* pNum){ return asm ( "10: ldl_l %t0, (%a0);" // Load-lock value into a register " subl %t0, 1, %t0;" // Decrement value " or %t0, %zero, %v0;" // set new value for return. " stl_c %t0, (%a0);" // Save new value into *pNum " beq %t0, 10b;" // Retry if sequence failed , pNum);}/* Add n and return new value */inline INT32HXAtomicAddRetINT32(INT32* pNum, INT32 n){ return asm ( "10: ldl_l %t0, (%a0);" // Load-lock value into a register " addl %t0, %a1, %t0;" // Add n to value " or %t0, %zero, %v0;" // set new value for return. " stl_c %t0, (%a0);" // Save new value into *pNum " beq %t0, 10b;" // Retry if sequence failed , pNum, n);}/* Subtract n and return new value */inline INT32HXAtomicSubRetINT32(INT32* pNum, INT32 n){ return asm ( "10: ldl_l %t0, (%a0);" // Load-lock value into a register " subl %t0, %a1, %t0;" // Subtract n from value " or %t0, %zero, %v0;" // set new value for return. " stl_c %t0, (%a0);" // Save new value into *pNum " beq %t0, 10b;" // Retry if sequence failed , pNum, n);}/* Increment by 1 and return new value */inline UINT32HXAtomicIncRetUINT32(UINT32* pNum){ return asm ( "10: ldl_l %t0, (%a0);" // Load-lock value into a register " addl %t0, 1, %t0;" // Increment value " or %t0, %zero, %v0;" // set new value for return. " stl_c %t0, (%a0);" // Save new value into *pNum " beq %t0, 10b;" // Retry if sequence failed , pNum);}/* Decrement by 1 and return new value */inline UINT32HXAtomicDecRetUINT32(UINT32* pNum){ return asm ( "10: ldl_l %t0, (%a0);" // Load-lock value into a register " subl %t0, 1, %t0;" // Decrement value " or %t0, %zero, %v0;" // set new value for return. " stl_c %t0, (%a0);" // Save new value into *pNum " beq %t0, 10b;" // Retry if sequence failed , pNum);}/* Add n and return new value */inline UINT32HXAtomicAddRetUINT32(UINT32* pNum, UINT32 n){ return asm ( "10: ldl_l %t0, (%a0);" // Load-lock value into a register " addl %t0, %a1, %t0;" // Add n to value " or %t0, %zero, %v0;" // set new value for return. " stl_c %t0, (%a0);" // Save new value into *pNum " beq %t0, 10b;" // Retry if sequence failed , pNum, n);}/* Subtract n and return new value */inline UINT32HXAtomicSubRetUINT32(UINT32* pNum, UINT32 n){ return asm ( "10: ldl_l %t0, (%a0);" // Load-lock value into a register " subl %t0, %a1, %t0;" // Subtract n from value " or %t0, %zero, %v0;" // set new value for return. " stl_c %t0, (%a0);" // Save new value into *pNum " beq %t0, 10b;" // Retry if sequence failed , pNum, n);}#define HXAtomicIncINT32(p) HXAtomicIncRetINT32((p))#define HXAtomicDecINT32(p) HXAtomicDecRetINT32((p))#define HXAtomicAddINT32(p,n) HXAtomicAddRetINT32((p),(n))#define HXAtomicSubINT32(p,n) HXAtomicSubRetINT32((p),(n))#define HXAtomicIncUINT32(p) HXAtomicIncRetUINT32((p))#define HXAtomicDecUINT32(p) HXAtomicDecRetUINT32((p))#define HXAtomicAddUINT32(p,n) HXAtomicAddRetUINT32((p),(n))#define HXAtomicSubUINT32(p,n) HXAtomicSubRetUINT32((p),(n))/*********************************************************************** * AIX / PowerPC (Native compiler) * * Implementation Notes: * * XXXDC: The xlc compiler is able to do inline asm for C but when I do * it for C++ it crashes, so for now I have resorted to putting * the asm in a separate assembler routine. The way you inline with * xlc/xlC is difficult to use, requiring the use of "#pragma mc_func". */#elif defined (_AIX)//defined in common/util/platform/aix/atomicops.s#if defined(__cplusplus)extern "C" {#endif INT32 _HXAtomicAddRetINT32 (INT32* pNum, INT32 lNum); INT32 _HXAtomicSubRetINT32 (INT32* pNum, INT32 lNum); UINT32 _HXAtomicAddRetUINT32 (UINT32* pNum, UINT32 ulNum); UINT32 _HXAtomicSubRetUINT32 (UINT32* pNum, UINT32 ulNum);#if defined(__cplusplus)}#endif#define HXAtomicIncINT32(p) _HXAtomicAddRetINT32((p),(INT32)1)#define HXAtomicDecINT32(p) _HXAtomicSubRetINT32((p),(INT32)1)#define HXAtomicIncRetINT32(p) _HXAtomicAddRetINT32((p),(INT32)1)#define HXAtomicDecRetINT32(p) _HXAtomicSubRetINT32((p),(INT32)1)#define HXAtomicAddINT32(p,n) _HXAtomicAddRetINT32((p),(n))#define HXAtomicSubINT32(p,n) _HXAtomicSubRetINT32((p),(n))#define HXAtomicAddRetINT32(p,n) _HXAtomicAddRetINT32((p),(n))#define HXAtomicSubRetINT32(p,n) _HXAtomicSubRetINT32((p),(n))#define HXAtomicIncUINT32(p) _HXAtomicAddRetUINT32((p),(UINT32)1)#define HXAtomicDecUINT32(p) _HXAtomicSubRetUINT32((p),(UINT32)1)#define HXAtomicIncRetUINT32(p) _HXAtomicAddRetUINT32((p),(UINT32)1)#define HXAtomicDecRetUINT32(p) _HXAtomicSubRetUINT32((p),(UINT32)1)#define HXAtomicAddUINT32(p,n) _HXAtomicAddRetUINT32((p),(n))#define HXAtomicSubUINT32(p,n) _HXAtomicSubRetUINT32((p),(n))#define HXAtomicAddRetUINT32(p,n) _HXAtomicAddRetUINT32((p),(n))#define HXAtomicSubRetUINT32(p,n) _HXAtomicSubRetUINT32((p),(n))/*********************************************************************** * MAC / PowerPC (CW) * * Implementation Notes: * * This will need to be rewritten, probably, once we move away from CW to PB. * * Note: This is an imcompletely-defined platform, be aware that * not all standard HXAtomic operators are defined! * */#elif defined(_MACINTOSH) && defined(__MWERKS__)inline UINT32HXAtomicIncRetUINT32(register UINT32* pNum){ register UINT32 zeroOffset = 0; register UINT32 temp; asm { again: lwarx temp, zeroOffset, pNum addi temp, temp, 1 stwcx. temp, zeroOffset, pNum bne- again } return temp;}inline UINT32HXAtomicDecRetUINT32(register UINT32* pNum){ register UINT32 zeroOffset = 0; register UINT32 temp; asm { again: lwarx temp, zeroOffset, pNum subi temp, temp, 1 stwcx. temp, zeroOffset, pNum bne- again } return temp;}/*********************************************************************** * MAC - PowerPC (PB or XCode) / Linux - PowerPC * * Implementation Notes: * * Use PowerPC load exclusive and store exclusive instructions * */#elif defined(_MAC_UNIX) || (defined(_LINUX) && defined(__powerpc__))// could also probably be defined(__GNUC__) && defined(__powerpc)static inline UINT32HXAtomicIncRetUINT32(UINT32* pNum){ volatile UINT32 result; __asm__ __volatile__ ("1: lwarx %0, %3, %2;\n"" addi %0, %0, 1;\n"" stwcx. %0, %3, %2;\n"" bne- 1b;" : "=b" (result) : "0" (result), "b" (pNum), "b" (0x0) : "cc", "memory" ); return result;}static inline UINT32HXAtomicDecRetUINT32(UINT32* pNum){ volatile UINT32 result; __asm__ __volatile__ ("1: lwarx %0, %3, %2;\n"" subi %0, %0, 1;\n"" stwcx. %0, %3, %2;\n"" bne- 1b;" : "=b" (result) : "0" (result), "b" (pNum), "b" (0x0) : "cc", "memory" ); return result;}static inline UINT32HXAtomicAddRetUINT32(UINT32* pNum, UINT32 ulNum){ volatile UINT32 result; __asm__ __volatile__ ("1: lwarx %0, %3, %2;\n"" add %0, %0, %4;\n"" stwcx. %0, %3, %2;\n"" bne- 1b;" : "=b" (result) : "0" (result), "b" (pNum), "b" (0x0), "b" (ulNum) : "cc", "memory" ); return result;}static inline UINT32HXAtomicSubRetUINT32(UINT32* pNum, UINT32 ulNum){ volatile UINT32 result; __asm__ __volatile__ ("1: lwarx %0, %3, %2;\n"" sub %0, %0, %4;\n"" stwcx. %0, %3, %2;\n"" bne- 1b;" : "=b" (result) : "0" (result), "b" (pNum), "b" (0x0), "b" (ulNum) : "cc", "memory" ); return result;}// the rest of these atomic operations can be implemented in terms of the four above.static inline void HXAtomicIncINT32(INT32* p) { (void)HXAtomicIncRetUINT32((UINT32*)p); }static inline void HXAtomicDecINT32(INT32* p) { (void)HXAtomicDecRetUINT32((UINT32*)p); }static inline void HXAtomicAddINT32(INT32* p, INT32 n) { (void)HXAtomicAddRetUINT32((UINT32*)p, (UINT32)n); }static inline void HXAtomicSubINT32(INT32* p, INT32 n) { (void)HXAtomicSubRetUINT32((UINT32*)p, (UINT32)n); }static inline INT32 HXAtomicIncRetINT32(INT32* p) { return (INT32)HXAtomicIncRetUINT32((UINT32*)p); }static inline INT32 HXAtomicDecRetINT32(INT32* p) { return (INT32)HXAtomicDecRetUINT32((UINT32*)p); }static inline INT32 HXAtomicAddRetINT32(INT32* p, INT32 n) { return (INT32)HXAtomicAddRetUINT32((UINT32*)p, (UINT32)n); }static inline INT32 HXAtomicSubRetINT32(INT32* p, INT32 n) { return (INT32)HXAtomicSubRetUINT32((UINT32*)p, (UINT32)n); }static inline void HXAtomicIncUINT32(UINT32* p) { (void)HXAtomicIncRetUINT32(p); }static inline void HXAtomicDecUINT32(UINT32* p) { (void)HXAtomicDecRetUINT32(p); }static inline void HXAtomicAddUINT32(UINT32* p, UINT32 n) { (void)HXAtomicAddRetUINT32(p, n); }static inline void HXAtomicSubUINT32(UINT32* p, UINT32 n) { (void)HXAtomicSubRetUINT32(p, n); }/*********************************************************************** * Generic * * Implementation Notes: * * This should work on any platform with a HXMutex-style mutex. * It allocates a pool of mutexes and hashes the int pointers * to one of the mutexes. Since the mutexes are held for * such a short time, only long enough to increment an int, * collisions should be extremely rare and this should work fine, * although it is probably less fast than the extra-high-performance * atomic operators provided above. You need to link in atomic.cpp * to get HXAtomic::m_pLocks defined. * * Basic design of the mutex-based lock-pool implementation: * At startup, allocate an array of N mutexes (where N is a power of 2). * When a method is called, hash the int pointer to one of the locks. * Lock this mutex. * Modify the value. * Unlock this mutex. * * * Platform-specific notes: * Any platforms that use this should be documented here! * Why are you using the generic operators for this platform? * * HP-UX / HP-PA: * This is used on the HP-PA processor since it doesn't provide the * necessary assembler operators to implement proper atomic updates * of ints. HP's mutex primitive seems pretty fast however, resulting * in a workable solution. * * OpenBSD: * The standard assembler on x86 can't handle the gcc/asm operators * defined above, so we're using the lock-pool approach for now. * This approach also makes it possible to support non-x86 OpenBSD * builds more easily (someday). * */#elif defined(_HPUX) || defined(_OPENBSD)#if defined(__cplusplus)#include "microsleep.h"
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -