Panda3D

atomicAdjustI386Impl.I

00001 // Filename: atomicAdjustI386Impl.I
00002 // Created by:  drose (01Apr06)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 
00016 ////////////////////////////////////////////////////////////////////
00017 //     Function: AtomicAdjustI386Impl::inc
00018 //       Access: Public, Static
00019 //  Description: Atomically increments the indicated variable.
00020 ////////////////////////////////////////////////////////////////////
00021 INLINE void AtomicAdjustI386Impl::
00022 inc(TVOLATILE AtomicAdjustI386Impl::Integer &var) {
00023 #ifdef _M_IX86
00024   // Windows case
00025   TVOLATILE Integer *var_ptr = &var;
00026   __asm {
00027     mov edx, var_ptr;
00028     lock inc dword ptr [edx];
00029   }
00030 #elif !defined(__EDG__)
00031   // GCC case
00032   __asm__ __volatile__("lock; incl %0"
00033                        :"=m" (var)
00034                        :"m" (&var));
00035 #endif  // __EDG__
00036 }
00037 
00038 ////////////////////////////////////////////////////////////////////
00039 //     Function: AtomicAdjustI386Impl::dec
00040 //       Access: Public, Static
00041 //  Description: Atomically decrements the indicated variable and
00042 //               returns true if the new value is nonzero, false if it
00043 //               is zero.
00044 ////////////////////////////////////////////////////////////////////
00045 INLINE bool AtomicAdjustI386Impl::
00046 dec(TVOLATILE AtomicAdjustI386Impl::Integer &var) {
00047   unsigned char c;
00048 #ifdef _M_IX86
00049   // Windows case
00050   TVOLATILE Integer *var_ptr = &var;
00051   __asm {
00052     mov edx, var_ptr;
00053     lock dec dword ptr [edx];
00054     sete c;
00055   }
00056 #elif !defined(__EDG__)
00057   // GCC case
00058   __asm__ __volatile__("lock; decl %0; sete %1"
00059                        :"=m" (var), "=qm" (c)
00060                        :"m" (&var) : "memory");
00061 #endif  // __EDG__
00062   return (c == 0);
00063 }
00064 
00065 ////////////////////////////////////////////////////////////////////
00066 //     Function: AtomicAdjustI386Impl::add
00067 //       Access: Public, Static
00068 //  Description: Atomically computes var += delta.  It is legal for
00069 //               delta to be negative.
00070 ////////////////////////////////////////////////////////////////////
00071 INLINE void AtomicAdjustI386Impl::
00072 add(TVOLATILE AtomicAdjustI386Impl::Integer &var, AtomicAdjustI386Impl::Integer delta) {
00073   Integer orig_value = var;
00074   while (compare_and_exchange(var, orig_value, orig_value + delta) != orig_value) {
00075     orig_value = var;
00076   }
00077 }
00078 
00079 ////////////////////////////////////////////////////////////////////
00080 //     Function: AtomicAdjustI386Impl::set
00081 //       Access: Public, Static
00082 //  Description: Atomically changes the indicated variable and
00083 //               returns the original value.
00084 ////////////////////////////////////////////////////////////////////
00085 INLINE AtomicAdjustI386Impl::Integer AtomicAdjustI386Impl::
00086 set(TVOLATILE AtomicAdjustI386Impl::Integer &var, AtomicAdjustI386Impl::Integer new_value) {
00087   Integer orig_value = var;
00088   var = new_value;
00089   return orig_value;
00090 }
00091 
00092 ////////////////////////////////////////////////////////////////////
00093 //     Function: AtomicAdjustI386Impl::get
00094 //       Access: Public, Static
00095 //  Description: Atomically retrieves the snapshot value of the
00096 //               indicated variable.  This is the only guaranteed safe
00097 //               way to retrieve the value that other threads might be
00098 //               asynchronously setting, incrementing, or decrementing
00099 //               (via other AtomicAjust methods).
00100 ////////////////////////////////////////////////////////////////////
00101 INLINE AtomicAdjustI386Impl::Integer AtomicAdjustI386Impl::
00102 get(const TVOLATILE AtomicAdjustI386Impl::Integer &var) {
00103   return var;
00104 }
00105 
00106 ////////////////////////////////////////////////////////////////////
00107 //     Function: AtomicAdjustI386Impl::set_ptr
00108 //       Access: Public, Static
00109 //  Description: Atomically changes the indicated variable and
00110 //               returns the original value.
00111 ////////////////////////////////////////////////////////////////////
00112 INLINE void *AtomicAdjustI386Impl::
00113 set_ptr(void * TVOLATILE &var, void *new_value) {
00114   void *orig_value = var;
00115   var = new_value;
00116   return orig_value;
00117 }
00118 
00119 ////////////////////////////////////////////////////////////////////
00120 //     Function: AtomicAdjustI386Impl::get_ptr
00121 //       Access: Public, Static
00122 //  Description: Atomically retrieves the snapshot value of the
00123 //               indicated variable.  This is the only guaranteed safe
00124 //               way to retrieve the value that other threads might be
00125 //               asynchronously setting, incrementing, or decrementing
00126 //               (via other AtomicAjust methods).
00127 ////////////////////////////////////////////////////////////////////
00128 INLINE void *AtomicAdjustI386Impl::
00129 get_ptr(void * const TVOLATILE &var) {
00130   return var;
00131 }
00132 
00133 ////////////////////////////////////////////////////////////////////
00134 //     Function: AtomicAdjustI386Impl::compare_and_exchange
00135 //       Access: Public, Static
00136 //  Description: Atomic compare and exchange.  
00137 //
00138 //               If mem is equal to old_value, store new_value in mem.
00139 //               In either case, return the original value of mem.
00140 //               The caller can test for success by comparing
00141 //               return_value == old_value.
00142 //
00143 //               The atomic function expressed in pseudo-code:
00144 //
00145 //                 orig_value = mem;
00146 //                 if (mem == old_value) {
00147 //                   mem = new_value;
00148 //                 }
00149 //                 return orig_value;
00150 //
00151 ////////////////////////////////////////////////////////////////////
00152 INLINE AtomicAdjustI386Impl::Integer AtomicAdjustI386Impl::
00153 compare_and_exchange(TVOLATILE AtomicAdjustI386Impl::Integer &mem, AtomicAdjustI386Impl::Integer old_value,
00154                      AtomicAdjustI386Impl::Integer new_value) {
00155   Integer prev;
00156 #ifdef _M_IX86
00157   // Windows case
00158   TVOLATILE Integer *mem_ptr = &mem;
00159   __asm {
00160     mov edx, mem_ptr;
00161     mov ecx, new_value;
00162     mov eax, old_value;
00163     lock cmpxchg dword ptr [edx], ecx;
00164     mov prev, eax;
00165   }
00166 #elif !defined(__EDG__)
00167   // GCC case
00168   __asm__ __volatile__("lock; cmpxchgl %1,%2"
00169                        : "=a"(prev)
00170                        : "r"(new_value), "m"(mem), "0"(old_value)
00171                        : "memory");
00172 #endif  // __EDG__
00173   return prev;
00174 }
00175 
00176 ////////////////////////////////////////////////////////////////////
00177 //     Function: AtomicAdjustI386Impl::compare_and_exchange_ptr
00178 //       Access: Public, Static
00179 //  Description: Atomic compare and exchange.  
00180 //
00181 //               As above, but works on pointers instead of integers.
00182 ////////////////////////////////////////////////////////////////////
00183 INLINE void *AtomicAdjustI386Impl::
00184 compare_and_exchange_ptr(void * TVOLATILE &mem, void *old_value,
00185                          void *new_value) {
00186   void *prev;
00187 #ifdef _M_IX86
00188   // Windows case
00189   void * TVOLATILE *mem_ptr = &mem;
00190   __asm {
00191     mov edx, mem_ptr;
00192     mov ecx, new_value;
00193     mov eax, old_value;
00194     lock cmpxchg dword ptr [edx], ecx;
00195     mov prev, eax;
00196   }
00197 #elif !defined(__EDG__)
00198   // GCC case
00199   __asm__ __volatile__("lock; cmpxchgl %1,%2"
00200                        : "=a"(prev)
00201                        : "r"(new_value), "m"(mem), "0"(old_value)
00202                        : "memory");
00203 #endif  // __EDG__
00204   return prev;
00205 }
 All Classes Functions Variables Enumerations