Atomic_Op.cpp

Go to the documentation of this file.
00001 // Atomic_Op.cpp,v 4.14 2005/10/28 16:14:51 ossama Exp
00002 
00003 #include "ace/Atomic_Op.h"
00004 #include "ace/OS_NS_unistd.h"
00005 
00006 ACE_RCSID (ace,
00007            Atomic_Op,
00008            "Atomic_Op.cpp,v 4.14 2005/10/28 16:14:51 ossama Exp")
00009 
00010 #if !defined (__ACE_INLINE__)
00011 #include "ace/Atomic_Op.inl"
00012 #endif /* __ACE_INLINE__ */
00013 
00014 #if defined (ACE_HAS_BUILTIN_ATOMIC_OP)
00015 
00016 namespace {
00017 
00018 #if defined (_MSC_VER)
00019 // Disable "no return value" warning, as we will be putting
00020 // the return values directly into the EAX register.
00021 #pragma warning (push)
00022 #pragma warning (disable: 4035)
00023 #endif /* _MSC_VER */
00024 
00025 long
00026 single_cpu_increment (volatile long *value)
00027 {
00028 #if defined (__GNUC__) && (defined (ACE_HAS_PENTIUM) || defined (__amd64__))
00029   long tmp = 1;
00030   unsigned long addr = reinterpret_cast<unsigned long> (value);
00031   asm( "xadd %0, (%1)" : "+r"(tmp) : "r"(addr) );
00032   return tmp + 1;
00033 #else /* __GNUC__ && ACE_HAS_PENTIUM */
00034   ACE_UNUSED_ARG (value);
00035   ACE_NOTSUP_RETURN (-1);
00036 #endif /* __GNUC__ && ACE_HAS_PENTIUM */
00037 }
00038 
00039 long
00040 single_cpu_decrement (volatile long *value)
00041 {
00042 #if defined (__GNUC__) && (defined (ACE_HAS_PENTIUM) || defined (__amd64__))
00043   long tmp = -1;
00044   unsigned long addr = reinterpret_cast<unsigned long> (value);
00045   asm( "xadd %0, (%1)" : "+r"(tmp) : "r"(addr) );
00046   return tmp - 1;
00047 #else /* __GNUC__ && ACE_HAS_PENTIUM */
00048   ACE_UNUSED_ARG (value);
00049   ACE_NOTSUP_RETURN (-1);
00050 #endif /* __GNUC__ && ACE_HAS_PENTIUM */
00051 }
00052 
00053 long
00054 single_cpu_exchange (volatile long *value, long rhs)
00055 {
00056 #if defined (__GNUC__) && (defined (ACE_HAS_PENTIUM) || defined (__amd64__))
00057   unsigned long addr = reinterpret_cast<unsigned long> (value);
00058   asm( "xchg %0, (%1)" : "+r"(rhs) : "r"(addr) );
00059   return rhs;
00060 #else /* __GNUC__ && ACE_HAS_PENTIUM */
00061   ACE_UNUSED_ARG (value);
00062   ACE_UNUSED_ARG (rhs);
00063   ACE_NOTSUP_RETURN (-1);
00064 #endif /* __GNUC__ && ACE_HAS_PENTIUM */
00065 }
00066 
00067 long
00068 single_cpu_exchange_add (volatile long *value, long rhs)
00069 {
00070 #if defined (__GNUC__) && (defined (ACE_HAS_PENTIUM) || defined (__amd64__))
00071   unsigned long addr = reinterpret_cast<unsigned long> (value);
00072   asm( "xadd %0, (%1)" : "+r"(rhs) : "r"(addr) );
00073   return rhs;
00074 #elif defined (WIN32) && !defined (ACE_HAS_INTERLOCKED_EXCHANGEADD)
00075 # if defined (_MSC_VER)
00076   __asm
00077     {
00078       mov eax, rhs
00079       mov edx, value
00080       xadd [edx], eax
00081     }
00082   // Return value is already in EAX register.
00083 # elif defined (__BORLANDC__)
00084   _EAX = rhs;
00085   _EDX = reinterpret_cast<unsigned long> (value);
00086   __emit__(0x0F, 0xC1, 0x02); // xadd [edx], eax
00087   // Return value is already in EAX register.
00088 # else /* _MSC_VER */
00089   ACE_UNUSED_ARG (value);
00090   ACE_UNUSED_ARG (rhs);
00091   ACE_NOTSUP_RETURN (-1);
00092 # endif /* _MSC_VER */
00093 #else /* __GNUC__ && ACE_HAS_PENTIUM */
00094   ACE_UNUSED_ARG (value);
00095   ACE_UNUSED_ARG (rhs);
00096   ACE_NOTSUP_RETURN (-1);
00097 #endif /* __GNUC__ && ACE_HAS_PENTIUM */
00098 }
00099 
00100 long
00101 multi_cpu_increment (volatile long *value)
00102 {
00103 #if defined (__GNUC__) && (defined (ACE_HAS_PENTIUM) || defined (__amd64__))
00104   long tmp = 1;
00105   unsigned long addr = reinterpret_cast<unsigned long> (value);
00106   asm( "lock ; xadd %0, (%1)" : "+r"(tmp) : "r"(addr) );
00107   return tmp + 1;
00108 #else /* __GNUC__ && ACE_HAS_PENTIUM */
00109   ACE_UNUSED_ARG (value);
00110   ACE_NOTSUP_RETURN (-1);
00111 #endif /* __GNUC__ && ACE_HAS_PENTIUM */
00112 }
00113 
00114 long
00115 multi_cpu_decrement (volatile long *value)
00116 {
00117 #if defined (__GNUC__) && (defined (ACE_HAS_PENTIUM) || defined (__amd64__))
00118   long tmp = -1;
00119   unsigned long addr = reinterpret_cast<unsigned long> (value);
00120   asm( "lock ; xadd %0, (%1)" : "+r"(tmp) : "r"(addr) );
00121   return tmp - 1;
00122 #else /* __GNUC__ && ACE_HAS_PENTIUM */
00123   ACE_UNUSED_ARG (value);
00124   ACE_NOTSUP_RETURN (-1);
00125 #endif /* __GNUC__ && ACE_HAS_PENTIUM */
00126 }
00127 
00128 long
00129 multi_cpu_exchange (volatile long *value, long rhs)
00130 {
00131 #if defined (__GNUC__) && (defined (ACE_HAS_PENTIUM) || defined (__amd64__))
00132   unsigned long addr = reinterpret_cast<unsigned long> (value);
00133   // The XCHG instruction automatically follows LOCK semantics
00134   asm( "xchg %0, (%1)" : "+r"(rhs) : "r"(addr) );
00135   return rhs;
00136 #else /* __GNUC__ && ACE_HAS_PENTIUM */
00137   ACE_UNUSED_ARG (value);
00138   ACE_UNUSED_ARG (rhs);
00139   ACE_NOTSUP_RETURN (-1);
00140 #endif /* __GNUC__ && ACE_HAS_PENTIUM */
00141 }
00142 
00143 long
00144 multi_cpu_exchange_add (volatile long *value, long rhs)
00145 {
00146 #if defined (__GNUC__) && (defined (ACE_HAS_PENTIUM) || defined (__amd64__))
00147   unsigned long addr = reinterpret_cast<unsigned long> (value);
00148   asm( "lock ; xadd %0, (%1)" : "+r"(rhs) : "r"(addr) );
00149   return rhs;
00150 #elif defined (WIN32) && !defined (ACE_HAS_INTERLOCKED_EXCHANGEADD)
00151 # if defined (_MSC_VER)
00152   __asm
00153     {
00154       mov eax, rhs
00155       mov edx, value
00156       lock xadd [edx], eax
00157     }
00158   // Return value is already in EAX register.
00159 # elif defined (__BORLANDC__)
00160   _EAX = rhs;
00161   _EDX = reinterpret_cast<unsigned long> (value);
00162   __emit__(0xF0, 0x0F, 0xC1, 0x02); // lock xadd [edx], eax
00163   // Return value is already in EAX register.
00164 # else /* _MSC_VER */
00165   ACE_UNUSED_ARG (value);
00166   ACE_UNUSED_ARG (rhs);
00167   ACE_NOTSUP_RETURN (-1);
00168 # endif /* _MSC_VER */
00169 #else /* __GNUC__ && ACE_HAS_PENTIUM */
00170   ACE_UNUSED_ARG (value);
00171   ACE_UNUSED_ARG (rhs);
00172   ACE_NOTSUP_RETURN (-1);
00173 #endif /* __GNUC__ && ACE_HAS_PENTIUM */
00174 }
00175 
00176 #if defined (_MSC_VER)
00177 #pragma warning (pop)
00178 #endif /* _MSC_VER */
00179 
00180 } // end namespace
00181 
00182 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00183 
00184 long (*ACE_Atomic_Op<ACE_Thread_Mutex, long>::increment_fn_) (volatile long *) = 0;
00185 long (*ACE_Atomic_Op<ACE_Thread_Mutex, long>::decrement_fn_) (volatile long *) = 0;
00186 long (*ACE_Atomic_Op<ACE_Thread_Mutex, long>::exchange_fn_) (volatile long *, long) = 0;
00187 long (*ACE_Atomic_Op<ACE_Thread_Mutex, long>::exchange_add_fn_) (volatile long *, long) = 0;
00188 
00189 void
00190 ACE_Atomic_Op<ACE_Thread_Mutex, long>::init_functions (void)
00191 {
00192   if (ACE_OS::num_processors () == 1)
00193     {
00194       increment_fn_ = single_cpu_increment;
00195       decrement_fn_ = single_cpu_decrement;
00196       exchange_fn_ = single_cpu_exchange;
00197       exchange_add_fn_ = single_cpu_exchange_add;
00198     }
00199   else
00200     {
00201       increment_fn_ = multi_cpu_increment;
00202       decrement_fn_ = multi_cpu_decrement;
00203       exchange_fn_ = multi_cpu_exchange;
00204       exchange_add_fn_ = multi_cpu_exchange_add;
00205     }
00206 }
00207 
00208 void
00209 ACE_Atomic_Op<ACE_Thread_Mutex, long>::dump (void) const
00210 {
00211 #if defined (ACE_HAS_DUMP)
00212   ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
00213   ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
00214 #endif /* ACE_HAS_DUMP */
00215 }
00216 
00217 long (*ACE_Atomic_Op<ACE_Thread_Mutex, unsigned long>::increment_fn_) (volatile long *) = 0;
00218 long (*ACE_Atomic_Op<ACE_Thread_Mutex, unsigned long>::decrement_fn_) (volatile long *) = 0;
00219 long (*ACE_Atomic_Op<ACE_Thread_Mutex, unsigned long>::exchange_fn_) (volatile long *, long) = 0;
00220 long (*ACE_Atomic_Op<ACE_Thread_Mutex, unsigned long>::exchange_add_fn_) (volatile long *, long) = 0;
00221 
00222 void
00223 ACE_Atomic_Op<ACE_Thread_Mutex, unsigned long>::init_functions (void)
00224 {
00225   if (ACE_OS::num_processors () == 1)
00226     {
00227       increment_fn_ = single_cpu_increment;
00228       decrement_fn_ = single_cpu_decrement;
00229       exchange_fn_ = single_cpu_exchange;
00230       exchange_add_fn_ = single_cpu_exchange_add;
00231     }
00232   else
00233     {
00234       increment_fn_ = multi_cpu_increment;
00235       decrement_fn_ = multi_cpu_decrement;
00236       exchange_fn_ = multi_cpu_exchange;
00237       exchange_add_fn_ = multi_cpu_exchange_add;
00238     }
00239 }
00240 
00241 void
00242 ACE_Atomic_Op<ACE_Thread_Mutex, unsigned long>::dump (void) const
00243 {
00244 #if defined (ACE_HAS_DUMP)
00245   ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
00246   ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
00247 #endif /* ACE_HAS_DUMP */
00248 }
00249 
00250 ACE_END_VERSIONED_NAMESPACE_DECL
00251 
00252 #endif /* ACE_HAS_BUILTIN_ATOMIC_OP */

Generated on Thu Nov 9 09:41:46 2006 for ACE by doxygen 1.3.6