00001 #ifndef QT_ATOMICS_H
00002 #define QT_ATOMICS_H
00003
00004 #include <pthread.h>
00005 #include <qthread/common.h>
00006 #include <qthread/qthread.h>
00007
00008 #ifdef QTHREAD_NEEDS_IA64INTRIN
00009 # ifdef HAVE_IA64INTRIN_H
00010 # include <ia64intrin.h>
00011 # elif defined(HAVE_IA32INTRIN_H)
00012 # include <ia32intrin.h>
00013 # endif
00014 #endif
00015
00016 #if defined(__tile__)
00017 # include <tmc/sync.h>
00018 # define QTHREAD_FASTLOCK_INIT(x) tmc_sync_mutex_init(&(x))
00019 # define QTHREAD_FASTLOCK_INIT_PTR(x) tmc_sync_mutex_init((x))
00020 # define QTHREAD_FASTLOCK_LOCK(x) tmc_sync_mutex_lock((x))
00021 # define QTHREAD_FASTLOCK_UNLOCK(x) tmc_sync_mutex_unlock((x))
00022 # define QTHREAD_FASTLOCK_DESTROY(x)
00023 # define QTHREAD_FASTLOCK_DESTROY_PTR(x)
00024 # define QTHREAD_FASTLOCK_TYPE tmc_sync_mutex_t
00025 # define QTHREAD_FASTLOCK_INITIALIZER TMC_SYNC_MUTEX_INIT
00026 #elif defined(HAVE_PTHREAD_SPIN_INIT)
00027 # define QTHREAD_FASTLOCK_INIT(x) pthread_spin_init(&(x), PTHREAD_PROCESS_PRIVATE)
00028 # define QTHREAD_FASTLOCK_INIT_PTR(x) pthread_spin_init((x), PTHREAD_PROCESS_PRIVATE)
00029 # define QTHREAD_FASTLOCK_LOCK(x) pthread_spin_lock((x))
00030 # define QTHREAD_FASTLOCK_UNLOCK(x) pthread_spin_unlock((x))
00031 # define QTHREAD_FASTLOCK_DESTROY(x) pthread_spin_destroy(&(x))
00032 # define QTHREAD_FASTLOCK_DESTROY_PTR(x) pthread_spin_destroy((x))
00033 # define QTHREAD_FASTLOCK_TYPE pthread_spinlock_t
00034 # define QTHREAD_FASTLOCK_INITIALIZER PTHREAD_SPINLOCK_INITIALIZER
00035 #else
00036 # define QTHREAD_FASTLOCK_INIT(x) pthread_mutex_init(&(x), NULL)
00037 # define QTHREAD_FASTLOCK_INIT_PTR(x) pthread_mutex_init((x), NULL)
00038 # define QTHREAD_FASTLOCK_LOCK(x) pthread_mutex_lock((x))
00039 # define QTHREAD_FASTLOCK_UNLOCK(x) pthread_mutex_unlock((x))
00040 # define QTHREAD_FASTLOCK_DESTROY(x) pthread_mutex_destroy(&(x))
00041 # define QTHREAD_FASTLOCK_DESTROY_PTR(x) pthread_mutex_destroy((x))
00042 # define QTHREAD_FASTLOCK_TYPE pthread_mutex_t
00043 # define QTHREAD_FASTLOCK_INITIALIZER PTHREAD_MUTEX_INITIALIZER
00044 #endif
00045
00046 #ifdef QTHREAD_MUTEX_INCREMENT
00047 # define QTHREAD_CASLOCK(var) var; QTHREAD_FASTLOCK_TYPE var##_caslock
00048 # define QTHREAD_CASLOCK_INIT(var,i) var = i; QTHREAD_FASTLOCK_INIT(var##_caslock)
00049 # define QTHREAD_CASLOCK_DESTROY(var) QTHREAD_FASTLOCK_DESTROY(var##_caslock)
00050 # define QTHREAD_CASLOCK_READ(var) (void*)qt_cas_read_ui((volatile uintptr_t*)&(var), &(var##_caslock))
00051 # define QTHREAD_CASLOCK_READ_UI(var) qt_cas_read_ui((volatile uintptr_t*)&(var), &(var##_caslock))
00052 # define QT_CAS(var,oldv,newv) qt_cas((void*volatile*)&(var), (void*)(oldv), (void*)(newv), &(var##_caslock))
00053 static QINLINE void* qt_cas(void*volatile* const ptr, void* const oldv, void* const newv, QTHREAD_FASTLOCK_TYPE *lock)
00054 {
00055 void * ret;
00056 QTHREAD_FASTLOCK_LOCK(lock);
00057 ret = *ptr;
00058 if (*ptr == oldv) {
00059 *ptr = newv;
00060 }
00061 QTHREAD_FASTLOCK_UNLOCK(lock);
00062 return ret;
00063 }
00064 static QINLINE uintptr_t qt_cas_read_ui(volatile uintptr_t * const ptr, QTHREAD_FASTLOCK_TYPE *mutex)
00065 {
00066 uintptr_t ret;
00067 QTHREAD_FASTLOCK_LOCK(mutex);
00068 ret = *ptr;
00069 QTHREAD_FASTLOCK_UNLOCK(mutex);
00070 return ret;
00071 }
00072 #else
00073 # define QTHREAD_CASLOCK(var) (var)
00074 # define QTHREAD_CASLOCK2(var) (var) = NULL
00075 # define QTHREAD_CASLOCK_INIT(var,i) (var) = i
00076 # define QTHREAD_CASLOCK_DESTROY(var)
00077 # define QTHREAD_CASLOCK_READ(var) (var)
00078 # define QTHREAD_CASLOCK_READ_UI(var) (var)
00079 # define QT_CAS(var,oldv,newv) qt_cas((void*volatile*)&(var), (void*)(oldv), (void*)(newv))
00080 # ifdef QTHREAD_ATOMIC_CAS_PTR
00081 # define qt_cas(P,O,N) (void*)__sync_val_compare_and_swap((P),(O),(N))
00082 # else
00083 static QINLINE void* qt_cas(void*volatile* const ptr, void* const oldv, void* const newv)
00084 {
00085 # if defined(HAVE_GCC_INLINE_ASSEMBLY)
00086 # if (QTHREAD_ASSEMBLY_ARCH == QTHREAD_POWERPC32)
00087 void* result;
00088 __asm__ __volatile__ ("1:\n\t"
00089 "lwarx %0,0,%3\n\t"
00090 "cmpw %0,%1\n\t"
00091 "bne 2f\n\t"
00092 "stwcx. %2,0,%3\n\t"
00093 "bne- 1b\n"
00094 "2:"
00095 :"=&b" (result)
00096 :"r"(oldv), "r"(newv), "r"(ptr)
00097 :"cc", "memory");
00098 return result;
00099 # elif (QTHREAD_ASSEMBLY_ARCH == QTHREAD_POWERPC64)
00100 void* result;
00101 __asm__ __volatile__ ("1:\n\t"
00102 "ldarx %0,0,%3\n\t"
00103 "cmpw %0,%1\n\t"
00104 "bne 2f\n\t"
00105 "stdcx. %2,0,%3\n\t"
00106 "bne- 1b\n"
00107 "2:"
00108 :"=&b" (result)
00109 :"r"(oldv), "r"(newv), "r"(ptr)
00110 :"cc", "memory");
00111 return result;
00112 # elif (QTHREAD_ASSEMBLY_ARCH == QTHREAD_SPARCV9_32)
00113 void *nv = newv;
00114 __asm__ __volatile__
00115 ("cas [%1], %2, %0"
00116 : "=&r" (nv)
00117 : "r" (ptr), "r"(oldv)
00118 #if !defined(__SUNPRO_C) && !defined(__SUNPRO_CC)
00119 , "0"(nv)
00120 #endif
00121 : "cc", "memory");
00122 return nv;
00123 # elif (QTHREAD_ASSEMBLY_ARCH == QTHREAD_SPARCV9_64)
00124 void *nv = newv;
00125 __asm__ __volatile__
00126 ("casx [%1], %2, %0"
00127 : "=&r" (nv)
00128 : "r" (ptr), "r"(oldv)
00129 #if !defined(__SUNPRO_C) && !defined(__SUNPRO_CC)
00130 , "0"(nv)
00131 #endif
00132 : "cc", "memory");
00133 return nv;
00134 # elif (QTHREAD_ASSEMBLY_ARCH == QTHREAD_IA64)
00135 void ** retval;
00136 __asm__ __volatile__ ("mov ar.ccv=%0;;": :"rO" (oldv));
00137 __asm__ __volatile__ ("cmpxchg4.acq %0=[%1],%2,ar.ccv"
00138 :"=r"(retval)
00139 :"r"(ptr), "r"(newv)
00140 :"memory");
00141 return retval;
00142 # elif (QTHREAD_ASSEMBLY_ARCH == QTHREAD_AMD64) || (QTHREAD_ASSEMBLY_ARCH == QTHREAD_IA32)
00143 void ** retval;
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153 # if (QTHREAD_ASSEMBLY_ARCH == QTHREAD_AMD64) && defined(__PGI)
00154 __asm__ __volatile__ ("lock; cmpxchg %1,(%2)\n\t"
00155 "mov %%rax,(%0)"
00156 ::"r"(&retval),
00157 "r"(newv), "r" (ptr),
00158 "a"(oldv)
00159 :"cc","memory");
00160 # else
00161 __asm__ __volatile__ ("lock; cmpxchg %1,(%2)"
00162 : "=a"(retval)
00163 : "r"(newv), "r" (ptr),
00164 "a"(oldv)
00165 :"cc","memory");
00166 # endif
00167 return retval;
00168 # else
00169 # error "Don't have a qt_cas implementation for this architecture"
00170 # endif
00171 # else
00172 # error "CAS needs inline assembly OR __sync_val_compare_and_swap"
00173 # endif
00174 }
00175 # endif
00176 #endif
00177
00178 #endif