summaryrefslogtreecommitdiff
path: root/ace/Atomic_Op.cpp
diff options
context:
space:
mode:
authorchris <chris@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>2002-09-03 23:09:26 +0000
committerchris <chris@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>2002-09-03 23:09:26 +0000
commit8cddc9a06545cb99612875b7c9508fffeb5b6d03 (patch)
treee763aff3e70097db4ef86735f3ad4a9651bfaa5f /ace/Atomic_Op.cpp
parentba28132d4d2c430fabf8caf83676e56401271071 (diff)
downloadATCD-8cddc9a06545cb99612875b7c9508fffeb5b6d03.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.cpp192
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 */