00001 #include "ace_pch.h"
00002
00003
00004 #include "ace/Atomic_Op.h"
00005 #include "ace/OS.h"
00006
00007 ACE_RCSID(ace, Atomic_Op, "$Id: Atomic_Op.cpp,v 1.1.1.1.2.1 2003/03/13 19:44:20 chad Exp $")
00008
00009 #if !defined (__ACE_INLINE__)
00010 #include "ace/Atomic_Op.i"
00011 #endif
00012
00013 #if defined (ACE_HAS_BUILTIN_ATOMIC_OP)
00014
00015 long (*ACE_Atomic_Op<ACE_Thread_Mutex, long>::increment_fn_) (volatile long *) = 0;
00016 long (*ACE_Atomic_Op<ACE_Thread_Mutex, long>::decrement_fn_) (volatile long *) = 0;
00017 long (*ACE_Atomic_Op<ACE_Thread_Mutex, long>::exchange_add_fn_) (volatile long *, long) = 0;
00018
00019 void
00020 ACE_Atomic_Op<ACE_Thread_Mutex, long>::init_functions (void)
00021 {
00022 if (ACE_OS::num_processors () == 1)
00023 {
00024 increment_fn_ = single_cpu_increment;
00025 decrement_fn_ = single_cpu_decrement;
00026 exchange_add_fn_ = single_cpu_exchange_add;
00027 }
00028 else
00029 {
00030 increment_fn_ = multi_cpu_increment;
00031 decrement_fn_ = multi_cpu_decrement;
00032 exchange_add_fn_ = multi_cpu_exchange_add;
00033 }
00034 }
00035
00036 void
00037 ACE_Atomic_Op<ACE_Thread_Mutex, long>::dump (void) const
00038 {
00039 ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
00040 ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
00041 }
00042
00043 #if defined (_MSC_VER)
00044
00045
00046 #pragma warning (push)
00047 #pragma warning (disable: 4035)
00048 #endif
00049
00050 long
00051 ACE_Atomic_Op<ACE_Thread_Mutex, long>::single_cpu_increment (volatile long *value)
00052 {
00053 #if defined (__GNUC__) && defined (ACE_HAS_PENTIUM)
00054 long tmp = 1;
00055 unsigned long addr = ACE_reinterpret_cast (unsigned long, value);
00056 asm( "xadd %0, (%1)" : "+r"(tmp) : "r"(addr) );
00057 return tmp + 1;
00058 #else
00059 ACE_UNUSED_ARG (value);
00060 ACE_NOTSUP_RETURN (-1);
00061 #endif
00062 }
00063
00064 long
00065 ACE_Atomic_Op<ACE_Thread_Mutex, long>::single_cpu_decrement (volatile long *value)
00066 {
00067 #if defined (__GNUC__) && defined (ACE_HAS_PENTIUM)
00068 long tmp = -1;
00069 unsigned long addr = ACE_reinterpret_cast (unsigned long, value);
00070 asm( "xadd %0, (%1)" : "+r"(tmp) : "r"(addr) );
00071 return tmp - 1;
00072 #else
00073 ACE_UNUSED_ARG (value);
00074 ACE_NOTSUP_RETURN (-1);
00075 #endif
00076 }
00077
00078 long
00079 ACE_Atomic_Op<ACE_Thread_Mutex, long>::single_cpu_exchange_add (volatile long *value,
00080 long rhs)
00081 {
00082 #if defined (__GNUC__) && defined (ACE_HAS_PENTIUM)
00083 unsigned long addr = ACE_reinterpret_cast (unsigned long, value);
00084 asm( "xadd %0, (%1)" : "+r"(rhs) : "r"(addr) );
00085 return rhs;
00086 #elif defined (WIN32) && !defined (ACE_HAS_INTERLOCKED_EXCHANGEADD)
00087 # if defined (_MSC_VER)
00088 __asm
00089 {
00090 mov eax, rhs
00091 mov edx, value
00092 xadd [edx], eax
00093 }
00094
00095 # elif defined (__BORLANDC__)
00096 _EAX = rhs;
00097 _EDX = ACE_reinterpret_cast (unsigned long, value);
00098 __emit__(0x0F, 0xC1, 0x02);
00099
00100 # else
00101 ACE_UNUSED_ARG (value);
00102 ACE_UNUSED_ARG (rhs);
00103 ACE_NOTSUP_RETURN (-1);
00104 # endif
00105 #else
00106 ACE_UNUSED_ARG (value);
00107 ACE_UNUSED_ARG (rhs);
00108 ACE_NOTSUP_RETURN (-1);
00109 #endif
00110 }
00111
00112 long
00113 ACE_Atomic_Op<ACE_Thread_Mutex, long>::multi_cpu_increment (volatile long *value)
00114 {
00115 #if defined (__GNUC__) && defined (ACE_HAS_PENTIUM)
00116 long tmp = 1;
00117 unsigned long addr = ACE_reinterpret_cast (unsigned long, value);
00118 asm( "lock ; xadd %0, (%1)" : "+r"(tmp) : "r"(addr) );
00119 return tmp + 1;
00120 #else
00121 ACE_UNUSED_ARG (value);
00122 ACE_NOTSUP_RETURN (-1);
00123 #endif
00124 }
00125
00126 long
00127 ACE_Atomic_Op<ACE_Thread_Mutex, long>::multi_cpu_decrement (volatile long *value)
00128 {
00129 #if defined (__GNUC__) && defined (ACE_HAS_PENTIUM)
00130 long tmp = -1;
00131 unsigned long addr = ACE_reinterpret_cast (unsigned long, value);
00132 asm( "lock ; xadd %0, (%1)" : "+r"(tmp) : "r"(addr) );
00133 return tmp - 1;
00134 #else
00135 ACE_UNUSED_ARG (value);
00136 ACE_NOTSUP_RETURN (-1);
00137 #endif
00138 }
00139
00140 long
00141 ACE_Atomic_Op<ACE_Thread_Mutex, long>::multi_cpu_exchange_add (volatile long *value,
00142 long rhs)
00143 {
00144 #if defined (__GNUC__) && defined (ACE_HAS_PENTIUM)
00145 unsigned long addr = ACE_reinterpret_cast (unsigned long, value);
00146 asm( "lock ; xadd %0, (%1)" : "+r"(rhs) : "r"(addr) );
00147 return rhs;
00148 #elif defined (WIN32) && !defined (ACE_HAS_INTERLOCKED_EXCHANGEADD)
00149 # if defined (_MSC_VER)
00150 __asm
00151 {
00152 mov eax, rhs
00153 mov edx, value
00154 lock xadd [edx], eax
00155 }
00156
00157 # elif defined (__BORLANDC__)
00158 _EAX = rhs;
00159 _EDX = ACE_reinterpret_cast (unsigned long, value);
00160 __emit__(0xF0, 0x0F, 0xC1, 0x02);
00161
00162 # else
00163 ACE_UNUSED_ARG (value);
00164 ACE_UNUSED_ARG (rhs);
00165 ACE_NOTSUP_RETURN (-1);
00166 # endif
00167 #else
00168 ACE_UNUSED_ARG (value);
00169 ACE_UNUSED_ARG (rhs);
00170 ACE_NOTSUP_RETURN (-1);
00171 #endif
00172 }
00173
00174 #if defined (_MSC_VER)
00175 #pragma warning (pop)
00176 #endif
00177
00178 #endif
00179
00180 #if defined (ACE_HAS_THREADS)
00181 # if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION)
00182 # if !defined (ACE_HAS_BUILTIN_ATOMIC_OP)
00183 template class ACE_Atomic_Op<ACE_Thread_Mutex, long>;
00184 # endif
00185 template class ACE_Atomic_Op_Ex<ACE_Thread_Mutex, long>;
00186 # elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA)
00187 # if !defined (ACE_HAS_BUILTIN_ATOMIC_OP)
00188 # pragma instantiate ACE_Atomic_Op<ACE_Thread_Mutex, long>
00189 # endif
00190 # pragma instantiate ACE_Atomic_Op_Ex<ACE_Thread_Mutex, long>
00191 # endif
00192 #endif