JackAtomic.h

00001 /*
00002 Copyright (C) 2004-2006 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 typedef unsigned short UInt16;
00024 typedef unsigned long UInt32;
00025 typedef long SInt32;
00026 #ifdef WIN32
00027         #include <windows.h>
00028 
00029 typedef ULONGLONG UInt64;
00030 #else
00031 
00032 typedef unsigned long long UInt64;
00033 #endif
00034 
00035 #if defined(__APPLE__)
00036 
00037 #if defined(__ppc__)
00038 
00039 static inline int CAS(register UInt32 value, register UInt32 newvalue, register volatile void* addr)
00040 {
00041     register int result;
00042     asm volatile (
00043         "# CAS                                  \n"
00044         "       lwarx   r0, 0, %1       \n"         // creates a reservation on addr
00045         "       cmpw    r0, %2          \n"                     //  test value at addr
00046         "       bne-    1f          \n"
00047         "       sync                    \n"         //  synchronize instructions
00048         "       stwcx.  %3, 0, %1       \n"         //  if the reservation is not altered
00049         //  stores the new value at addr
00050         "       bne-    1f          \n"
00051         "   li      %0, 1       \n"
00052         "       b               2f          \n"
00053         "1:                     \n"
00054         "   li      %0, 0       \n"
00055         "2:                     \n"
00056     : "=r" (result)
00057                 : "r" (addr), "r" (value), "r" (newvalue)
00058                 : "r0"
00059             );
00060     return result;
00061 }
00062 
00063 #endif
00064 
00065 #if defined(__i386__) || defined(__x86_64__)
00066 
00067 #ifdef __SMP__
00068 #       define LOCK "lock ; "
00069 #else
00070 #       define LOCK ""
00071 #endif
00072 
00073 static inline char CAS(volatile UInt32 value, UInt32 newvalue, volatile void* addr)
00074 {
00075     register char ret;
00076     __asm__ __volatile__ (
00077         "# CAS \n\t"
00078         LOCK "cmpxchg %2, (%1) \n\t"
00079         "sete %0               \n\t"
00080     : "=a" (ret)
00081                 : "c" (addr), "d" (newvalue), "a" (value)
00082             );
00083     return ret;
00084 }
00085 
00086 #endif
00087 
00088 #endif
00089 
00090 #ifdef __linux__
00091 
00092 #ifdef __PPC__
00093 
00094 static inline int CAS(register UInt32 value, register UInt32 newvalue, register volatile void* addr)
00095 {
00096     register int result;
00097     register UInt32 tmp;
00098     asm volatile (
00099         "# CAS                                  \n"
00100         "       lwarx   %4, 0, %1       \n"         // creates a reservation on addr
00101         "       cmpw    %4, %2          \n"        //  test value at addr
00102         "       bne-    1f          \n"
00103         "       sync                    \n"         //  synchronize instructions
00104         "       stwcx.  %3, 0, %1       \n"         //  if the reservation is not altered
00105         //  stores the new value at addr
00106         "       bne-    1f          \n"
00107         "   li      %0, 1       \n"
00108         "       b               2f          \n"
00109         "1:                     \n"
00110         "   li      %0, 0       \n"
00111         "2:                     \n"
00112     : "=r" (result)
00113                 : "r" (addr), "r" (value), "r" (newvalue), "r" (tmp)
00114             );
00115     return result;
00116 }
00117 
00118 #endif
00119 
00120 #if defined(__i386__) || defined(__x86_64__)
00121 
00122 #ifdef __SMP__
00123 #       define LOCK "lock ; "
00124 #else
00125 #       define LOCK ""
00126 #endif
00127 
00128 static inline char CAS(volatile UInt32 value, UInt32 newvalue, volatile void* addr)
00129 {
00130     register char ret;
00131     __asm__ __volatile__ (
00132         "# CAS \n\t"
00133         LOCK "cmpxchg %2, (%1) \n\t"
00134         "sete %0               \n\t"
00135     : "=a" (ret)
00136                 : "c" (addr), "d" (newvalue), "a" (value)
00137             );
00138     return ret;
00139 }
00140 
00141 #endif
00142 
00143 #endif
00144 
00145 #ifdef WIN32
00146 
00147 #ifdef __SMP__
00148 #       define LOCK lock
00149 #else
00150 #       define LOCK
00151 #endif
00152 
00153 #define inline __inline
00154 
00155 //----------------------------------------------------------------
00156 // CAS functions
00157 //----------------------------------------------------------------
00158 inline char CAS (volatile UInt32 value, UInt32 newvalue, volatile void * addr)
00159 {
00160     register char c;
00161     __asm {
00162         push    ebx
00163         push    esi
00164         mov     esi, addr
00165         mov     eax, value
00166         mov     ebx, newvalue
00167         LOCK cmpxchg dword ptr [esi], ebx
00168         sete    c
00169         pop     esi
00170         pop     ebx
00171     }
00172     return c;
00173 }
00174 
00175 #endif
00176 
00177 static inline long INC_ATOMIC(volatile SInt32* val)
00178 {
00179     SInt32 actual;
00180     do {
00181         actual = *val;
00182     } while (!CAS(actual, actual + 1, val));
00183     return actual;
00184 }
00185 
00186 static inline long DEC_ATOMIC(volatile SInt32* val)
00187 {
00188     SInt32 actual;
00189     do {
00190         actual = *val;
00191     } while (!CAS(actual, actual - 1, val));
00192     return actual;
00193 }
00194 
00195 #endif
00196 
00197 

Generated on Wed Jan 10 11:42:43 2007 for Jackdmp by  doxygen 1.4.5