PAPI 7.1.0.0
Loading...
Searching...
No Matches
linux-lock.h
Go to the documentation of this file.
1#ifndef _LINUX_LOCK_H
2#define _LINUX_LOCK_H
3
4#include "mb.h"
5
6/* Let's try to use the atomics from the libatomic_ops project, */
7/* unless the user explicitly asks us to fall back to the legacy */
8/* PAPI atomics by specifying the flag USE_LEGACY_ATOMICS. */
9#include "atomic_ops.h"
10#if defined(AO_HAVE_test_and_set_acquire)&&!defined(USE_LEGACY_ATOMICS)
11#define USE_LIBAO_ATOMICS
12#endif
13
14/* Locking functions */
15
16#if defined(USE_PTHREAD_MUTEXES)
17
18#include <pthread.h>
19
21
22#define _papi_hwd_lock(lck) \
23do \
24{ \
25 pthread_mutex_lock (&_papi_hwd_lock_data[lck]); \
26} while(0)
27#define _papi_hwd_unlock(lck) \
28do \
29{ \
30 pthread_mutex_unlock(&_papi_hwd_lock_data[lck]); \
31} while(0)
32
33#elif defined(USE_LIBAO_ATOMICS)
34
36#define _papi_hwd_lock(lck) {while (AO_test_and_set_acquire(&_papi_hwd_lock_data[lck]) != AO_TS_CLEAR) { ; } }
37#define _papi_hwd_unlock(lck) { AO_CLEAR(&_papi_hwd_lock_data[lck]); }
38
39#else
40
41extern volatile unsigned int _papi_hwd_lock_data[PAPI_MAX_LOCK];
42#define MUTEX_OPEN 0
43#define MUTEX_CLOSED 1
44
45/********/
46/* ia64 */
47/********/
48
49#if defined(__ia64__)
50#ifdef __INTEL_COMPILER
51#define _papi_hwd_lock(lck) { while(_InterlockedCompareExchange_acq(&_papi_hwd_lock_data[lck],MUTEX_CLOSED,MUTEX_OPEN) != MUTEX_OPEN) { ; } }
52#define _papi_hwd_unlock(lck) { _InterlockedExchange((volatile int *)&_papi_hwd_lock_data[lck], MUTEX_OPEN); }
53#else /* GCC */
54#define _papi_hwd_lock(lck) \
55 { int res = 0; \
56 do { \
57 __asm__ __volatile__ ("mov ar.ccv=%0;;" :: "r"(MUTEX_OPEN)); \
58 __asm__ __volatile__ ("cmpxchg4.acq %0=[%1],%2,ar.ccv" : "=r"(res) : "r"(&_papi_hwd_lock_data[lck]), "r"(MUTEX_CLOSED) : "memory"); \
59 } while (res != MUTEX_OPEN); }
60
61#define _papi_hwd_unlock(lck) { __asm__ __volatile__ ("st4.rel [%0]=%1" : : "r"(&_papi_hwd_lock_data[lck]), "r"(MUTEX_OPEN) : "memory"); }
62#endif
63
64/***********/
65/* NEC */
66/* TODO: need CAS instructions for NEC card */
67/***********/
68
69#elif defined(__NEC__)
70#define _papi_hwd_lock(lck) \
71do \
72{ \
73 unsigned int res = 0; \
74} while(0)
75#define _papi_hwd_unlock(lck) \
76do \
77{ \
78 unsigned int res = 0; \
79} while(0)
80/***********/
81/* x86 */
82/***********/
83
84#elif defined(__i386__)||defined(__x86_64__)
85#define _papi_hwd_lock(lck) \
86do \
87{ \
88 unsigned int res = 0; \
89 do { \
90 __asm__ __volatile__ ("lock ; " "cmpxchg %1,%2" : "=a"(res) : "q"(MUTEX_CLOSED), "m"(_papi_hwd_lock_data[lck]), "0"(MUTEX_OPEN) : "memory"); \
91 } while(res != (unsigned int)MUTEX_OPEN); \
92} while(0)
93#define _papi_hwd_unlock(lck) \
94do \
95{ \
96 unsigned int res = 0; \
97 __asm__ __volatile__ ("xchg %0,%1" : "=r"(res) : "m"(_papi_hwd_lock_data[lck]), "0"(MUTEX_OPEN) : "memory"); \
98} while(0)
99
100/***************/
101/* power */
102/***************/
103
104#elif defined(__powerpc__)
105
106/*
107 * These functions are slight modifications of the functions in
108 * /usr/include/asm-ppc/system.h.
109 *
110 * We can't use the ones in system.h directly because they are defined
111 * only when __KERNEL__ is defined.
112 */
113
114static __inline__ unsigned long
115papi_xchg_u32( volatile void *p, unsigned long val )
116{
117 unsigned long prev;
118
119 __asm__ __volatile__( "\n\
120 sync \n\
1211: lwarx %0,0,%2 \n\
122 stwcx. %3,0,%2 \n\
123 bne- 1b \n\
124 isync":"=&r"( prev ), "=m"( *( volatile unsigned long * ) p )
125 :"r"( p ), "r"( val ),
126 "m"( *( volatile unsigned long * ) p )
127 :"cc", "memory" );
128
129 return prev;
130}
131
132#define _papi_hwd_lock(lck) \
133do { \
134 unsigned int retval; \
135 do { \
136 retval = papi_xchg_u32(&_papi_hwd_lock_data[lck],MUTEX_CLOSED); \
137 } while(retval != (unsigned int)MUTEX_OPEN); \
138} while(0)
139#define _papi_hwd_unlock(lck) \
140do { \
141 unsigned int retval; \
142 do { \
143 retval = papi_xchg_u32(&_papi_hwd_lock_data[lck],MUTEX_OPEN); \
144 } while(retval != (unsigned int)MUTEX_CLOSED); \
145} while (0)
146
147/*****************/
148/* SPARC */
149/*****************/
150
151#elif defined(__sparc__)
152static inline void
153__raw_spin_lock( volatile unsigned int *lock )
154{
155 __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 */
156 :"r"( lock )
157 :"g2", "memory", "cc" );
158}
159static inline void
160__raw_spin_unlock( volatile unsigned int *lock )
161{
162 __asm__ __volatile__( "stb %%g0, [%0]"::"r"( lock ):"memory" );
163}
164
165#define _papi_hwd_lock(lck) __raw_spin_lock(&_papi_hwd_lock_data[lck]);
166#define _papi_hwd_unlock(lck) __raw_spin_unlock(&_papi_hwd_lock_data[lck])
167
168/*******************/
169/* ARM */
170/*******************/
171
172#elif defined(__arm__)
173
174#if 0
175
176/* OLD CODE FROM VINCE BELOW */
177
178/* FIXME */
179/* not sure if this even works */
180/* also the various flavors of ARM */
181/* have differing levels of atomic */
182/* instruction support. A proper */
183/* implementation needs to handle this :( */
184
185#warning "WARNING! Verify mutexes work on ARM!"
186
187/*
188 * For arm/gcc, 0 is clear, 1 is set.
189 */
190#define MUTEX_SET(tsl) ({ \
191 int __r; \
192 asm volatile( \
193 "swpb %0, %1, [%2]\n\t" \
194 "eor %0, %0, #1\n\t" \
195 : "=&r" (__r) \
196 : "r" (1), "r" (tsl) \
197 ); \
198 __r & 1; \
199 })
200
201#define _papi_hwd_lock(lck) MUTEX_SET(lck)
202#define _papi_hwd_unlock(lck) (*(volatile int *)(lck) = 0)
203#endif
204
205/* NEW CODE FROM PHIL */
206
207static inline int __arm_papi_spin_lock (volatile unsigned int *lock)
208{
209 unsigned int val;
210
211 do
212 asm volatile ("swp %0, %1, [%2]"
213 : "=r" (val)
214 : "0" (1), "r" (lock)
215 : "memory");
216 while (val != 0);
217
218 return 0;
219}
220#define _papi_hwd_lock(lck) { rmb(); __arm_papi_spin_lock(&_papi_hwd_lock_data[lck]); rmb(); }
221#define _papi_hwd_unlock(lck) { rmb(); _papi_hwd_lock_data[lck] = 0; rmb(); }
222
223#elif defined(__mips__)
224static inline void __raw_spin_lock(volatile unsigned int *lock)
225{
226 unsigned int tmp;
227 __asm__ __volatile__(
228 " .set noreorder # __raw_spin_lock \n"
229 "1: ll %1, %2 \n"
230 " bnez %1, 1b \n"
231 " li %1, 1 \n"
232 " sc %1, %0 \n"
233#if __mips_isa_rev < 6
234 " beqzl %1, 1b \n"
235 " nop \n"
236#else
237 " beqzc %1,1b \n"
238#endif
239 " sync \n"
240 " .set reorder \n"
241 : "=m" (*lock), "=&r" (tmp)
242 : "m" (*lock)
243 : "memory");
244}
245
246static inline void __raw_spin_unlock(volatile unsigned int *lock)
247{
248 __asm__ __volatile__(
249 " .set noreorder # __raw_spin_unlock \n"
250 " sync \n"
251 " sw $0, %0 \n"
252 " .set\treorder \n"
253 : "=m" (*lock)
254 : "m" (*lock)
255 : "memory");
256}
257#define _papi_hwd_lock(lck) __raw_spin_lock(&_papi_hwd_lock_data[lck]);
258#define _papi_hwd_unlock(lck) __raw_spin_unlock(&_papi_hwd_lock_data[lck])
259#else
260
261#error "_papi_hwd_lock/unlock undefined!"
262#endif
263
264#endif
265
266#endif /* defined(USE_PTHREAD_MUTEXES) */
double tmp
atomic_p lock[]
Definition: aix.c:25
#define AO_TS_t
Definition: gcc/hppa.h:39
volatile unsigned int _papi_hwd_lock_data[PAPI_MAX_LOCK]
Definition: darwin-common.c:32
#define PAPI_MAX_LOCK
Definition: papi_lock.h:18