diff options
author | Chris Cleeland <chris.cleeland@gmail.com> | 2002-09-03 23:09:26 +0000 |
---|---|---|
committer | Chris Cleeland <chris.cleeland@gmail.com> | 2002-09-03 23:09:26 +0000 |
commit | 519afa77126fad5a8a7acf367852ed332247a30b (patch) | |
tree | e763aff3e70097db4ef86735f3ad4a9651bfaa5f /ace/Atomic_Op.cpp | |
parent | 22e1fc30c6d6d609130692500993f90745de0c74 (diff) | |
download | ATCD-519afa77126fad5a8a7acf367852ed332247a30b.tar.gz |
ChangeLogTag:Tue Sep 3 15:54:33 2002 Christopher Kohlhoff <chris@kohlhoff.com>
Diffstat (limited to 'ace/Atomic_Op.cpp')
-rw-r--r-- | ace/Atomic_Op.cpp | 192 |
1 files changed, 143 insertions, 49 deletions
diff --git a/ace/Atomic_Op.cpp b/ace/Atomic_Op.cpp index df82902efcb..8261ec2f6d8 100644 --- a/ace/Atomic_Op.cpp +++ b/ace/Atomic_Op.cpp @@ -1,83 +1,177 @@ -#ifndef ACE_ATOMIC_OP_C -#define ACE_ATOMIC_OP_C +// $Id$ #include "ace/Atomic_Op.h" +#include "ace/OS.h" -#if !defined (ACE_LACKS_PRAGMA_ONCE) -# pragma once -#endif /* ACE_LACKS_PRAGMA_ONCE */ +ACE_RCSID(ace, Atomic_Op, "$Id$") #if !defined (__ACE_INLINE__) -// On non-Win32 platforms, this code will be treated as normal code. -#if !defined (ACE_WIN32) #include "ace/Atomic_Op.i" -#endif /* !ACE_WIN32 */ #endif /* __ACE_INLINE__ */ +#if defined (ACE_HAS_BUILTIN_ATOMIC_OP) -ACE_ALLOC_HOOK_DEFINE(ACE_Atomic_Op_Ex) -ACE_ALLOC_HOOK_DEFINE(ACE_Atomic_Op) - -ACE_RCSID(ace, Atomic_Op, "$Id$") +long (*ACE_Atomic_Op<ACE_Thread_Mutex, long>::increment_fn_) (volatile long *) = 0; +long (*ACE_Atomic_Op<ACE_Thread_Mutex, long>::decrement_fn_) (volatile long *) = 0; +long (*ACE_Atomic_Op<ACE_Thread_Mutex, long>::exchange_add_fn_) (volatile long *, long) = 0; -// ************************************************* -template <class ACE_LOCK, class TYPE> ACE_LOCK & -ACE_Atomic_Op_Ex<ACE_LOCK, TYPE>::mutex (void) +void +ACE_Atomic_Op<ACE_Thread_Mutex, long>::init_functions (void) { - // ACE_TRACE ("ACE_Atomic_Op_Ex<ACE_LOCK, TYPE>::mutex"); - return this->mutex_; + if (ACE_OS::num_processors () == 1) + { + increment_fn_ = single_cpu_increment; + decrement_fn_ = single_cpu_decrement; + exchange_add_fn_ = single_cpu_exchange_add; + } + else + { + increment_fn_ = multi_cpu_increment; + decrement_fn_ = multi_cpu_decrement; + exchange_add_fn_ = multi_cpu_exchange_add; + } } -template <class ACE_LOCK, class TYPE> void -ACE_Atomic_Op_Ex<ACE_LOCK, TYPE>::dump (void) const +void +ACE_Atomic_Op<ACE_Thread_Mutex, long>::dump (void) const { - // ACE_TRACE ("ACE_Atomic_Op_Ex<ACE_LOCK, TYPE>::dump"); ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); - this->mutex_.dump (); ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); } -template <class ACE_LOCK, class TYPE> -ACE_Atomic_Op_Ex<ACE_LOCK, TYPE>::ACE_Atomic_Op_Ex - (ACE_LOCK &mtx) - : mutex_ (mtx), - value_ (0) +#if defined (_MSC_VER) +// Disable "no return value" warning, as we will be putting +// the return values directly into the EAX register. +#pragma warning (push) +#pragma warning (disable: 4035) +#endif /* _MSC_VER */ + +long +ACE_Atomic_Op<ACE_Thread_Mutex, long>::single_cpu_increment (volatile long *value) { - // ACE_TRACE ("ACE_Atomic_Op_Ex<ACE_LOCK, TYPE>::ACE_Atomic_Op_Ex"); +#if defined (__GNUC__) && defined (ACE_HAS_PENTIUM) + long tmp = 1; + unsigned long addr = ACE_reinterpret_cast (unsigned long, value); + asm( "xadd %0, (%1)" : "+r"(tmp) : "r"(addr) ); + return tmp + 1; +#else /* __GNUC__ && ACE_HAS_PENTIUM */ + ACE_UNUSED_ARG (value); + ACE_NOTSUP_RETURN (-1); +#endif /* __GNUC__ && ACE_HAS_PENTIUM */ } -template <class ACE_LOCK, class TYPE> -ACE_Atomic_Op_Ex<ACE_LOCK, TYPE>::ACE_Atomic_Op_Ex - (ACE_LOCK &mtx, const TYPE &c) - : mutex_ (mtx), - value_ (c) +long +ACE_Atomic_Op<ACE_Thread_Mutex, long>::single_cpu_decrement (volatile long *value) { -// ACE_TRACE ("ACE_Atomic_Op_Ex<ACE_LOCK, TYPE>::ACE_Atomic_Op_Ex"); +#if defined (__GNUC__) && defined (ACE_HAS_PENTIUM) + long tmp = -1; + unsigned long addr = ACE_reinterpret_cast (unsigned long, value); + asm( "xadd %0, (%1)" : "+r"(tmp) : "r"(addr) ); + return tmp - 1; +#else /* __GNUC__ && ACE_HAS_PENTIUM */ + ACE_UNUSED_ARG (value); + ACE_NOTSUP_RETURN (-1); +#endif /* __GNUC__ && ACE_HAS_PENTIUM */ } -// **************************************************************** +long +ACE_Atomic_Op<ACE_Thread_Mutex, long>::single_cpu_exchange_add (volatile long *value, + long rhs) +{ +#if defined (__GNUC__) && defined (ACE_HAS_PENTIUM) + unsigned long addr = ACE_reinterpret_cast (unsigned long, value); + asm( "xadd %0, (%1)" : "+r"(rhs) : "r"(addr) ); + return rhs; +#elif defined (WIN32) && !defined (ACE_HAS_INTERLOCKED_EXCHANGEADD) +# if defined (_MSC_VER) + __asm + { + mov eax, rhs + mov edx, value + xadd [edx], eax + } + // Return value is already in EAX register. +# elif defined (__BORLANDC__) + _EAX = rhs; + _EDX = ACE_reinterpret_cast (unsigned long, value); + __emit__(0x0F, 0xC1, 0x02); // xadd [edx], eax + // Return value is already in EAX register. +# else /* _MSC_VER */ + ACE_UNUSED_ARG (value); + ACE_UNUSED_ARG (rhs); + ACE_NOTSUP_RETURN (-1); +# endif /* _MSC_VER */ +#else /* __GNUC__ && ACE_HAS_PENTIUM */ + ACE_UNUSED_ARG (value); + ACE_UNUSED_ARG (rhs); + ACE_NOTSUP_RETURN (-1); +#endif /* __GNUC__ && ACE_HAS_PENTIUM */ +} -template <class ACE_LOCK, class TYPE> -ACE_Atomic_Op<ACE_LOCK, TYPE>::ACE_Atomic_Op (void) - : ACE_Atomic_Op_Ex < ACE_LOCK,TYPE > (this->own_mutex_) +long +ACE_Atomic_Op<ACE_Thread_Mutex, long>::multi_cpu_increment (volatile long *value) { - // ACE_TRACE ("ACE_Atomic_Op<ACE_LOCK, TYPE>::ACE_Atomic_Op"); +#if defined (__GNUC__) && defined (ACE_HAS_PENTIUM) + long tmp = 1; + unsigned long addr = ACE_reinterpret_cast (unsigned long, value); + asm( "lock ; xadd %0, (%1)" : "+r"(tmp) : "r"(addr) ); + return tmp + 1; +#else /* __GNUC__ && ACE_HAS_PENTIUM */ + ACE_UNUSED_ARG (value); + ACE_NOTSUP_RETURN (-1); +#endif /* __GNUC__ && ACE_HAS_PENTIUM */ } -template <class ACE_LOCK, class TYPE> -ACE_Atomic_Op<ACE_LOCK, TYPE>::ACE_Atomic_Op (const TYPE &c) - : ACE_Atomic_Op_Ex < ACE_LOCK,TYPE > (this->own_mutex_, c) +long +ACE_Atomic_Op<ACE_Thread_Mutex, long>::multi_cpu_decrement (volatile long *value) { - // ACE_TRACE ("ACE_Atomic_Op<ACE_LOCK, TYPE>::ACE_Atomic_Op"); +#if defined (__GNUC__) && defined (ACE_HAS_PENTIUM) + long tmp = -1; + unsigned long addr = ACE_reinterpret_cast (unsigned long, value); + asm( "lock ; xadd %0, (%1)" : "+r"(tmp) : "r"(addr) ); + return tmp - 1; +#else /* __GNUC__ && ACE_HAS_PENTIUM */ + ACE_UNUSED_ARG (value); + ACE_NOTSUP_RETURN (-1); +#endif /* __GNUC__ && ACE_HAS_PENTIUM */ } -template <class ACE_LOCK, class TYPE> ACE_INLINE -ACE_Atomic_Op<ACE_LOCK, TYPE>::ACE_Atomic_Op - (const ACE_Atomic_Op<ACE_LOCK, TYPE> &rhs) - : ACE_Atomic_Op_Ex < ACE_LOCK,TYPE > - ( this->own_mutex_, rhs.value() ) +long +ACE_Atomic_Op<ACE_Thread_Mutex, long>::multi_cpu_exchange_add (volatile long *value, + long rhs) { -// ACE_TRACE ("ACE_Atomic_Op<ACE_LOCK, TYPE>::ACE_Atomic_Op"); +#if defined (__GNUC__) && defined (ACE_HAS_PENTIUM) + unsigned long addr = ACE_reinterpret_cast (unsigned long, value); + asm( "lock ; xadd %0, (%1)" : "+r"(rhs) : "r"(addr) ); + return rhs; +#elif defined (WIN32) && !defined (ACE_HAS_INTERLOCKED_EXCHANGEADD) +# if defined (_MSC_VER) + __asm + { + mov eax, rhs + mov edx, value + lock xadd [edx], eax + } + // Return value is already in EAX register. +# elif defined (__BORLANDC__) + _EAX = rhs; + _EDX = ACE_reinterpret_cast (unsigned long, value); + __emit__(0xF0, 0x0F, 0xC1, 0x02); // lock xadd [edx], eax + // Return value is already in EAX register. +# else /* _MSC_VER */ + ACE_UNUSED_ARG (value); + ACE_UNUSED_ARG (rhs); + ACE_NOTSUP_RETURN (-1); +# endif /* _MSC_VER */ +#else /* __GNUC__ && ACE_HAS_PENTIUM */ + ACE_UNUSED_ARG (value); + ACE_UNUSED_ARG (rhs); + ACE_NOTSUP_RETURN (-1); +#endif /* __GNUC__ && ACE_HAS_PENTIUM */ } -#endif /*ACE_ATOMIC_OP */ +#if defined (_MSC_VER) +#pragma warning (pop) +#endif /* _MSC_VER */ + +#endif /* ACE_HAS_BUILTIN_ATOMIC_OP */ |