2
* Copyright (c) 2003 Fabrice Bellard
4
* This library is free software; you can redistribute it and/or
5
* modify it under the terms of the GNU Lesser General Public
6
* License as published by the Free Software Foundation; either
7
* version 2 of the License, or (at your option) any later version.
9
* This library is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
* Lesser General Public License for more details.
14
* You should have received a copy of the GNU Lesser General Public
15
* License along with this library; if not, write to the Free Software
16
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
/* Locking primitives. Most of this code should be redundant -
20
system emulation doesn't need/use locking, NPTL userspace uses
21
pthread mutexes, and non-NPTL userspace isn't threadsafe anyway.
22
In either case a spinlock is probably the wrong kind of lock.
23
Spinlocks are only good if you know annother CPU has the lock and is
24
likely to release it soon. In environments where you have more threads
25
than physical CPUs (the extreme case being a single CPU host) a spinlock
26
simply wastes CPU until the OS decides to preempt it. */
30
#define spin_lock pthread_mutex_lock
31
#define spin_unlock pthread_mutex_unlock
32
#define spinlock_t pthread_mutex_t
33
#define SPIN_LOCK_UNLOCKED PTHREAD_MUTEX_INITIALIZER
39
typedef int spinlock_t[4];
41
#define SPIN_LOCK_UNLOCKED { 1, 1, 1, 1 }
43
static inline void resetlock (spinlock_t *p)
45
(*p)[0] = (*p)[1] = (*p)[2] = (*p)[3] = 1;
50
typedef int spinlock_t;
52
#define SPIN_LOCK_UNLOCKED 0
54
static inline void resetlock (spinlock_t *p)
56
*p = SPIN_LOCK_UNLOCKED;
61
#if defined(__powerpc__)
62
static inline int testandset (int *p)
65
__asm__ __volatile__ (
73
: "r" (p), "r" (1), "r" (0)
77
#elif defined(__i386__)
78
static inline int testandset (int *p)
82
__asm__ __volatile__ ("lock; cmpxchgl %2, %0"
83
: "+m" (*p), "+a" (readval)
88
#elif defined(__x86_64__)
89
static inline int testandset (int *p)
93
__asm__ __volatile__ ("lock; cmpxchgl %2, %0"
94
: "+m" (*p), "+a" (readval)
99
#elif defined(__s390__)
100
static inline int testandset (int *p)
104
__asm__ __volatile__ ("0: cs %0,%1,0(%2)\n"
107
: "r" (1), "a" (p), "0" (*p)
111
#elif defined(__alpha__)
112
static inline int testandset (int *p)
117
__asm__ __volatile__ ("0: mov 1,%2\n"
124
: "=r" (ret), "=m" (*p), "=r" (one)
128
#elif defined(__sparc__)
129
static inline int testandset (int *p)
133
__asm__ __volatile__("ldstub [%1], %0"
138
return (ret ? 1 : 0);
140
#elif defined(__arm__)
141
static inline int testandset (int *spinlock)
143
register unsigned int ret;
144
__asm__ __volatile__("swp %0, %1, [%2]"
146
: "0"(1), "r"(spinlock));
150
#elif defined(__mc68000)
151
static inline int testandset (int *p)
154
__asm__ __volatile__("tas %1; sne %0"
160
#elif defined(__hppa__)
162
/* Because malloc only guarantees 8-byte alignment for malloc'd data,
163
and GCC only guarantees 8-byte alignment for stack locals, we can't
164
be assured of 16-byte alignment for atomic lock data even if we
165
specify "__attribute ((aligned(16)))" in the type declaration. So,
166
we use a struct containing an array of four ints for the atomic lock
167
type and dynamically select the 16-byte aligned int from the array
168
for the semaphore. */
169
#define __PA_LDCW_ALIGNMENT 16
170
static inline void *ldcw_align (void *p) {
171
unsigned long a = (unsigned long)p;
172
a = (a + __PA_LDCW_ALIGNMENT - 1) & ~(__PA_LDCW_ALIGNMENT - 1);
176
static inline int testandset (spinlock_t *p)
180
__asm__ __volatile__("ldcw 0(%1),%0"
187
#elif defined(__ia64)
189
#include <ia64intrin.h>
191
static inline int testandset (int *p)
193
return __sync_lock_test_and_set (p, 1);
195
#elif defined(__mips__)
196
static inline int testandset (int *p)
200
__asm__ __volatile__ (
209
: "=r" (ret), "+R" (*p)
216
#error unimplemented CPU support
219
#if defined(CONFIG_USER_ONLY)
220
static inline void spin_lock(spinlock_t *lock)
222
while (testandset(lock));
225
static inline void spin_unlock(spinlock_t *lock)
230
static inline int spin_trylock(spinlock_t *lock)
232
return !testandset(lock);
235
static inline void spin_lock(spinlock_t *lock)
239
static inline void spin_unlock(spinlock_t *lock)
243
static inline int spin_trylock(spinlock_t *lock)