|
PAPI
5.0.1.0
|
00001 #ifndef _LINUX_LOCK_H 00002 #define _LINUX_LOCK_H 00003 00004 #include "mb.h" 00005 00006 /* Locking functions */ 00007 00008 #if defined(USE_PTHREAD_MUTEXES) 00009 00010 #include <pthread.h> 00011 00012 extern pthread_mutex_t _papi_hwd_lock_data[PAPI_MAX_LOCK]; 00013 00014 #define _papi_hwd_lock(lck) \ 00015 do \ 00016 { \ 00017 pthread_mutex_lock (&_papi_hwd_lock_data[lck]); \ 00018 } while(0) 00019 #define _papi_hwd_unlock(lck) \ 00020 do \ 00021 { \ 00022 pthread_mutex_unlock(&_papi_hwd_lock_data[lck]); \ 00023 } while(0) 00024 00025 00026 #else 00027 00028 extern volatile unsigned int _papi_hwd_lock_data[PAPI_MAX_LOCK]; 00029 #define MUTEX_OPEN 0 00030 #define MUTEX_CLOSED 1 00031 00032 /********/ 00033 /* ia64 */ 00034 /********/ 00035 00036 #if defined(__ia64__) 00037 #ifdef __INTEL_COMPILER 00038 #define _papi_hwd_lock(lck) { while(_InterlockedCompareExchange_acq(&_papi_hwd_lock_data[lck],MUTEX_CLOSED,MUTEX_OPEN) != MUTEX_OPEN) { ; } } 00039 #define _papi_hwd_unlock(lck) { _InterlockedExchange((volatile int *)&_papi_hwd_lock_data[lck], MUTEX_OPEN); } 00040 #else /* GCC */ 00041 #define _papi_hwd_lock(lck) \ 00042 { int res = 0; \ 00043 do { \ 00044 __asm__ __volatile__ ("mov ar.ccv=%0;;" :: "r"(MUTEX_OPEN)); \ 00045 __asm__ __volatile__ ("cmpxchg4.acq %0=[%1],%2,ar.ccv" : "=r"(res) : "r"(&_papi_hwd_lock_data[lck]), "r"(MUTEX_CLOSED) : "memory"); \ 00046 } while (res != MUTEX_OPEN); } 00047 00048 #define _papi_hwd_unlock(lck) { __asm__ __volatile__ ("st4.rel [%0]=%1" : : "r"(&_papi_hwd_lock_data[lck]), "r"(MUTEX_OPEN) : "memory"); } 00049 #endif 00050 00051 /***********/ 00052 /* x86 */ 00053 /***********/ 00054 00055 #elif defined(__i386__)||defined(__x86_64__) 00056 #define _papi_hwd_lock(lck) \ 00057 do \ 00058 { \ 00059 unsigned int res = 0; \ 00060 do { \ 00061 __asm__ __volatile__ ("lock ; " "cmpxchg %1,%2" : "=a"(res) : "q"(MUTEX_CLOSED), "m"(_papi_hwd_lock_data[lck]), "0"(MUTEX_OPEN) : "memory"); \ 00062 } while(res != (unsigned int)MUTEX_OPEN); \ 00063 } while(0) 00064 #define _papi_hwd_unlock(lck) \ 00065 do \ 00066 { \ 00067 unsigned int res = 0; \ 00068 __asm__ __volatile__ ("xchg %0,%1" : "=r"(res) : "m"(_papi_hwd_lock_data[lck]), "0"(MUTEX_OPEN) : "memory"); \ 00069 } while(0) 00070 00071 /***************/ 00072 /* power */ 00073 /***************/ 00074 00075 #elif defined(__powerpc__) 00076 00077 /* 00078 * These functions are slight modifications of the functions in 00079 * /usr/include/asm-ppc/system.h. 00080 * 00081 * We can't use the ones in system.h directly because they are defined 00082 * only when __KERNEL__ is defined. 00083 */ 00084 00085 static __inline__ unsigned long 00086 papi_xchg_u32( volatile void *p, unsigned long val ) 00087 { 00088 unsigned long prev; 00089 00090 __asm__ __volatile__( "\n\ 00091 sync \n\ 00092 1: lwarx %0,0,%2 \n\ 00093 stwcx. %3,0,%2 \n\ 00094 bne- 1b \n\ 00095 isync":"=&r"( prev ), "=m"( *( volatile unsigned long * ) p ) 00096 :"r"( p ), "r"( val ), 00097 "m"( *( volatile unsigned long * ) p ) 00098 :"cc", "memory" ); 00099 00100 return prev; 00101 } 00102 00103 #define _papi_hwd_lock(lck) \ 00104 do { \ 00105 unsigned int retval; \ 00106 do { \ 00107 retval = papi_xchg_u32(&_papi_hwd_lock_data[lck],MUTEX_CLOSED); \ 00108 } while(retval != (unsigned int)MUTEX_OPEN); \ 00109 } while(0) 00110 #define _papi_hwd_unlock(lck) \ 00111 do { \ 00112 unsigned int retval; \ 00113 retval = papi_xchg_u32(&_papi_hwd_lock_data[lck],MUTEX_OPEN); \ 00114 } while(0) 00115 00116 /*****************/ 00117 /* SPARC */ 00118 /*****************/ 00119 00120 #elif defined(__sparc__) 00121 static inline void 00122 __raw_spin_lock( volatile unsigned int *lock ) 00123 { 00124 __asm__ __volatile__( "\n1:\n\t" "ldstub [%0], %%g2\n\t" "orcc %%g2, 0x0, %%g0\n\t" "bne,a 2f\n\t" " ldub [%0], %%g2\n\t" ".subsection 2\n" "2:\n\t" "orcc %%g2, 0x0, %%g0\n\t" "bne,a 2b\n\t" " ldub [%0], %%g2\n\t" "b,a 1b\n\t" ".previous\n": /* no outputs */ 00125 :"r"( lock ) 00126 :"g2", "memory", "cc" ); 00127 } 00128 static inline void 00129 __raw_spin_unlock( volatile unsigned int *lock ) 00130 { 00131 __asm__ __volatile__( "stb %%g0, [%0]"::"r"( lock ):"memory" ); 00132 } 00133 00134 #define _papi_hwd_lock(lck) __raw_spin_lock(&_papi_hwd_lock_data[lck]); 00135 #define _papi_hwd_unlock(lck) __raw_spin_unlock(&_papi_hwd_lock_data[lck]) 00136 00137 /*******************/ 00138 /* ARM */ 00139 /*******************/ 00140 00141 #elif defined(__arm__) 00142 00143 #if 0 00144 00145 /* OLD CODE FROM VINCE BELOW */ 00146 00147 /* FIXME */ 00148 /* not sure if this even works */ 00149 /* also the various flavors of ARM */ 00150 /* have differing levels of atomic */ 00151 /* instruction support. A proper */ 00152 /* implementation needs to handle this :( */ 00153 00154 #warning "WARNING! Verify mutexes work on ARM!" 00155 00156 /* 00157 * For arm/gcc, 0 is clear, 1 is set. 00158 */ 00159 #define MUTEX_SET(tsl) ({ \ 00160 int __r; \ 00161 asm volatile( \ 00162 "swpb %0, %1, [%2]\n\t" \ 00163 "eor %0, %0, #1\n\t" \ 00164 : "=&r" (__r) \ 00165 : "r" (1), "r" (tsl) \ 00166 ); \ 00167 __r & 1; \ 00168 }) 00169 00170 #define _papi_hwd_lock(lck) MUTEX_SET(lck) 00171 #define _papi_hwd_unlock(lck) (*(volatile int *)(lck) = 0) 00172 #endif 00173 00174 /* NEW CODE FROM PHIL */ 00175 00176 static inline int __arm_papi_spin_lock (volatile unsigned int *lock) 00177 { 00178 unsigned int val; 00179 00180 do 00181 asm volatile ("swp %0, %1, [%2]" 00182 : "=r" (val) 00183 : "0" (1), "r" (lock) 00184 : "memory"); 00185 while (val != 0); 00186 00187 return 0; 00188 } 00189 #define _papi_hwd_lock(lck) { mb(); __arm_papi_spin_lock(&_papi_hwd_lock_data[lck]); mb(); } 00190 #define _papi_hwd_unlock(lck) { mb(); _papi_hwd_lock_data[lck] = 0; mb(); } 00191 00192 #elif defined(__mips__) 00193 static inline void __raw_spin_lock(volatile unsigned int *lock) 00194 { 00195 unsigned int tmp; 00196 __asm__ __volatile__( 00197 " .set noreorder # __raw_spin_lock \n" 00198 "1: ll %1, %2 \n" 00199 " bnez %1, 1b \n" 00200 " li %1, 1 \n" 00201 " sc %1, %0 \n" 00202 " beqzl %1, 1b \n" 00203 " nop \n" 00204 " sync \n" 00205 " .set reorder \n" 00206 : "=m" (*lock), "=&r" (tmp) 00207 : "m" (*lock) 00208 : "memory"); 00209 } 00210 00211 static inline void __raw_spin_unlock(volatile unsigned int *lock) 00212 { 00213 __asm__ __volatile__( 00214 " .set noreorder # __raw_spin_unlock \n" 00215 " sync \n" 00216 " sw $0, %0 \n" 00217 " .set\treorder \n" 00218 : "=m" (*lock) 00219 : "m" (*lock) 00220 : "memory"); 00221 } 00222 #define _papi_hwd_lock(lck) __raw_spin_lock(&_papi_hwd_lock_data[lck]); 00223 #define _papi_hwd_unlock(lck) __raw_spin_unlock(&_papi_hwd_lock_data[lck]) 00224 #else 00225 00226 #error "_papi_hwd_lock/unlock undefined!" 00227 #endif 00228 00229 #endif 00230 00231 #endif /* defined(USE_PTHREAD_MUTEXES) */