//%2006//////////////////////////////////////////////////////////////////////// // // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems. // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.; // IBM Corp.; EMC Corporation, The Open Group. // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.; // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group. // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.; // EMC Corporation; VERITAS Software Corporation; The Open Group. // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.; // EMC Corporation; Symantec Corporation; The Open Group. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // //============================================================================== // // Author: Mike Brasher (m.brasher@inovadevelopment.com) - Inova Development // //%///////////////////////////////////////////////////////////////////////////// #ifndef Pegasus_AtomicInt_h #define Pegasus_AtomicInt_h #include //============================================================================== // // class AtomicIntTemplate<> // //============================================================================== PEGASUS_NAMESPACE_BEGIN template class AtomicIntTemplate { public: // Constructor. AtomicIntTemplate(Uint32 n = 0); // Destructor. ~AtomicIntTemplate(); // Sets value. void set(Uint32 n); // Gets value. Uint32 get() const; // Increment. void inc(); // Decrement. void dec(); // Decrements and returns true if it is zero. bool decAndTestIfZero(); // Assignment. AtomicIntTemplate& operator=(Uint32 n) { set(n); return* this; } // Post-increment. void operator++(int) { inc(); } // Post-decrement. void operator--(int) { dec(); } private: // Note: These methods are intentionally hidden (and should not be called). // The implementation is much easier without having to implement these for // every platform. AtomicIntTemplate(const AtomicIntTemplate&); AtomicIntTemplate& operator=(const AtomicIntTemplate&); Boolean operator==(Uint32) const; void operator++(); void operator--(); typedef AtomicIntTemplate This; ATOMIC_TYPE _rep; }; PEGASUS_NAMESPACE_END //============================================================================== // // PEGASUS_PLATFORM_LINUX_IX86_GNU // //============================================================================== #if defined(PEGASUS_PLATFORM_LINUX_IX86_GNU) # define PEGASUS_ATOMIC_INT_DEFINED // Note: this lock can be eliminated for single processor systems. # define PEGASUS_ATOMIC_LOCK "lock ; " PEGASUS_NAMESPACE_BEGIN struct AtomicType { volatile int n; }; PEGASUS_TEMPLATE_SPECIALIZATION inline AtomicIntTemplate::AtomicIntTemplate(Uint32 n) { _rep.n = n; } PEGASUS_TEMPLATE_SPECIALIZATION inline AtomicIntTemplate::~AtomicIntTemplate() { } PEGASUS_TEMPLATE_SPECIALIZATION inline Uint32 AtomicIntTemplate::get() const { return _rep.n; } PEGASUS_TEMPLATE_SPECIALIZATION inline void AtomicIntTemplate::set(Uint32 n) { _rep.n = n; } PEGASUS_TEMPLATE_SPECIALIZATION inline void AtomicIntTemplate::inc() { asm volatile( PEGASUS_ATOMIC_LOCK "incl %0" :"=m" (_rep.n) :"m" (_rep.n)); } PEGASUS_TEMPLATE_SPECIALIZATION inline void AtomicIntTemplate::dec() { asm volatile( PEGASUS_ATOMIC_LOCK "decl %0" :"=m" (_rep.n) :"m" (_rep.n)); } PEGASUS_TEMPLATE_SPECIALIZATION inline bool AtomicIntTemplate::decAndTestIfZero() { unsigned char c; asm volatile( PEGASUS_ATOMIC_LOCK "decl %0; sete %1" :"=m" (_rep.n), "=qm" (c) :"m" (_rep.n) : "memory"); return c != 0; } typedef AtomicIntTemplate AtomicInt; PEGASUS_NAMESPACE_END #endif /* PEGASUS_PLATFORM_LINUX_IX86_GNU */ //============================================================================== // // PEGASUS_PLATFORM_LINUX_X86_64_GNU // //============================================================================== #if defined(PEGASUS_PLATFORM_LINUX_X86_64_GNU) # define PEGASUS_ATOMIC_INT_DEFINED // Note: this lock can be eliminated for single processor systems. # define PEGASUS_ATOMIC_LOCK "lock ; " PEGASUS_NAMESPACE_BEGIN struct AtomicType { volatile int n; }; PEGASUS_TEMPLATE_SPECIALIZATION inline AtomicIntTemplate::AtomicIntTemplate(Uint32 n) { _rep.n = n; } PEGASUS_TEMPLATE_SPECIALIZATION inline AtomicIntTemplate::~AtomicIntTemplate() { } PEGASUS_TEMPLATE_SPECIALIZATION inline Uint32 AtomicIntTemplate::get() const { return _rep.n; } PEGASUS_TEMPLATE_SPECIALIZATION inline void AtomicIntTemplate::set(Uint32 n) { _rep.n = n; } PEGASUS_TEMPLATE_SPECIALIZATION inline void AtomicIntTemplate::inc() { asm volatile( PEGASUS_ATOMIC_LOCK "incl %0" :"=m" (_rep.n) :"m" (_rep.n)); } PEGASUS_TEMPLATE_SPECIALIZATION inline void AtomicIntTemplate::dec() { asm volatile( PEGASUS_ATOMIC_LOCK "decl %0" :"=m" (_rep.n) :"m" (_rep.n)); } PEGASUS_TEMPLATE_SPECIALIZATION inline bool AtomicIntTemplate::decAndTestIfZero() { unsigned char c; asm volatile( PEGASUS_ATOMIC_LOCK "decl %0; sete %1" :"=m" (_rep.n), "=qm" (c) :"m" (_rep.n) : "memory"); return c != 0; } typedef AtomicIntTemplate AtomicInt; PEGASUS_NAMESPACE_END #endif /* PEGASUS_PLATFORM_LINUX_X86_64_GNU */ //============================================================================== // // PEGASUS_PLATFORM_LINUX_IA64_GNU // //============================================================================== #if defined(PEGASUS_PLATFORM_LINUX_IA64_GNU) # define PEGASUS_ATOMIC_INT_DEFINED PEGASUS_NAMESPACE_BEGIN struct AtomicType { volatile int n; }; PEGASUS_TEMPLATE_SPECIALIZATION inline AtomicIntTemplate::AtomicIntTemplate(Uint32 n) { _rep.n = (int)n; } PEGASUS_TEMPLATE_SPECIALIZATION inline AtomicIntTemplate::~AtomicIntTemplate() { // Nothing to do! } PEGASUS_TEMPLATE_SPECIALIZATION inline Uint32 AtomicIntTemplate::get() const { return (Uint32)_rep.n; } PEGASUS_TEMPLATE_SPECIALIZATION inline void AtomicIntTemplate::set(Uint32 n) { _rep.n = (int)n; } PEGASUS_TEMPLATE_SPECIALIZATION inline void AtomicIntTemplate::inc() { unsigned long tmp; volatile int* v = &_rep.n; asm volatile( "fetchadd4.rel %0=[%1],%2" : "=r"(tmp) : "r"(v), "i"(1) : "memory"); } PEGASUS_TEMPLATE_SPECIALIZATION inline void AtomicIntTemplate::dec() { unsigned long tmp; volatile int* v = &_rep.n; asm volatile( "fetchadd4.rel %0=[%1],%2" : "=r"(tmp) : "r"(v), "i"(-1) : "memory"); } PEGASUS_TEMPLATE_SPECIALIZATION inline bool AtomicIntTemplate::decAndTestIfZero() { unsigned long tmp; volatile int* v = &_rep.n; asm volatile( "fetchadd4.rel %0=[%1],%2" : "=r"(tmp) : "r"(v), "i"(-1) : "memory"); return tmp == 1; } typedef AtomicIntTemplate AtomicInt; PEGASUS_NAMESPACE_END #endif /* PEGASUS_PLATFORM_LINUX_IA64_GNU */ //============================================================================== // // PEGASUS_PLATFORM_LINUX_PPC_GNU // //============================================================================== #if defined(PEGASUS_PLATFORM_LINUX_PPC_GNU) # define PEGASUS_ATOMIC_INT_DEFINED PEGASUS_NAMESPACE_BEGIN struct AtomicType { volatile Uint32 n; }; PEGASUS_TEMPLATE_SPECIALIZATION inline AtomicIntTemplate::AtomicIntTemplate(Uint32 n) { _rep.n = n; } PEGASUS_TEMPLATE_SPECIALIZATION inline AtomicIntTemplate::~AtomicIntTemplate() { } PEGASUS_TEMPLATE_SPECIALIZATION inline Uint32 AtomicIntTemplate::get() const { return _rep.n; } PEGASUS_TEMPLATE_SPECIALIZATION inline void AtomicIntTemplate::set(Uint32 n) { _rep.n = n; } PEGASUS_TEMPLATE_SPECIALIZATION inline void AtomicIntTemplate::inc() { int t; asm volatile( "1: lwarx %0,0,%2\n" "addic %0,%0,1\n" "stwcx. %0,0,%2\n" "bne- 1b" : "=&r" (t), "=m" (_rep.n) : "r" (&_rep.n), "m" (_rep.n) : "cc"); } PEGASUS_TEMPLATE_SPECIALIZATION inline void AtomicIntTemplate::dec() { int c; asm volatile( "1: lwarx %0,0,%1\n" "addic %0,%0,-1\n" "stwcx. %0,0,%1\n" "bne- 1b" : "=&r" (c) : "r" (&_rep.n) : "cc", "memory"); } PEGASUS_TEMPLATE_SPECIALIZATION inline bool AtomicIntTemplate::decAndTestIfZero() { int c; asm volatile( "1: lwarx %0,0,%1\n" "addic %0,%0,-1\n" "stwcx. %0,0,%1\n" "bne- 1b" : "=&r" (c) : "r" (&_rep.n) : "cc", "memory"); return c == 0; } typedef AtomicIntTemplate AtomicInt; PEGASUS_NAMESPACE_END #endif /* PEGASUS_PLATFORM_LINUX_PPC_GNU */ //============================================================================== // // PEGASUS_PLATFORM_WIN32_IX86_MSVC // //============================================================================== #if defined(PEGASUS_PLATFORM_WIN32_IX86_MSVC) # define PEGASUS_ATOMIC_INT_DEFINED #include #include PEGASUS_NAMESPACE_BEGIN typedef LONG AtomicType; PEGASUS_TEMPLATE_SPECIALIZATION inline AtomicIntTemplate::AtomicIntTemplate(Uint32 n) { _rep = LONG(n); } PEGASUS_TEMPLATE_SPECIALIZATION inline AtomicIntTemplate::~AtomicIntTemplate() { } PEGASUS_TEMPLATE_SPECIALIZATION inline Uint32 AtomicIntTemplate::get() const { return Uint32(_rep); } PEGASUS_TEMPLATE_SPECIALIZATION inline void AtomicIntTemplate::set(Uint32 n) { _rep = LONG(n); } PEGASUS_TEMPLATE_SPECIALIZATION inline void AtomicIntTemplate::inc() { InterlockedIncrement(&_rep); } PEGASUS_TEMPLATE_SPECIALIZATION inline void AtomicIntTemplate::dec() { InterlockedDecrement(&_rep); } PEGASUS_TEMPLATE_SPECIALIZATION inline bool AtomicIntTemplate::decAndTestIfZero() { return InterlockedDecrement(&_rep) == 0; } typedef AtomicIntTemplate AtomicInt; PEGASUS_NAMESPACE_END #endif /* PEGASUS_PLATFORM_WIN32_IX86_MSVC */ //============================================================================== // // PEGASUS_PLATFORM_ZOS_ZSERIES_IBM // //============================================================================== #if defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM) # define PEGASUS_ATOMIC_INT_DEFINED PEGASUS_NAMESPACE_BEGIN struct AtomicType { cs_t n; }; PEGASUS_TEMPLATE_SPECIALIZATION inline AtomicIntTemplate::AtomicIntTemplate(Uint32 n) { _rep.n = (cs_t)n; } PEGASUS_TEMPLATE_SPECIALIZATION inline AtomicIntTemplate::~AtomicIntTemplate() { } PEGASUS_TEMPLATE_SPECIALIZATION inline Uint32 AtomicIntTemplate::get() const { return (Uint32)_rep.n; } PEGASUS_TEMPLATE_SPECIALIZATION inline void AtomicIntTemplate::set(Uint32 n) { _rep.n = (cs_t)n; } PEGASUS_TEMPLATE_SPECIALIZATION inline void AtomicIntTemplate::inc() { Uint32 x = (Uint32)_rep.n; Uint32 old = x; x++; while ( cs( (cs_t*)&old, &(_rep.n), (cs_t)x) ) { x = (Uint32)_rep.n; old = x; x++; } } PEGASUS_TEMPLATE_SPECIALIZATION inline void AtomicIntTemplate::dec() { Uint32 x = (Uint32)_rep.n; Uint32 old = x; x--; while ( cs( (cs_t*)&old, &(_rep.n), (cs_t) x) ) { x = (Uint32) _rep.n; old = x; x--; } } PEGASUS_TEMPLATE_SPECIALIZATION inline bool AtomicIntTemplate::decAndTestIfZero() { Uint32 x = (Uint32)_rep.n; Uint32 old = x; x--; while ( cs( (cs_t*)&old, &(_rep.n), (cs_t) x) ) { x = (Uint32) _rep.n; old = x; x--; } return x==0; } typedef AtomicIntTemplate AtomicInt; PEGASUS_NAMESPACE_END #endif /* PEGASUS_PLATFORM_ZOS_ZSERIES_IBM */ //============================================================================== // // PEGASUS_PLATFORM_HPUX_PARISC_ACC // //============================================================================== #if defined (PEGASUS_PLATFORM_HPUX_PARISC_ACC) // Uses generic implementation defined later. #endif /* PEGASUS_PLATFORM_HPUX_PARISC_ACC */ //============================================================================== // // PEGASUS_PLATFORM_HPUX_IA64_ACC // //============================================================================== #if defined (PEGASUS_PLATFORM_HPUX_IA64_ACC) # define PEGASUS_ATOMIC_INT_DEFINED #include PEGASUS_NAMESPACE_BEGIN struct AtomicType { volatile Uint32 n; }; PEGASUS_TEMPLATE_SPECIALIZATION inline AtomicIntTemplate::AtomicIntTemplate(Uint32 n) { _rep.n = n; } PEGASUS_TEMPLATE_SPECIALIZATION inline AtomicIntTemplate::~AtomicIntTemplate() { // Nothing to do! } PEGASUS_TEMPLATE_SPECIALIZATION inline Uint32 AtomicIntTemplate::get() const { return _rep.n; } PEGASUS_TEMPLATE_SPECIALIZATION inline void AtomicIntTemplate::set(Uint32 n) { _rep.n = n; } PEGASUS_TEMPLATE_SPECIALIZATION inline void AtomicIntTemplate::inc() { _Asm_fetchadd( (_Asm_fasz)_FASZ_W, (_Asm_sem)_SEM_ACQ, (volatile Uint32*)&_rep.n, (int)1, (_Asm_ldhint)_LDHINT_NONE); } PEGASUS_TEMPLATE_SPECIALIZATION inline void AtomicIntTemplate::dec() { _Asm_fetchadd( (_Asm_fasz)_FASZ_W, (_Asm_sem)_SEM_ACQ, (volatile Uint32*)&_rep.n, (int)-1, (_Asm_ldhint)_LDHINT_NONE); } PEGASUS_TEMPLATE_SPECIALIZATION inline bool AtomicIntTemplate::decAndTestIfZero() { Uint32 x = _Asm_fetchadd( (_Asm_fasz)_FASZ_W, (_Asm_sem)_SEM_ACQ, (volatile Uint32*)&_rep.n, (int)-1, (_Asm_ldhint)_LDHINT_NONE); return x == 1; } typedef AtomicIntTemplate AtomicInt; PEGASUS_NAMESPACE_END #endif /* PEGASUS_PLATFORM_HPUX_IA64_ACC */ //============================================================================== // // PEGASUS_PLATFORM_LINUX_XSCALE_GNU // //============================================================================== #if defined (PEGASUS_PLATFORM_LINUX_XSCALE_GNU) # define PEGASUS_ATOMIC_INT_DEFINED PEGASUS_NAMESPACE_BEGIN inline void AtomicIntDisableIRQs(unsigned long& flags) { unsigned long temp; unsigned long x; asm volatile( "mrs %0, cpsr\n" "orr %1, %0, #128\n" "msr cpsr_c, %1\n" : "=r" (x), "=r" (temp) : : "memory"); flags = x; } inline void AtomicIntEnableIRQs(unsigned long x) { unsigned long temp; asm volatile( "mrs %0, cpsr\n" "orr %1, %0, #128\n" "msr cpsr_c, %1\n" : "=r" (x), "=r" (temp) : : "memory"); } struct AtomicType { volatile Uint32 n; }; PEGASUS_TEMPLATE_SPECIALIZATION inline AtomicIntTemplate::AtomicIntTemplate(Uint32 n) { _rep.n = n; } PEGASUS_TEMPLATE_SPECIALIZATION inline AtomicIntTemplate::~AtomicIntTemplate() { } PEGASUS_TEMPLATE_SPECIALIZATION inline Uint32 AtomicIntTemplate::get() const { return _rep.n; } PEGASUS_TEMPLATE_SPECIALIZATION inline void AtomicIntTemplate::set(Uint32 n) { _rep.n = n; } PEGASUS_TEMPLATE_SPECIALIZATION inline void AtomicIntTemplate::inc() { unsigned long flags; AtomicIntDisableIRQs(flags); _rep.n++; AtomicIntEnableIRQs(flags); } PEGASUS_TEMPLATE_SPECIALIZATION inline void AtomicIntTemplate::dec() { unsigned long flags; AtomicIntDisableIRQs(flags); _rep.n--; AtomicIntEnableIRQs(flags); } PEGASUS_TEMPLATE_SPECIALIZATION inline bool AtomicIntTemplate::decAndTestIfZero() { Uint32 tmp; unsigned long flags; AtomicIntDisableIRQs(flags); tmp = --_rep.n; AtomicIntEnableIRQs(flags); return tmp == 0; } typedef AtomicIntTemplate AtomicInt; PEGASUS_NAMESPACE_END #endif /* PEGASUS_PLATFORM_LINUX_XSCALE_GNU */ //============================================================================== // // PEGASUS_PLATFORM_VMS_ALPHA_DECCXX // PEGASUS_PLATFORM_VMS_IA64_DECCXX // //============================================================================== #if defined (PEGASUS_PLATFORM_VMS_ALPHA_DECCXX) || \ defined (PEGASUS_PLATFORM_VMS_IA64_DECCXX) # define PEGASUS_ATOMIC_INT_DEFINED # include PEGASUS_NAMESPACE_BEGIN struct AtomicType { volatile int n; }; PEGASUS_TEMPLATE_SPECIALIZATION inline AtomicIntTemplate::AtomicIntTemplate(Uint32 n) { _rep.n = n; } PEGASUS_TEMPLATE_SPECIALIZATION inline AtomicIntTemplate::~AtomicIntTemplate() { } PEGASUS_TEMPLATE_SPECIALIZATION inline Uint32 AtomicIntTemplate::get() const { return _rep.n; } PEGASUS_TEMPLATE_SPECIALIZATION inline void AtomicIntTemplate::set(Uint32 n) { _rep.n = n; } PEGASUS_TEMPLATE_SPECIALIZATION inline void AtomicIntTemplate::inc() { __ATOMIC_INCREMENT_LONG(&_rep.n); } PEGASUS_TEMPLATE_SPECIALIZATION inline void AtomicIntTemplate::dec() { __ATOMIC_DECREMENT_LONG(&_rep.n); } PEGASUS_TEMPLATE_SPECIALIZATION inline bool AtomicIntTemplate::decAndTestIfZero() { return __ATOMIC_DECREMENT_LONG(&_rep.n) == 1; } typedef AtomicIntTemplate AtomicInt; PEGASUS_NAMESPACE_END #endif /* _Pegasus_Common_AtomicInt_VMS_h */ //============================================================================== // // Generic Implementation // //============================================================================== #if !defined(PEGASUS_ATOMIC_INT_DEFINED) # define PEGASUS_ATOMIC_INT_DEFINED # include PEGASUS_NAMESPACE_BEGIN // Represents the atomic type counter. struct AtomicType { Uint32 n; }; PEGASUS_TEMPLATE_SPECIALIZATION inline AtomicIntTemplate::AtomicIntTemplate(Uint32 n) { _rep.n = n; if (spinLockPoolInitialized == 0) SpinLockCreatePool(); } PEGASUS_TEMPLATE_SPECIALIZATION inline AtomicIntTemplate::~AtomicIntTemplate() { // Nothing to do. } PEGASUS_TEMPLATE_SPECIALIZATION inline Uint32 AtomicIntTemplate::get() const { Uint32 tmp; size_t i = SpinLockIndex(&_rep); SpinLockLock(spinLockPool[i]); tmp = _rep.n; SpinLockUnlock(spinLockPool[i]); return tmp; } PEGASUS_TEMPLATE_SPECIALIZATION inline void AtomicIntTemplate::set(Uint32 n) { size_t i = SpinLockIndex(&_rep); SpinLockLock(spinLockPool[i]); _rep.n = n; SpinLockUnlock(spinLockPool[i]); } PEGASUS_TEMPLATE_SPECIALIZATION inline void AtomicIntTemplate::inc() { size_t i = SpinLockIndex(&_rep); SpinLockLock(spinLockPool[i]); _rep.n++; SpinLockUnlock(spinLockPool[i]); } PEGASUS_TEMPLATE_SPECIALIZATION inline void AtomicIntTemplate::dec() { size_t i = SpinLockIndex(&_rep); SpinLockLock(spinLockPool[i]); _rep.n--; SpinLockUnlock(spinLockPool[i]); } PEGASUS_TEMPLATE_SPECIALIZATION inline bool AtomicIntTemplate::decAndTestIfZero() { Uint32 tmp; size_t i = SpinLockIndex(&_rep); SpinLockLock(spinLockPool[i]); tmp = --_rep.n; SpinLockUnlock(spinLockPool[i]); return tmp == 0; } typedef AtomicIntTemplate AtomicInt; PEGASUS_NAMESPACE_END #endif /* !PEGASUS_ATOMIC_INT_DEFINED */ #endif /* Pegasus_AtomicInt_h */