00001
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
00013
00014 #if defined (ACE_HAS_BUILTIN_ATOMIC_OP)
00015
00016 namespace {
00017
00018 #if defined (_MSC_VER)
00019
00020
00021 #pragma warning (push)
00022 #pragma warning (disable: 4035)
00023 #endif
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
00034 ACE_UNUSED_ARG (value);
00035 ACE_NOTSUP_RETURN (-1);
00036 #endif
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
00048 ACE_UNUSED_ARG (value);
00049 ACE_NOTSUP_RETURN (-1);
00050 #endif
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
00061 ACE_UNUSED_ARG (value);
00062 ACE_UNUSED_ARG (rhs);
00063 ACE_NOTSUP_RETURN (-1);
00064 #endif
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
00083 # elif defined (__BORLANDC__)
00084 _EAX = rhs;
00085 _EDX = reinterpret_cast<unsigned long> (value);
00086 __emit__(0x0F, 0xC1, 0x02);
00087
00088 # else
00089 ACE_UNUSED_ARG (value);
00090 ACE_UNUSED_ARG (rhs);
00091 ACE_NOTSUP_RETURN (-1);
00092 # endif
00093 #else
00094 ACE_UNUSED_ARG (value);
00095 ACE_UNUSED_ARG (rhs);
00096 ACE_NOTSUP_RETURN (-1);
00097 #endif
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
00109 ACE_UNUSED_ARG (value);
00110 ACE_NOTSUP_RETURN (-1);
00111 #endif
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
00123 ACE_UNUSED_ARG (value);
00124 ACE_NOTSUP_RETURN (-1);
00125 #endif
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
00134 asm( "xchg %0, (%1)" : "+r"(rhs) : "r"(addr) );
00135 return rhs;
00136 #else
00137 ACE_UNUSED_ARG (value);
00138 ACE_UNUSED_ARG (rhs);
00139 ACE_NOTSUP_RETURN (-1);
00140 #endif
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
00159 # elif defined (__BORLANDC__)
00160 _EAX = rhs;
00161 _EDX = reinterpret_cast<unsigned long> (value);
00162 __emit__(0xF0, 0x0F, 0xC1, 0x02);
00163
00164 # else
00165 ACE_UNUSED_ARG (value);
00166 ACE_UNUSED_ARG (rhs);
00167 ACE_NOTSUP_RETURN (-1);
00168 # endif
00169 #else
00170 ACE_UNUSED_ARG (value);
00171 ACE_UNUSED_ARG (rhs);
00172 ACE_NOTSUP_RETURN (-1);
00173 #endif
00174 }
00175
00176 #if defined (_MSC_VER)
00177 #pragma warning (pop)
00178 #endif
00179
00180 }
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
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
00248 }
00249
00250 ACE_END_VERSIONED_NAMESPACE_DECL
00251
00252 #endif