Revision 02615337 qemu-lock.h

b/qemu-lock.h
15 15
 * License along with this library; if not, see <http://www.gnu.org/licenses/>
16 16
 */
17 17

  
18
/* Locking primitives.  Most of this code should be redundant -
19
   system emulation doesn't need/use locking, NPTL userspace uses
20
   pthread mutexes, and non-NPTL userspace isn't threadsafe anyway.
21
   In either case a spinlock is probably the wrong kind of lock.
22
   Spinlocks are only good if you know annother CPU has the lock and is
23
   likely to release it soon.  In environments where you have more threads
24
   than physical CPUs (the extreme case being a single CPU host) a spinlock
25
   simply wastes CPU until the OS decides to preempt it.  */
26
#if defined(CONFIG_USE_NPTL)
18
/* configure guarantees us that we have pthreads on any host except
19
 * mingw32, which doesn't support any of the user-only targets.
20
 * So we can simply assume we have pthread mutexes here.
21
 */
22
#if defined(CONFIG_USER_ONLY)
27 23

  
28 24
#include <pthread.h>
29 25
#define spin_lock pthread_mutex_lock
......
33 29

  
34 30
#else
35 31

  
36
#if defined(__hppa__)
37

  
38
typedef int spinlock_t[4];
39

  
40
#define SPIN_LOCK_UNLOCKED { 1, 1, 1, 1 }
41

  
42
static inline void resetlock (spinlock_t *p)
43
{
44
    (*p)[0] = (*p)[1] = (*p)[2] = (*p)[3] = 1;
45
}
46

  
47
#else
48

  
32
/* Empty implementations, on the theory that system mode emulation
33
 * is single-threaded. This means that these functions should only
34
 * be used from code run in the TCG cpu thread, and cannot protect
35
 * data structures which might also be accessed from the IO thread
36
 * or from signal handlers.
37
 */
49 38
typedef int spinlock_t;
50

  
51 39
#define SPIN_LOCK_UNLOCKED 0
52 40

  
53
static inline void resetlock (spinlock_t *p)
54
{
55
    *p = SPIN_LOCK_UNLOCKED;
56
}
57

  
58
#endif
59

  
60
#if defined(_ARCH_PPC)
61
static inline int testandset (int *p)
62
{
63
    int ret;
64
    __asm__ __volatile__ (
65
                          "      lwarx %0,0,%1\n"
66
                          "      xor. %0,%3,%0\n"
67
                          "      bne $+12\n"
68
                          "      stwcx. %2,0,%1\n"
69
                          "      bne- $-16\n"
70
                          : "=&r" (ret)
71
                          : "r" (p), "r" (1), "r" (0)
72
                          : "cr0", "memory");
73
    return ret;
74
}
75
#elif defined(__i386__)
76
static inline int testandset (int *p)
77
{
78
    long int readval = 0;
79

  
80
    __asm__ __volatile__ ("lock; cmpxchgl %2, %0"
81
                          : "+m" (*p), "+a" (readval)
82
                          : "r" (1)
83
                          : "cc");
84
    return readval;
85
}
86
#elif defined(__x86_64__)
87
static inline int testandset (int *p)
88
{
89
    long int readval = 0;
90

  
91
    __asm__ __volatile__ ("lock; cmpxchgl %2, %0"
92
                          : "+m" (*p), "+a" (readval)
93
                          : "r" (1)
94
                          : "cc");
95
    return readval;
96
}
97
#elif defined(__s390__)
98
static inline int testandset (int *p)
99
{
100
    int ret;
101

  
102
    __asm__ __volatile__ ("0: cs    %0,%1,0(%2)\n"
103
			  "   jl    0b"
104
			  : "=&d" (ret)
105
			  : "r" (1), "a" (p), "0" (*p)
106
			  : "cc", "memory" );
107
    return ret;
108
}
109
#elif defined(__alpha__)
110
static inline int testandset (int *p)
111
{
112
    int ret;
113
    unsigned long one;
114

  
115
    __asm__ __volatile__ ("0:	mov 1,%2\n"
116
			  "	ldl_l %0,%1\n"
117
			  "	stl_c %2,%1\n"
118
			  "	beq %2,1f\n"
119
			  ".subsection 2\n"
120
			  "1:	br 0b\n"
121
			  ".previous"
122
			  : "=r" (ret), "=m" (*p), "=r" (one)
123
			  : "m" (*p));
124
    return ret;
125
}
126
#elif defined(__sparc__)
127
static inline int testandset (int *p)
128
{
129
	int ret;
130

  
131
	__asm__ __volatile__("ldstub	[%1], %0"
132
			     : "=r" (ret)
133
			     : "r" (p)
134
			     : "memory");
135

  
136
	return (ret ? 1 : 0);
137
}
138
#elif defined(__arm__)
139
static inline int testandset (int *spinlock)
140
{
141
    register unsigned int ret;
142
    __asm__ __volatile__("swp %0, %1, [%2]"
143
                         : "=r"(ret)
144
                         : "0"(1), "r"(spinlock));
145

  
146
    return ret;
147
}
148
#elif defined(__mc68000)
149
static inline int testandset (int *p)
150
{
151
    char ret;
152
    __asm__ __volatile__("tas %1; sne %0"
153
                         : "=r" (ret)
154
                         : "m" (p)
155
                         : "cc","memory");
156
    return ret;
157
}
158
#elif defined(__hppa__)
159

  
160
/* Because malloc only guarantees 8-byte alignment for malloc'd data,
161
   and GCC only guarantees 8-byte alignment for stack locals, we can't
162
   be assured of 16-byte alignment for atomic lock data even if we
163
   specify "__attribute ((aligned(16)))" in the type declaration.  So,
164
   we use a struct containing an array of four ints for the atomic lock
165
   type and dynamically select the 16-byte aligned int from the array
166
   for the semaphore.  */
167
#define __PA_LDCW_ALIGNMENT 16
168
static inline void *ldcw_align (void *p) {
169
    unsigned long a = (unsigned long)p;
170
    a = (a + __PA_LDCW_ALIGNMENT - 1) & ~(__PA_LDCW_ALIGNMENT - 1);
171
    return (void *)a;
172
}
173

  
174
static inline int testandset (spinlock_t *p)
175
{
176
    unsigned int ret;
177
    p = ldcw_align(p);
178
    __asm__ __volatile__("ldcw 0(%1),%0"
179
                         : "=r" (ret)
180
                         : "r" (p)
181
                         : "memory" );
182
    return !ret;
183
}
184

  
185
#elif defined(__ia64)
186

  
187
#include <ia64intrin.h>
188

  
189
static inline int testandset (int *p)
190
{
191
    return __sync_lock_test_and_set (p, 1);
192
}
193
#elif defined(__mips__)
194
static inline int testandset (int *p)
195
{
196
    int ret;
197

  
198
    __asm__ __volatile__ (
199
	"	.set push		\n"
200
	"	.set noat		\n"
201
	"	.set mips2		\n"
202
	"1:	li	$1, 1		\n"
203
	"	ll	%0, %1		\n"
204
	"	sc	$1, %1		\n"
205
	"	beqz	$1, 1b		\n"
206
	"	.set pop		"
207
	: "=r" (ret), "+R" (*p)
208
	:
209
	: "memory");
210

  
211
    return ret;
212
}
213
#else
214
#error unimplemented CPU support
215
#endif
216

  
217
#if defined(CONFIG_USER_ONLY)
218
static inline void spin_lock(spinlock_t *lock)
219
{
220
    while (testandset(lock));
221
}
222

  
223
static inline void spin_unlock(spinlock_t *lock)
224
{
225
    resetlock(lock);
226
}
227
#else
228 41
static inline void spin_lock(spinlock_t *lock)
229 42
{
230 43
}
......
232 45
static inline void spin_unlock(spinlock_t *lock)
233 46
{
234 47
}
235
#endif
236 48

  
237 49
#endif

Also available in: Unified diff