00001
00002
00003
00004
00005
00006
00007
00008 #ifndef PIKE_CPULIB_H
00009 #define PIKE_CPULIB_H
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifdef PIKE_RUN_UNLOCKED
00019
00020 #define pike_atomic_fool_gcc(x) (*(volatile struct { int a[100]; } *)x)
00021
00022
00023
00024
00025
00026
00027 #define BEGIN_MEMORY_LOCK(ADDR) do { \
00028 PIKE_MUTEX_T *pike_mem_mutex=pike_memory_locks+ \
00029 ((unsigned long)(ADDR))%PIKE_MEM_HASH; \
00030 mt_lock(pike_mem_mutex)
00031
00032 #define END_MEMORY_LOCK() \
00033 mt_unlock(pike_mem_mutex); \
00034 }while(0)
00035
00036 #define pike_memlock(ADDR) do{ \
00037 PIKE_MUTEX_T *pike_mem_mutex=pike_memory_locks+ \
00038 ((unsigned long)(ADDR))%PIKE_MEM_HASH; \
00039 mt_lock(pike_mem_mutex) \
00040 }while(0)
00041
00042 #define pike_unmemlock(ADDR) do{ \
00043 PIKE_MUTEX_T *pike_mem_mutex=pike_memory_locks+ \
00044 ((unsigned long)(ADDR))%PIKE_MEM_HASH; \
00045 mt_unlock(pike_mem_mutex) \
00046 }while(0)
00047
00048 #define PIKE_NEED_MEMLOCK
00049
00050
00051 #if defined(__i386__) && defined(__GNUC__)
00052
00053
00054
00055
00056
00057
00058
00059
00060 #define PIKE_HAS_INC32
00061 static INLINE void pike_atomic_inc32(volatile INT32 *v)
00062 {
00063 __asm__ __volatile__("lock ; incl %0"
00064 :"=m" (pike_atomic_fool_gcc(v))
00065 :"m" (pike_atomic_fool_gcc(v))
00066 :"cc");
00067 }
00068
00069
00070 #define PIKE_HAS_DEC_AND_TEST32
00071 static INLINE int pike_atomic_dec_and_test32(INT32 *v)
00072 {
00073 unsigned char c;
00074
00075 __asm__ __volatile__("lock ; decl %0; setne %1"
00076 :"=m" (pike_atomic_fool_gcc(v)), "=qm" (c)
00077 :"m" (pike_atomic_fool_gcc(v))
00078 :"cc");
00079 return c;
00080 }
00081
00082 #define PIKE_HAS_COMPARE_AND_SWAP32
00083 static INLINE int
00084 pike_atomic_compare_and_swap32 (INT32 *p, INT32 oldval, INT32 newval)
00085 {
00086 char ret;
00087 INT32 readval;
00088
00089 __asm__ __volatile__ ("lock; cmpxchgl %3, %1; sete %0"
00090 : "=q" (ret), "=m" (*p), "=a" (readval)
00091 : "r" (newval), "m" (*p), "a" (oldval)
00092 : "cc", "memory");
00093 return ret;
00094 }
00095
00096
00097
00098 #define PIKE_HAS_COMPARE_AND_SWAP64
00099 static INLINE int
00100 pike_atomic_compare_and_swap64 (INT64 *p, INT64 oldval, INT64 newval)
00101 {
00102 char ret;
00103 #define HIGH(X) ((INT32 *)&(X))[1]
00104 #define LOW(X) ((INT32 *)&(X))[0]
00105
00106 #if 1
00107 INT32 t1, t2, t3;
00108
00109 #if 0
00110 __asm__ __volatile__ (
00111 "xchgl %%ebx, %%edi ;"
00112 "lock; cmpxchg8b (%%esi); sete %%al;"
00113 "movl %%edi, %%ebx; "
00114 "movb %%al, %0 "
00115 :"=q" (ret),
00116 "=a" (t1),"=d" (t2),"=D" (t3)
00117 :"S" (p),
00118 "1" (LOW(oldval)), "2" (HIGH(oldval)),
00119 "3" (LOW(newval)), "c" (HIGH(newval))
00120 :"cc", "memory");
00121 #else
00122 __asm__ __volatile__ (
00123 "xchgl %%ebx, %%edi ;"
00124 "lock; cmpxchg8b (%%esi); sete %%al;"
00125 "movl %%edi, %%ebx; "
00126 "movb %%al, %0 "
00127 :"=q" (ret),
00128 "=a" (t1),"=d" (t2),"=D" (t3)
00129 :"S" (p),
00130 "a" (LOW(oldval)), "d" (HIGH(oldval)),
00131 "D" (LOW(newval)), "c" (HIGH(newval))
00132 :"cc", "memory");
00133 #endif
00134
00135 #else
00136 INT32 readval;
00137
00138 __asm__ __volatile__ ("lock; cmpxchg8b (%1); sete %0"
00139 :"=q" (ret), "=m" (*p)
00140 :"r" (newval), "m" (*p),
00141 "a" (LOW(oldval)),"d" (HIGH(oldval)),
00142 "b" (LOW(newval)),"c" (HIGH(newval))
00143 : "cc", "memory");
00144 #endif
00145 return ret;
00146 }
00147
00148 #endif
00149
00150 #if defined(__ia64__) && defined(__GNUC__)
00151
00152 #define PIKE_HAS_COMPARE_AND_SWAP32
00153
00154 static INLINE int
00155 pike_atomic_compare_and_swap32 (INT32 *p, INT32 oldval, INT32 newval)
00156 {
00157 INT32 ret;
00158
00159 __asm__ __volatile__ ("mov ar.ccv = %1;\n"
00160 "\t;;\n"
00161 "\tcmpxchg4.rel.nta %0 = [%2], %3, ar.ccv"
00162 : "=r" (ret)
00163 : "r" (oldval), "r" (p), "r" (newval)
00164 : "memory", "ar.ccv");
00165 return ret == oldval;
00166 }
00167
00168 #endif
00169
00170 #if defined(_M_IA64)
00171
00172 #define PIKE_HAS_COMPARE_AND_SWAP32
00173
00174 static INLINE int
00175 pike_atomic_compare_and_swap32 (INT32 *p, INT32 oldval, INT32 newval)
00176 {
00177 return _InterlockedCompareExchange(p, newval, oldval) == oldval;
00178 }
00179
00180 #endif
00181
00182 #if defined(__sparc_v9__) && defined(__GNUC__)
00183
00184 #define PIKE_HAS_COMPARE_AND_SWAP32
00185
00186 static INLINE int
00187 pike_atomic_compare_and_swap32 (INT32 *p, INT32 oldval, INT32 newval)
00188 {
00189 __asm__ __volatile__ ("membar #LoadStore\n"
00190 "cas [%2], %3, %0"
00191 : "=r" (newval)
00192 : "0" (newval), "r" (p), "r" (oldval)
00193 : "memory");
00194 return newval == oldval;
00195 }
00196
00197 #endif
00198
00199 #if defined(__m68k__) && defined(__GNUC__)
00200
00201
00202 #define PIKE_HAS_COMPARE_AND_SWAP32
00203
00204 static INLINE int
00205 pike_atomic_compare_and_swap32 (INT32 *p, INT32 oldval, INT32 newval)
00206 {
00207 INT32 cmpval = oldval;
00208
00209
00210
00211
00212
00213
00214
00215 __asm__ __volatile__ ("casl %0, %3, %1;"
00216 : "=d" (oldval), "=m", (*p)
00217 : "0" (oldval), "d" (newval), "0" (p)
00218 : "memory");
00219 return oldval == cmpval;
00220 }
00221
00222 #endif
00223
00224
00225
00226
00227
00228
00229
00230 #ifndef PIKE_HAS_COMPARE_AND_SWAP32
00231
00232 #define PIKE_HAS_COMPARE_AND_SWAP32
00233 #undef PIKE_NEED_MEMLOCK
00234 #define PIKE_NEED_MEMLOCK
00235
00236 #include "threads.h"
00237
00238 static INLINE int
00239 pike_atomic_compare_and_swap32 (INT32 *p, INT32 oldval, INT32 newval)
00240 {
00241 int ret;
00242 BEGIN_MEMORY_LOCK(p);
00243 if(ret == (*p == oldval)) *p=newval;
00244 END_MEMORY_LOCK();
00245 return ret;
00246 }
00247
00248
00249 #ifndef PIKE_HAS_INC32
00250 #define PIKE_HAS_INC32
00251 static INLINE void pike_atomic_inc32(INT32 *ref)
00252 {
00253 BEGIN_MEMORY_LOCK(p);
00254 ref++;
00255 END_MEMORY_LOCK();
00256 }
00257 #endif
00258
00259 #ifndef PIKE_HAS_DEC_AND_TEST32
00260 #define PIKE_HAS_DEC_AND_TEST32
00261 static INLINE int pike_atomic_dec_and_test32(INT32 *ref)
00262 {
00263 INT32 ret;
00264 BEGIN_MEMORY_LOCK(p);
00265 ret=--ref;
00266 END_MEMORY_LOCK();
00267 return ret;
00268 }
00269 #endif
00270
00271
00272
00273 #ifndef PIKE_HAS_SWAP32
00274 #define PIKE_HAS_SWAP32
00275 static INLINE INT32 pike_atomic_swap32(INT32 *addr, INT32 newval)
00276 {
00277 INT32 ret;
00278 BEGIN_MEMORY_LOCK(p);
00279 ret=*addr;
00280 *addr=newval;
00281 END_MEMORY_LOCK();
00282 return ret;
00283 }
00284 #endif
00285
00286 #endif
00287
00288 #if !defined(PIKE_HAS_COMPARE_AND_SWAP64) && defined(INT64)
00289
00290 #define PIKE_HAS_COMPARE_AND_SWAP64
00291 #undef PIKE_NEED_MEMLOCK
00292 #define PIKE_NEED_MEMLOCK
00293
00294 #include "threads.h"
00295
00296 static INLINE int
00297 pike_atomic_compare_and_swap64 (INT64 *p, INT64 oldval, INT64 newval)
00298 {
00299 int ret;
00300 BEGIN_MEMORY_LOCK(p);
00301 if(ret == (*p == oldval)) *p=newval;
00302 END_MEMORY_LOCK();
00303 return ret;
00304 }
00305
00306
00307 #ifndef PIKE_HAS_SWAP64
00308 #define PIKE_HAS_SWAP64
00309 static INLINE INT64 pike_atomic_swap64(INT64 *addr, INT64 newval)
00310 {
00311 INT64 ret;
00312 BEGIN_MEMORY_LOCK(p);
00313 ret=*addr;
00314 *addr=newval;
00315 END_MEMORY_LOCK();
00316 return ret;
00317 }
00318 #endif
00319
00320
00321 #ifndef PIKE_HAS_SET64
00322 #define PIKE_HAS_SET64
00323 static INLINE void pike_atomic_set64(INT64 *addr, INT64 newval)
00324 {
00325 BEGIN_MEMORY_LOCK(p);
00326 *addr=newval;
00327 END_MEMORY_LOCK();
00328 }
00329 #endif
00330
00331 #ifndef PIKE_HAS_GET64
00332 #define PIKE_HAS_GET64
00333 static INLINE INT64 pike_atomic_get64(INT64 *addr)
00334 {
00335 INT64 ret;
00336 BEGIN_MEMORY_LOCK(p);
00337 ret=*addr;
00338 END_MEMORY_LOCK();
00339 return ret;
00340 }
00341 #endif
00342
00343
00344 #endif
00345
00346
00347
00348
00349
00350
00351
00352
00353 #if defined(PIKE_HAS_COMPARE_AND_SWAP32) && !defined(PIKE_HAS_INC32)
00354 #define PIKE_HAS_INC32
00355 static INLINE void pike_atomic_inc32(INT32 *ref)
00356 {
00357 INT32 oldrefs;
00358 do
00359 oldrefs=*ref;
00360 while(! pike_atomic_compare_and_swap32(ref, oldrefs, oldrefs+1));
00361 }
00362 #endif
00363
00364
00365 #if defined(PIKE_HAS_COMPARE_AND_SWAP32) && !defined(PIKE_HAS_DEC_AND_TEST32)
00366 #define PIKE_HAS_DEC_AND_TEST32
00367 static INLINE int pike_atomic_dec_and_test32(INT32 *ref)
00368 {
00369 INT32 oldrefs;
00370 do
00371 oldrefs=*ref;
00372 while(! pike_atomic_compare_and_swap32(ref, oldrefs, oldrefs-1));
00373 return oldrefs-1;
00374 }
00375 #endif
00376
00377
00378 #if defined(PIKE_HAS_COMPARE_AND_SWAP32) && !defined(PIKE_HAS_SWAP32)
00379 #define PIKE_HAS_SWAP32
00380 static INLINE INT32 pike_atomic_swap32(INT32 *addr, INT32 newval)
00381 {
00382 INT32 ret;
00383 do
00384 {
00385 ret=*addr;
00386 }while(!pike_atomic_compare_and_swap32(addr, ret, newval));
00387 return ret;
00388 }
00389 #endif
00390
00391
00392 #if defined(PIKE_HAS_COMPARE_AND_SWAP64) && !defined(PIKE_HAS_SWAP64)
00393 #define PIKE_HAS_SWAP64
00394 static INLINE INT64 pike_atomic_swap64(INT64 *addr, INT64 newval)
00395 {
00396 INT64 ret;
00397 do
00398 {
00399 ret=*addr;
00400 }while(!pike_atomic_compare_and_swap64(addr, ret, newval));
00401 return ret;
00402 }
00403 #endif
00404
00405
00406
00407 #if defined(PIKE_HAS_SWAP64) && !defined(PIKE_HAS_SET64)
00408 #define PIKE_HAS_SET64
00409 static INLINE void pike_atomic_set64(INT64 *addr, INT64 newval)
00410 {
00411 pike_atomic_swap64(addr, newval);
00412 }
00413 #endif
00414
00415 #if defined(PIKE_HAS_COMPARE_AND_SWAP64) && !defined(PIKE_HAS_GET64)
00416 #define PIKE_HAS_GET64
00417 static INLINE INT64 pike_atomic_get64(INT64 *addr)
00418 {
00419 INT64 ret;
00420 do
00421 {
00422 ret=*addr;
00423 }while(!pike_atomic_compare_and_swap64(addr, ret, ret));
00424 return ret;
00425 }
00426 #endif
00427
00428
00429
00430 #endif
00431
00432 #ifdef PIKE_NEED_MEMLOCK
00433 extern void init_pike_cpulib(void);
00434 #else
00435 #define init_pike_cpulib()
00436 #endif
00437
00438 #endif