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

📄 atomicbase.h

📁 著名的 helix realplayer 基于手机 symbian 系统的 播放器全套源代码
💻 H
📖 第 1 页 / 共 4 页
字号:
/* ***** BEGIN LICENSE BLOCK ***** 
 * Version: RCSL 1.0/RPSL 1.0 
 *  
 * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 
 *      
 * The contents of this file, and the files included with this file, are 
 * subject to the current version of the RealNetworks Public Source License 
 * Version 1.0 (the "RPSL") available at 
 * http://www.helixcommunity.org/content/rpsl unless you have licensed 
 * the file under the RealNetworks Community Source License Version 1.0 
 * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 
 * in which case the RCSL will apply. You may also obtain the license terms 
 * directly from RealNetworks.  You may not use this file except in 
 * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 
 * applicable to this file, the RCSL.  Please see the applicable RPSL or 
 * RCSL for the rights, obligations and limitations governing use of the 
 * contents of the file.  
 *  
 * This file is part of the Helix DNA Technology. RealNetworks is the 
 * developer of the Original Code and owns the copyrights in the portions 
 * it created. 
 *  
 * This file, and the files included with this file, is distributed and made 
 * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
 * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 
 * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
 * 
 * Technology Compatibility Kit Test Suite(s) Location: 
 *    http://www.helixcommunity.org/content/tck 
 * 
 * Contributor(s): 
 *  
 * ***** END LICENSE BLOCK ***** */ 


/***********************************************************************
 *  THIS CODE IS HIGHLY CRITICAL TO THE SERVER'S STABILITY!!!
 *  DO NOT MAKE CHANGES TO THE ATOMIC OPERATORS OR TO THE
 *  MUTEX CODE WITHOUT A SERVER TEAM CODE-REVIEW! (dev@helix-server)
 */


/****************************************************************************
 *  $Id: atomicbase.h,v 1.23.2.2 2004/01/26 23:46:02 rggammon Exp $
 *
 *  atomicbase.h - Defines several atomic operations
 * 
 *  See server/common/util/pub/servatomic.h for broader platform support.
 *  Also conditionally overrides InterlockedIncrement/Decrement
 *  via USE_HX_ATOMIC_INTERLOCKED_INC_DEC.
 *
 *
 ***********************************************************************
 *
 * Defines:
 *
 * void HXAtomicIncINT32(INT32* p)             -- Increment *p
 * void HXAtomicDecINT32(INT32* p)             -- Decrement *p
 * void HXAtomicAddINT32(INT32* p, INT32 n)    -- Increment *p by n 
 * void HXAtomicSubINT32(INT32* p, INT32 n)    -- Decrement *p by n
 * INT32 HXAtomicIncRetINT32(INT32* p)         -- Increment *p and return it
 * INT32 HXAtomicDecRetINT32(INT32* p)         -- Decrement *p and return it
 * INT32 HXAtomicAddRetINT32(INT32* p, INT32 n)-- Increment *p by n, return it
 * INT32 HXAtomicSubRetINT32(INT32* p, INT32 n)-- Increment *p by n, return it
 *
 *
 * There are also UINT32 versions:
 *
 * void HXAtomicIncUINT32(UINT32* p)
 * void HXAtomicDecUINT32(UINT32* p)
 * void HXAtomicAddUINT32(UINT32* p, UINT32 n)
 * void HXAtomicSubUINT32(UINT32* p, UINT32 n)
 * UINT32 HXAtomicIncRetUINT32(UINT32* p)
 * UINT32 HXAtomicDecRetUINT32(UINT32* p)
 * UINT32 HXAtomicAddRetUINT32(UINT32* p, UINT32 n)
 * UINT32 HXAtomicSubRetUINT32(UINT32* p, UINT32 n)
 *
 ***********************************************************************
 *
 * TODO:
 *   Add INT64 versions
 *   Obsolete the 0x80000000-based Solaris implementation entirely.
 *
 ***********************************************************************/
#ifndef _ATOMICBASE_H_
#define _ATOMICBASE_H_


/***********************************************************************
 * Sun Solaris / SPARC (Native compiler)
 *
 * Implementation Notes:
 * This uses inline assembly from server/common/util/platform/solaris/atomicops.il
 * Note: Sparc/gcc is in include/atomicbase.h
 */
#if defined (_SOLARIS) && !defined (__GNUC__)

#if defined(__cplusplus)
extern "C" {
#endif
    //UINT32 _HXAtomicIncRetUINT32 (UINT32* pNum);
    //UINT32 _HXAtomicDecRetUINT32 (UINT32* pNum);
    UINT32 _HXAtomicAddRetUINT32 (UINT32* pNum, UINT32 ulNum);
    UINT32 _HXAtomicSubRetUINT32 (UINT32* pNum, UINT32 ulNum);
#if defined(__cplusplus)
}
#endif


#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))

inline void HXAtomicIncINT32(INT32* p)              { HXAtomicIncUINT32((UINT32*)p); }
inline void HXAtomicDecINT32(INT32* p)              { HXAtomicDecUINT32((UINT32*)p); }
inline void HXAtomicAddINT32(INT32* p, INT32 n)     { HXAtomicAddUINT32((UINT32*)p, (UINT32)n); }
inline void HXAtomicSubINT32(INT32* p, INT32 n)     { HXAtomicSubUINT32((UINT32*)p, (UINT32)n); }
inline INT32 HXAtomicIncRetINT32(INT32* p)          { return HXAtomicIncRetUINT32((UINT32*)p); }
inline INT32 HXAtomicDecRetINT32(INT32* p)          { return HXAtomicDecRetUINT32((UINT32*)p); }
inline INT32 HXAtomicAddRetINT32(INT32* p, INT32 n) { return HXAtomicAddRetUINT32((UINT32*)p, (UINT32)n); }
inline INT32 HXAtomicSubRetINT32(INT32* p, INT32 n) { return HXAtomicSubRetUINT32((UINT32*)p, (UINT32)n); }



/***********************************************************************
 * Sun Solaris / SPARC (gcc)
 *
 * Implementation Notes:
 * The sparc method of pipelining and use of "delay slots" requires
 * the nop's.  Be extra careful modifying these routines!
 *
 * This implementation sacrifices being able to store the value
 * 0x800000000 in the INT32 value, which is a special "busy" marker value.
 * Since these are intended for use primarily with AddRef/Release and
 * resource usage counters, this should be acceptable for now.  If a counter
 * is incremented to the point it would conflict with the flag, it is
 * incremented one more to hop over it.  The same in reverse for decrement.
 * This is far from ideal, however...  See the inline-assembly file
 * server/common/util/platform/solaris/mutex_setbit.il for *much*
 * better implementations using newer sparc assembly operators.
 *
 * Basic design of the flag-based implementation:
 *   1. Load a register with 0x80000000
 *   2. _atomically_ swap it with the INT32 (critical!)
 *   3. Compare what we got with 0x80000000
 *   4. Branch if equal to #2
 *   5. Increment (or decrement) the result
 *   6. Compare to 0x80000000
 *   7. Branch if equal to #5
 *   8. Save the new value to the INT32's location in memory
 *   9. Return new INT32 result if required
 *   
 * This implementation primarily exists due to limitations in the ancient
 * version of gcc we used to use on Solaris (2.7.2.3), and more modern
 * gcc's can probably handle assembly more like what's used in Sun's
 * Native compiler version.  
 *
 */
#elif defined (__sparc__) && defined (__GNUC__)

/* Increment by 1 */
inline void
HXAtomicIncUINT32(UINT32* pNum)
{
    __asm__ __volatile__(\
"1:      swap    [%0], %2;               ! Swap *pNum and %2\n"
"        nop;                            ! delay slot...\n"
"        cmp     %2, %1;                 ! Is someone else using pNum?\n"
"        be      1b;                     ! If so, retry...\n"
"        nop;                            ! delay slot...yawn\n"
"2:      inc     %2;                     ! Increment %2\n"
"        cmp     %2, %1;                 ! check for overflow\n"
"        be      2b;                     ! if so, inc again\n"
"        nop;                            ! but this means a delay, sigh\n"
"        st      %2, [%0];               ! Save new value into *pNum\n"
        : /* no output */
        : "r" (pNum), "r" (0x80000000), "r" (0x80000000)
        : "cc", "memory"
        );
}

/* Decrement by 1 */
inline void
HXAtomicDecUINT32(UINT32* pNum)
{
    __asm__ __volatile__(
"1:      swap    [%0], %2;               ! Swap *pNum and %2\n"
"        nop;                            ! delay slot...\n"
"        cmp     %2, %1;                 ! Is someone else using pNum?\n"
"        be      1b;                     ! If so, retry...\n"
"        nop;                            ! delay slot...yawn\n"
"2:      dec     %2;                     ! Increment %2\n"
"        cmp     %2, %1;                 ! check for overflow\n"
"        be      2b;                     ! if so, dec again\n"
"        nop;                            ! but this means a delay, sigh\n"
"        st      %2, [%0];               ! Save new value into *pNum\n"
        : /* no output */
        : "r" (pNum), "r" (0x80000000), "r" (0x80000000)
        : "cc", "memory"
        );
}

/* Increment by 1 and return new value */
inline UINT32
HXAtomicIncRetUINT32(UINT32* pNum)
{
    volatile UINT32 ulRet;
    __asm__ __volatile__(
"        mov     %2, %0;                 ! Copy %2 to %0 \n"
"1:      swap    [%1], %0;               ! Swap *pNum and %0\n"
"        nop;                            ! delay slot...\n"
"        cmp     %0, %2;                 ! Is someone else using pNum?\n"
"        be      1b;                     ! If so, retry...\n"
"        nop;                            ! delay slot...yawn\n"
"2:      inc     %0;                     ! Increment %0\n"
"        cmp     %0, %2;                 ! check for overflow\n"
"        be      2b;                     ! if so, inc again\n"
"        nop;                            ! but this means a delay, sigh\n"
"        st      %0, [%1];               ! Save new value into *pNum\n"
        : "=r" (ulRet)
        : "r" (pNum), "r" (0x80000000), "0" (ulRet)
        : "cc", "memory"
        );
    return ulRet;
}

/* Decrement by 1 and return new value */
inline UINT32
HXAtomicDecRetUINT32(UINT32* pNum)
{   volatile UINT32 ulRet;
    __asm__ __volatile__(
"        mov     %2, %0;                 ! Copy %2 to %0 \n"
"1:      swap    [%1], %0;               ! Swap *pNum and %0\n"
"        nop;                            ! delay slot...\n"
"        cmp     %0, %2;                 ! Is someone else using pNum?\n"
"        be      1b;                     ! If so, retry...\n"
"        nop;                            ! delay slot...yawn\n"
"2:      dec     %0;                     ! Decrement %0\n"
"        cmp     %0, %2;                 ! check for overflow\n"
"        be      2b;                     ! if so, dec again\n"
"        nop;                            ! but this means a delay, sigh\n"
"        st      %0, [%1];               ! Save new value into *pNum\n"
        : "=r" (ulRet)
        : "r" (pNum), "r" (0x80000000), "0" (ulRet)
        : "cc", "memory"
        );
    return ulRet;
}

/* Add n */
inline void
HXAtomicAddUINT32(UINT32* pNum, UINT32 ulNum)
{
    __asm__ __volatile__(
"1:      swap    [%0], %2;               ! Swap *pNum and %2\n"
"        nop;                            ! delay slot...\n"
"        cmp     %2, %1;                 ! Is someone else using pNum?\n"
"        be      1b;                     ! If so, retry...\n"
"        nop;                            ! delay slot...yawn\n"
"        add     %2, %3, %2;             ! Add ulNum to %2\n"
"        cmp     %2, %1;                 ! check for overflow\n"
"        bne     2f;                     ! if not, skip to the end\n"
"        nop;                            ! but this means a delay, sigh\n"
"        inc     %2;                     ! skip marker value\n"
"2:      st      %2, [%0];               ! Save new value into *pNum\n"
        : /* no output */
        : "r" (pNum), "r" (0x80000000), "r" (0x80000000), "r" (ulNum)
        : "cc", "memory"
        );
}

/* Subtract n */
inline void
HXAtomicSubUINT32(UINT32* pNum, UINT32 ulNum)
{
    __asm__ __volatile__(
"1:      swap    [%0], %2;               ! Swap *pNum and %2\n"
"        nop;                            ! delay slot...\n"
"        cmp     %2, %1;                 ! Is someone else using pNum?\n"
"        be      1b;                     ! If so, retry...\n"
"        nop;                            ! delay slot...yawn\n"
"        sub     %2, %3, %2;             ! Subtract ulNum to %2\n"
"        cmp     %2, %1;                 ! check for overflow\n"
"        bne     2f;                     ! if not, skip to the end\n"
"        nop;                            ! but this means a delay, sigh\n"
"        inc     %2;                     ! skip marker value\n"
"2:      st      %2, [%0];               ! Save new value into *pNum\n"
        : /* no output */
        : "r" (pNum), "r" (0x80000000), "r" (0x80000000), "r" (ulNum)
        : "cc", "memory"
        );
}

/* Add n and return new value */
inline UINT32
HXAtomicAddRetUINT32(UINT32* pNum, UINT32 ulNum)
{
    volatile UINT32 ulRet; \
    __asm__ __volatile__(
"        mov     %2, %0                  ! Copy %2 to %0 \n"
"1:      swap    [%1], %0;               ! Swap *pNum and %0\n"
"        nop;                            ! delay slot...\n"
"        cmp     %0, %2;                 ! Is someone else using pNum?\n"
"        be      1b;                     ! If so, retry...\n"
"        nop;                            ! delay slot...yawn\n"
"        add     %0, %3, %0;             ! Add ulNum to %0\n"
"        cmp     %0, %2;                 ! check for overflow\n"
"        bne     2f;                     ! if not, skip to the end\n"
"        nop;                            ! but this means a delay, sigh\n"
"        inc     %0;                     ! skip marker value\n"
"2:      st      %0, [%1];               ! Save new value into *pNum\n"
        : "=r" (ulRet)
        : "r" (pNum), "r" (0x80000000), "r" (ulNum), "0" (ulRet)
        : "cc", "memory"
        );
        return ulRet;
}

/* Subtract n and return new value */
inline UINT32
HXAtomicSubRetUINT32(UINT32* pNum, UINT32 ulNum)
{   volatile UINT32 ulRet;
    __asm__ __volatile__(
"        mov     %2, %0                  ! Copy %2 to %0 \n"
"1:      swap    [%1], %0;               ! Swap *pNum and %0\n"
"        nop;                            ! delay slot...\n"
"        cmp     %0, %2;                 ! Is someone else using pNum?\n"
"        be      1b;                     ! If so, retry...\n"
"        nop;                            ! delay slot...yawn\n"
"        sub     %0, %3, %0;             ! Sub ulNum from %0\n"
"        cmp     %0, %2;                 ! check for overflow\n"
"        bne     2f;                     ! if not, skip to the end\n"
"        nop;                            ! but this means a delay, sigh\n"
"        dec     %0;                     ! skip marker value\n"
"2:      st      %0, [%1];               ! Save new value into *pNum\n"
        : "=r" (ulRet)
        : "r" (pNum), "r" (0x80000000), "r" (ulNum), "0" (ulRet)
        : "cc", "memory"
        );
        return ulRet;
}

inline void HXAtomicIncINT32(INT32* p)              { HXAtomicIncUINT32((UINT32*)p); }
inline void HXAtomicDecINT32(INT32* p)              { HXAtomicDecUINT32((UINT32*)p); }
inline void HXAtomicAddINT32(INT32* p, INT32 n)     { HXAtomicAddUINT32((UINT32*)p, (UINT32)n); }
inline void HXAtomicSubINT32(INT32* p, INT32 n)     { HXAtomicSubUINT32((UINT32*)p, (UINT32)n); }
inline INT32 HXAtomicIncRetINT32(INT32* p)          { return HXAtomicIncRetUINT32((UINT32*)p); }
inline INT32 HXAtomicDecRetINT32(INT32* p)          { return HXAtomicDecRetUINT32((UINT32*)p); }
inline INT32 HXAtomicAddRetINT32(INT32* p, INT32 n) { return HXAtomicAddRetUINT32((UINT32*)p, (UINT32)n); }
inline INT32 HXAtomicSubRetINT32(INT32* p, INT32 n) { return HXAtomicSubRetUINT32((UINT32*)p, (UINT32)n); }

⌨️ 快捷键说明

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