PAPI  5.0.1.0
linux-lock.h
Go to the documentation of this file.
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) */
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines