00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifndef AMINO_UTIL_X86_H
00018 #define AMINO_UTIL_X86_H
00019
00020 const int CACHE_PER_CORE=512000;
00021 const int CACHE_LINE_SIZE=64;
00022
00023 #define LOCK "lock;"
00024
00025
00026 #define compiler_barrier() __asm__ __volatile__ ("":::"memory")
00027
00035 #define LFENCE __asm__ __volatile__ ("lfence":::"memory")
00036 #define SFENCE __asm__ __volatile__ ("sfence":::"memory")
00037 #define CC_FENCE __asm__ __volatile__ ("mfence":::"memory")
00038
00039 #if defined(BIT32)
00040 #define SC_FENCE __asm__ __volatile__ ("mfence":::"memory")
00041 #elif defined(BIT64)
00042 #define SC_FENCE __asm__ __volatile__ (LOCK "addl $0, 0(%%rsp)":::"memory")
00043 #endif
00044
00045
00046 inline int getProcessNum(){
00047
00048 return 8;
00049 }
00050
00076 inline bool cas(volatile void* address, void* oldV_a, unsigned long newV, int size)
00077 {
00078
00079 bool ret;
00080 switch(size){
00081 case 1:
00082 {
00083 unsigned char* addr = (unsigned char*)address;
00084 unsigned char* oldV_addr = (unsigned char*)oldV_a;
00085 __asm__ __volatile__(
00086 LOCK "cmpxchgb %b3, %2; setz %0;\n"
00087 : "=q"(ret), "=a"(*(oldV_addr)), "=m"(*(addr))
00088 : "c" (newV), "1"(*(oldV_addr))
00089 : "memory", "cc");
00090 return ret;
00091 }
00092 case 2:
00093 {
00094 unsigned short* addr = (unsigned short*)address;
00095 unsigned short* oldV_addr = (unsigned short*)oldV_a;
00096 __asm__ __volatile__(
00097 LOCK "cmpxchgw %w3, %2; setz %0;\n"
00098 : "=q"(ret), "=a"(*(oldV_addr)), "=m"(*(addr))
00099 : "r" (newV), "1"(*(oldV_addr))
00100 : "memory", "cc");
00101 return ret;
00102 }
00103 #if defined(BIT32)
00104 case 4:
00105 {
00106 unsigned long* addr = (unsigned long*)address;
00107 unsigned long* oldV_addr = (unsigned long*)oldV_a;
00108 __asm__ __volatile__(
00109 LOCK "cmpxchgl %3, %2; setz %0;\n"
00110 : "=q"(ret), "=a"(*(oldV_addr)), "=m"(*(addr))
00111 : "r" (newV), "1"(*(oldV_addr))
00112 : "memory", "cc");
00113 return ret;
00114 }
00115 #elif defined(BIT64)
00116 case 4:
00117 {
00118 unsigned int* addr = (unsigned int*)address;
00119 unsigned int* oldV_addr = (unsigned int*)oldV_a;
00120 __asm__ __volatile__(
00121 LOCK "cmpxchgl %k3, %2; setz %0;\n"
00122 : "=q"(ret), "=a"(*(oldV_addr)), "=m"(*(addr))
00123 : "r" (newV), "1"(*(oldV_addr))
00124 : "memory", "cc");
00125 return ret;
00126 }
00127 case 8:
00128 {
00129 unsigned long* addr = (unsigned long*)address;
00130 unsigned long* oldV_addr = (unsigned long*)oldV_a;
00131 __asm__ __volatile__(
00132 LOCK "cmpxchgq %3, %2; setz %0;\n"
00133 : "=q"(ret), "=a"(*(oldV_addr)), "=m"(*(addr))
00134 : "r" (newV), "1"(*(oldV_addr))
00135 : "memory", "cc");
00136 return ret;
00137 }
00138 #endif
00139 }
00140 return false;
00141 }
00142
00158 inline bool casd(volatile void *ptr, void *old_addr, const void * new_v) {
00159 unsigned long * old_addr_long = (unsigned long *) old_addr;
00160 const unsigned long * new_v_long = (const unsigned long *) new_v;
00161 bool ret;
00162 #if defined(BIT64)
00163 __asm__ __volatile__(
00164 "lock\n\t"
00165 "cmpxchg16b %5\n\t"
00166 "setz %0\n"
00167 : "=b"(ret), "=d"(old_addr_long[1]), "=a"(old_addr_long[0])
00168 : "0"(new_v_long[0]),
00169 "c"(new_v_long[1]),
00170 "m"(*(long *)ptr),
00171 "1"(old_addr_long[1]),
00172 "2"(old_addr_long[0])
00173 : "memory", "cc");
00174 #else
00175 #ifdef __PIC__
00176
00181 __asm__ __volatile__(
00182 "push %%ebx \n\t"
00183 "movl %3, %%ebx \n\t"
00184 "lock \n\t"
00185 "cmpxchg8b %5 \n\t"
00186 "setz %0 \n\t"
00187 "popl %%ebx \n\t"
00188 : "=q"(ret), "=d"(old_addr_long[1]), "=a"(old_addr_long[0])
00189 : "m"(new_v_long[0]),
00190 "c"(new_v_long[1]),
00191 "m"(*((long*)(ptr))),
00192 "1"(old_addr_long[1]),
00193 "2"(old_addr_long[0])
00194 : "memory", "cc");
00195 #else
00196 __asm__ __volatile__(
00197 "lock \n\t"
00198 "cmpxchg8b %5 \n\t"
00199 "setz %0 \n\t"
00200 : "=b"(ret), "=d"(old_addr_long[1]), "=a"(old_addr_long[0])
00201 : "0"(new_v_long[0]),
00202 "c"(new_v_long[1]),
00203 "m"(*((long*)(ptr))),
00204 "1"(old_addr_long[1]),
00205 "2"(old_addr_long[0])
00206 : "memory", "cc");
00207 #endif //__PIC__
00208 #endif //BIT64
00209 return ret;
00210 }
00211
00220 inline unsigned long xchg(volatile void * ptr, unsigned long v, int size)
00221 {
00222 switch (size) {
00223 case 1:
00224 {
00225 unsigned char* addr = (unsigned char*)ptr;
00226 __asm__ __volatile__("xchgb %b0,%1"
00227 :"=q" (v)
00228 :"m" (*addr), "0" (v)
00229 :"memory");
00230 break;
00231 }
00232 case 2:
00233 {
00234 unsigned short* addr = (unsigned short*)ptr;
00235 __asm__ __volatile__("xchgw %w0,%1"
00236 :"=r" (v)
00237 :"m" (*addr), "0" (v)
00238 :"memory");
00239 break;
00240 }
00241 #if defined(__i386__)
00242 case 4:
00243 {
00244 unsigned long* addr = (unsigned long*)ptr;
00245 __asm__ __volatile__("xchgl %0,%1"
00246 :"=r" (v)
00247 :"m" (*addr), "0" (v)
00248 :"memory");
00249 break;
00250 }
00251 #elif defined(__x86_64__)
00252 case 4:
00253 {
00254 unsigned int* addr = (unsigned int*)ptr;
00255 __asm__ __volatile__("xchgl %k0,%1"
00256 :"=r" (v)
00257 :"m" (*addr), "0" (v)
00258 :"memory");
00259 break;
00260 }
00261 case 8:
00262 {
00263 unsigned long* addr = (unsigned long*)ptr;
00264 __asm__ __volatile__("xchgq %0,%1"
00265 :"=r" (v)
00266 :"m" (*addr), "0" (v)
00267 :"memory");
00268 break;
00269 }
00270 #endif
00271 }
00272 return v;
00273 }
00274 #endif