JackAtomic.h

00001 /*
00002 Copyright (C) 2004-2008 Grame  
00003 
00004 This program is free software; you can redistribute it and/or modify
00005 it under the terms of the GNU General Public License as published by
00006 the Free Software Foundation; either version 2 of the License, or
00007 (at your option) any later version.
00008 
00009 This program is distributed in the hope that it will be useful,
00010 but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 GNU General Public License for more details.
00013 
00014 You should have received a copy of the GNU General Public License
00015 along with this program; if not, write to the Free Software
00016 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00017 
00018 */
00019 
00020 #ifndef __JackAtomic__
00021 #define __JackAtomic__
00022 
00023 #include "JackTypes.h"
00024 
00025 #if defined(__APPLE__)
00026 
00027 #if defined(__ppc__) || defined(__ppc64__)
00028 
00029 static inline int CAS(register UInt32 value, register UInt32 newvalue, register volatile void* addr)
00030 {
00031     register int result;
00032     asm volatile (
00033         "# CAS                                  \n"
00034         "       lwarx   r0, 0, %1       \n"         // creates a reservation on addr
00035         "       cmpw    r0, %2          \n"                     //  test value at addr
00036         "       bne-    1f          \n"
00037         "       sync                    \n"         //  synchronize instructions
00038         "       stwcx.  %3, 0, %1       \n"         //  if the reservation is not altered
00039         //  stores the new value at addr
00040         "       bne-    1f          \n"
00041         "   li      %0, 1       \n"
00042         "       b               2f          \n"
00043         "1:                     \n"
00044         "   li      %0, 0       \n"
00045         "2:                     \n"
00046     : "=r" (result)
00047                 : "r" (addr), "r" (value), "r" (newvalue)
00048                 : "r0"
00049             );
00050     return result;
00051 }
00052 
00053 #endif
00054 
00055 #if defined(__i386__) || defined(__x86_64__)
00056 
00057 #ifdef __SMP__
00058 #       define LOCK "lock ; "
00059 #else
00060 #       define LOCK ""
00061 #endif
00062 
00063 static inline char CAS(volatile UInt32 value, UInt32 newvalue, volatile void* addr)
00064 {
00065     register char ret;
00066     __asm__ __volatile__ (
00067         "# CAS \n\t"
00068         LOCK "cmpxchg %2, (%1) \n\t"
00069         "sete %0               \n\t"
00070     : "=a" (ret)
00071                 : "c" (addr), "d" (newvalue), "a" (value)
00072             );
00073     return ret;
00074 }
00075 
00076 #endif
00077 
00078 #endif
00079 
00080 #ifdef __linux__
00081 
00082 #ifdef __PPC__
00083 
00084 static inline int CAS(register UInt32 value, register UInt32 newvalue, register volatile void* addr)
00085 {
00086     register int result;
00087     register UInt32 tmp;
00088     asm volatile (
00089         "# CAS                                  \n"
00090         "       lwarx   %4, 0, %1       \n"         // creates a reservation on addr
00091         "       cmpw    %4, %2          \n"        //  test value at addr
00092         "       bne-    1f          \n"
00093         "       sync                    \n"         //  synchronize instructions
00094         "       stwcx.  %3, 0, %1       \n"         //  if the reservation is not altered
00095         //  stores the new value at addr
00096         "       bne-    1f          \n"
00097         "   li      %0, 1       \n"
00098         "       b               2f          \n"
00099         "1:                     \n"
00100         "   li      %0, 0       \n"
00101         "2:                     \n"
00102     : "=r" (result)
00103                 : "r" (addr), "r" (value), "r" (newvalue), "r" (tmp)
00104             );
00105     return result;
00106 }
00107 
00108 #endif
00109 
00110 #if defined(__i386__) || defined(__x86_64__)
00111 
00112 #ifdef __SMP__
00113 #       define LOCK "lock ; "
00114 #else
00115 #       define LOCK ""
00116 #endif
00117 
00118 static inline char CAS(volatile UInt32 value, UInt32 newvalue, volatile void* addr)
00119 {
00120     register char ret;
00121     __asm__ __volatile__ (
00122         "# CAS \n\t"
00123         LOCK "cmpxchg %2, (%1) \n\t"
00124         "sete %0               \n\t"
00125     : "=a" (ret)
00126                 : "c" (addr), "d" (newvalue), "a" (value)
00127             );
00128     return ret;
00129 }
00130 
00131 #endif
00132 
00133 #endif
00134 
00135 #ifdef WIN32
00136 
00137 #ifdef __SMP__
00138 #       define LOCK lock
00139 #else
00140 #       define LOCK
00141 #endif
00142 
00143 #define inline __inline
00144 
00145 //----------------------------------------------------------------
00146 // CAS functions
00147 //----------------------------------------------------------------
00148 inline char CAS(volatile UInt32 value, UInt32 newvalue, volatile void * addr)
00149 {
00150     register char c;
00151     __asm {
00152         push    ebx
00153         push    esi
00154         mov     esi, addr
00155         mov     eax, value
00156         mov     ebx, newvalue
00157         LOCK cmpxchg dword ptr [esi], ebx
00158         sete    c
00159         pop     esi
00160         pop     ebx
00161     }
00162     return c;
00163 }
00164 
00165 #endif
00166 
00167 static inline long INC_ATOMIC(volatile SInt32* val)
00168 {
00169     SInt32 actual;
00170     do {
00171         actual = *val;
00172     } while (!CAS(actual, actual + 1, val));
00173     return actual;
00174 }
00175 
00176 static inline long DEC_ATOMIC(volatile SInt32* val)
00177 {
00178     SInt32 actual;
00179     do {
00180         actual = *val;
00181     } while (!CAS(actual, actual - 1, val));
00182     return actual;
00183 }
00184 
00185 #endif
00186 
00187 

Generated on Thu Feb 14 11:16:01 2008 for Jackdmp by  doxygen 1.5.1