⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 atomicbase.h

📁 著名的 helix realplayer 基于手机 symbian 系统的 播放器全套源代码
💻 H
📖 第 1 页 / 共 4 页
字号:
#include <c_asm.h>

/* Increment by 1 and return new value */
inline INT32
HXAtomicIncRetINT32(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 INT32
HXAtomicDecRetINT32(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 INT32
HXAtomicAddRetINT32(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 INT32
HXAtomicSubRetINT32(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 UINT32
HXAtomicIncRetUINT32(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 UINT32
HXAtomicDecRetUINT32(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 UINT32
HXAtomicAddRetUINT32(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 UINT32
HXAtomicSubRetUINT32(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 seperate 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 UINT32
HXAtomicIncRetUINT32(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 UINT32
HXAtomicDecRetUINT32(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)
 *
 * Implementation Notes:
 *
 * Use the atomic operations exposed by DriverSynchronization.h
 *
 * Note: This is an imcompletely-defined platform, be aware that
 * not all standard HXAtomic operators are defined!
 *
 */
#elif defined(_MACINTOSH) || defined(_MAC_UNIX)

inline UINT32
HXAtomicIncRetUINT32(UINT32* pNum)
{
    return (UINT32)(IncrementAtomic((SInt32*)pNum) + 1);
}

inline UINT32
HXAtomicDecRetUINT32(UINT32* pNum)
{
    return (UINT32)(DecrementAtomic((SInt32*)pNum) - 1);
}

/***********************************************************************
 * Linux / PowerPC
 *
 * Implementation Notes:
 *
 * Use PowerPC load exclusive and store exclusive instructions
 *
 */
#elif defined(_LINUX) && defined(__powerpc__)

inline UINT32
HXAtomicIncRetUINT32(UINT32* pNum)
{
    volatile UINT32 result;

	__asm__ __volatile__ (
"1:      lwarx  %0, 0, %2;\n"
"        addi   %0, %0, 1;\n"
"        stwcx. %0, 0, %2;\n"
"        bne- 1b;"
         : "=r" (result) 
         : "0" (result), "r" (pNum)
         : "cc", "memory"
		 );
	
	return result;
}

inline UINT32
HXAtomicDecRetUINT32(UINT32* pNum)
{
    volatile UINT32 result;

	__asm__ __volatile__ (
"1:      lwarx   %0, 0, %2;\n"
"        subi   %0, %0, 1;\n"
"        stwcx. %0, 0, %2;\n"
"        bne- 1b;"
         : "=r" (result) 
         :  "0" (result), "r" (pNum)
         : "cc", "memory"
         );
	
	return result;
}

/***********************************************************************
 * 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)

#include "microsleep.h"
#include "hxcom.h"
#include "hxmutexlock.h"

class HXAtomic
{
public:
    HXAtomic();
    ~HXAtomic();
    void InitLockPool();

    /* Users of the HXAtomic routines should *NEVER* call these directly.
     * They should *ALWAYS* use the HXAtomicAddRetINT32-style macros instead.
     */
    INT32  _AddRetINT32  (INT32*  pNum, INT32  nNum);
    UINT32 _AddRetUINT32 (UINT32* pNum, UINT32 ulNum);
    INT32  _SubRetINT32  (INT32*  pNum, INT32  nNum);
    UINT32 _SubRetUINT32 (UINT32* pNum, UINT32 ulNum);

private:
    void Lock   (HX_MUTEX pLock);
    void Unlock (HX_MUTEX pLock);

    HX_MUTEX* m_pLocks;
};

extern HXAtomic g_AtomicOps; //in common/util/atomicops.cpp

#define HXAtomicIncINT32(p)       g_AtomicOps._AddRetINT32((p),(INT32)1)
#define HXAtomicDecINT32(p)       g_AtomicOps._SubRetINT32((p),(INT32)1)
#define HXAtomicIncRetINT32(p)    g_AtomicOps._AddRetINT32((p),(INT32)1)
#define HXAtomicDecRetINT32(p)    g_AtomicOps._SubRetINT32((p),(INT32)1)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -