Statistics
| Branch: | Revision:

root / qemu-lock.h @ 8215e914

History | View | Annotate | Download (6 kB)

1 d5975363 pbrook
/*
2 d5975363 pbrook
 *  Copyright (c) 2003 Fabrice Bellard
3 d5975363 pbrook
 *
4 d5975363 pbrook
 * This library is free software; you can redistribute it and/or
5 d5975363 pbrook
 * modify it under the terms of the GNU Lesser General Public
6 d5975363 pbrook
 * License as published by the Free Software Foundation; either
7 d5975363 pbrook
 * version 2 of the License, or (at your option) any later version.
8 d5975363 pbrook
 *
9 d5975363 pbrook
 * This library is distributed in the hope that it will be useful,
10 d5975363 pbrook
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 d5975363 pbrook
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 d5975363 pbrook
 * Lesser General Public License for more details.
13 d5975363 pbrook
 *
14 d5975363 pbrook
 * You should have received a copy of the GNU Lesser General Public
15 d5975363 pbrook
 * License along with this library; if not, write to the Free Software
16 fad6cb1a aurel32
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
17 d5975363 pbrook
 */
18 d5975363 pbrook
19 d5975363 pbrook
/* Locking primitives.  Most of this code should be redundant -
20 d5975363 pbrook
   system emulation doesn't need/use locking, NPTL userspace uses
21 d5975363 pbrook
   pthread mutexes, and non-NPTL userspace isn't threadsafe anyway.
22 d5975363 pbrook
   In either case a spinlock is probably the wrong kind of lock.
23 d5975363 pbrook
   Spinlocks are only good if you know annother CPU has the lock and is
24 d5975363 pbrook
   likely to release it soon.  In environments where you have more threads
25 d5975363 pbrook
   than physical CPUs (the extreme case being a single CPU host) a spinlock
26 d5975363 pbrook
   simply wastes CPU until the OS decides to preempt it.  */
27 d5975363 pbrook
#if defined(USE_NPTL)
28 d5975363 pbrook
29 d5975363 pbrook
#include <pthread.h>
30 d5975363 pbrook
#define spin_lock pthread_mutex_lock
31 d5975363 pbrook
#define spin_unlock pthread_mutex_unlock
32 d5975363 pbrook
#define spinlock_t pthread_mutex_t
33 d5975363 pbrook
#define SPIN_LOCK_UNLOCKED PTHREAD_MUTEX_INITIALIZER
34 d5975363 pbrook
35 d5975363 pbrook
#else
36 d5975363 pbrook
37 d5975363 pbrook
#if defined(__hppa__)
38 d5975363 pbrook
39 d5975363 pbrook
typedef int spinlock_t[4];
40 d5975363 pbrook
41 d5975363 pbrook
#define SPIN_LOCK_UNLOCKED { 1, 1, 1, 1 }
42 d5975363 pbrook
43 d5975363 pbrook
static inline void resetlock (spinlock_t *p)
44 d5975363 pbrook
{
45 d5975363 pbrook
    (*p)[0] = (*p)[1] = (*p)[2] = (*p)[3] = 1;
46 d5975363 pbrook
}
47 d5975363 pbrook
48 d5975363 pbrook
#else
49 d5975363 pbrook
50 d5975363 pbrook
typedef int spinlock_t;
51 d5975363 pbrook
52 d5975363 pbrook
#define SPIN_LOCK_UNLOCKED 0
53 d5975363 pbrook
54 d5975363 pbrook
static inline void resetlock (spinlock_t *p)
55 d5975363 pbrook
{
56 d5975363 pbrook
    *p = SPIN_LOCK_UNLOCKED;
57 d5975363 pbrook
}
58 d5975363 pbrook
59 d5975363 pbrook
#endif
60 d5975363 pbrook
61 e58ffeb3 malc
#if defined(_ARCH_PPC)
62 d5975363 pbrook
static inline int testandset (int *p)
63 d5975363 pbrook
{
64 d5975363 pbrook
    int ret;
65 d5975363 pbrook
    __asm__ __volatile__ (
66 14f87098 malc
                          "      lwarx %0,0,%1\n"
67 d5975363 pbrook
                          "      xor. %0,%3,%0\n"
68 14f87098 malc
                          "      bne $+12\n"
69 d5975363 pbrook
                          "      stwcx. %2,0,%1\n"
70 14f87098 malc
                          "      bne- $-16\n"
71 d5975363 pbrook
                          : "=&r" (ret)
72 d5975363 pbrook
                          : "r" (p), "r" (1), "r" (0)
73 d5975363 pbrook
                          : "cr0", "memory");
74 d5975363 pbrook
    return ret;
75 d5975363 pbrook
}
76 d5975363 pbrook
#elif defined(__i386__)
77 d5975363 pbrook
static inline int testandset (int *p)
78 d5975363 pbrook
{
79 d5975363 pbrook
    long int readval = 0;
80 d5975363 pbrook
81 d5975363 pbrook
    __asm__ __volatile__ ("lock; cmpxchgl %2, %0"
82 d5975363 pbrook
                          : "+m" (*p), "+a" (readval)
83 d5975363 pbrook
                          : "r" (1)
84 d5975363 pbrook
                          : "cc");
85 d5975363 pbrook
    return readval;
86 d5975363 pbrook
}
87 d5975363 pbrook
#elif defined(__x86_64__)
88 d5975363 pbrook
static inline int testandset (int *p)
89 d5975363 pbrook
{
90 d5975363 pbrook
    long int readval = 0;
91 d5975363 pbrook
92 d5975363 pbrook
    __asm__ __volatile__ ("lock; cmpxchgl %2, %0"
93 d5975363 pbrook
                          : "+m" (*p), "+a" (readval)
94 d5975363 pbrook
                          : "r" (1)
95 d5975363 pbrook
                          : "cc");
96 d5975363 pbrook
    return readval;
97 d5975363 pbrook
}
98 d5975363 pbrook
#elif defined(__s390__)
99 d5975363 pbrook
static inline int testandset (int *p)
100 d5975363 pbrook
{
101 d5975363 pbrook
    int ret;
102 d5975363 pbrook
103 d5975363 pbrook
    __asm__ __volatile__ ("0: cs    %0,%1,0(%2)\n"
104 d5975363 pbrook
                          "   jl    0b"
105 d5975363 pbrook
                          : "=&d" (ret)
106 d5975363 pbrook
                          : "r" (1), "a" (p), "0" (*p)
107 d5975363 pbrook
                          : "cc", "memory" );
108 d5975363 pbrook
    return ret;
109 d5975363 pbrook
}
110 d5975363 pbrook
#elif defined(__alpha__)
111 d5975363 pbrook
static inline int testandset (int *p)
112 d5975363 pbrook
{
113 d5975363 pbrook
    int ret;
114 d5975363 pbrook
    unsigned long one;
115 d5975363 pbrook
116 d5975363 pbrook
    __asm__ __volatile__ ("0:        mov 1,%2\n"
117 d5975363 pbrook
                          "        ldl_l %0,%1\n"
118 d5975363 pbrook
                          "        stl_c %2,%1\n"
119 d5975363 pbrook
                          "        beq %2,1f\n"
120 d5975363 pbrook
                          ".subsection 2\n"
121 d5975363 pbrook
                          "1:        br 0b\n"
122 d5975363 pbrook
                          ".previous"
123 d5975363 pbrook
                          : "=r" (ret), "=m" (*p), "=r" (one)
124 d5975363 pbrook
                          : "m" (*p));
125 d5975363 pbrook
    return ret;
126 d5975363 pbrook
}
127 d5975363 pbrook
#elif defined(__sparc__)
128 d5975363 pbrook
static inline int testandset (int *p)
129 d5975363 pbrook
{
130 d5975363 pbrook
        int ret;
131 d5975363 pbrook
132 d5975363 pbrook
        __asm__ __volatile__("ldstub        [%1], %0"
133 d5975363 pbrook
                             : "=r" (ret)
134 d5975363 pbrook
                             : "r" (p)
135 d5975363 pbrook
                             : "memory");
136 d5975363 pbrook
137 d5975363 pbrook
        return (ret ? 1 : 0);
138 d5975363 pbrook
}
139 d5975363 pbrook
#elif defined(__arm__)
140 d5975363 pbrook
static inline int testandset (int *spinlock)
141 d5975363 pbrook
{
142 d5975363 pbrook
    register unsigned int ret;
143 d5975363 pbrook
    __asm__ __volatile__("swp %0, %1, [%2]"
144 d5975363 pbrook
                         : "=r"(ret)
145 d5975363 pbrook
                         : "0"(1), "r"(spinlock));
146 d5975363 pbrook
147 d5975363 pbrook
    return ret;
148 d5975363 pbrook
}
149 d5975363 pbrook
#elif defined(__mc68000)
150 d5975363 pbrook
static inline int testandset (int *p)
151 d5975363 pbrook
{
152 d5975363 pbrook
    char ret;
153 d5975363 pbrook
    __asm__ __volatile__("tas %1; sne %0"
154 d5975363 pbrook
                         : "=r" (ret)
155 d5975363 pbrook
                         : "m" (p)
156 d5975363 pbrook
                         : "cc","memory");
157 d5975363 pbrook
    return ret;
158 d5975363 pbrook
}
159 d5975363 pbrook
#elif defined(__hppa__)
160 d5975363 pbrook
161 d5975363 pbrook
/* Because malloc only guarantees 8-byte alignment for malloc'd data,
162 d5975363 pbrook
   and GCC only guarantees 8-byte alignment for stack locals, we can't
163 d5975363 pbrook
   be assured of 16-byte alignment for atomic lock data even if we
164 d5975363 pbrook
   specify "__attribute ((aligned(16)))" in the type declaration.  So,
165 d5975363 pbrook
   we use a struct containing an array of four ints for the atomic lock
166 d5975363 pbrook
   type and dynamically select the 16-byte aligned int from the array
167 d5975363 pbrook
   for the semaphore.  */
168 d5975363 pbrook
#define __PA_LDCW_ALIGNMENT 16
169 d5975363 pbrook
static inline void *ldcw_align (void *p) {
170 d5975363 pbrook
    unsigned long a = (unsigned long)p;
171 d5975363 pbrook
    a = (a + __PA_LDCW_ALIGNMENT - 1) & ~(__PA_LDCW_ALIGNMENT - 1);
172 d5975363 pbrook
    return (void *)a;
173 d5975363 pbrook
}
174 d5975363 pbrook
175 d5975363 pbrook
static inline int testandset (spinlock_t *p)
176 d5975363 pbrook
{
177 d5975363 pbrook
    unsigned int ret;
178 d5975363 pbrook
    p = ldcw_align(p);
179 d5975363 pbrook
    __asm__ __volatile__("ldcw 0(%1),%0"
180 d5975363 pbrook
                         : "=r" (ret)
181 d5975363 pbrook
                         : "r" (p)
182 d5975363 pbrook
                         : "memory" );
183 d5975363 pbrook
    return !ret;
184 d5975363 pbrook
}
185 d5975363 pbrook
186 d5975363 pbrook
#elif defined(__ia64)
187 d5975363 pbrook
188 d5975363 pbrook
#include <ia64intrin.h>
189 d5975363 pbrook
190 d5975363 pbrook
static inline int testandset (int *p)
191 d5975363 pbrook
{
192 d5975363 pbrook
    return __sync_lock_test_and_set (p, 1);
193 d5975363 pbrook
}
194 d5975363 pbrook
#elif defined(__mips__)
195 d5975363 pbrook
static inline int testandset (int *p)
196 d5975363 pbrook
{
197 d5975363 pbrook
    int ret;
198 d5975363 pbrook
199 d5975363 pbrook
    __asm__ __volatile__ (
200 d5975363 pbrook
        "        .set push                \n"
201 d5975363 pbrook
        "        .set noat                \n"
202 d5975363 pbrook
        "        .set mips2                \n"
203 d5975363 pbrook
        "1:        li        $1, 1                \n"
204 d5975363 pbrook
        "        ll        %0, %1                \n"
205 d5975363 pbrook
        "        sc        $1, %1                \n"
206 d5975363 pbrook
        "        beqz        $1, 1b                \n"
207 d5975363 pbrook
        "        .set pop                "
208 d5975363 pbrook
        : "=r" (ret), "+R" (*p)
209 d5975363 pbrook
        :
210 d5975363 pbrook
        : "memory");
211 d5975363 pbrook
212 d5975363 pbrook
    return ret;
213 d5975363 pbrook
}
214 d5975363 pbrook
#else
215 d5975363 pbrook
#error unimplemented CPU support
216 d5975363 pbrook
#endif
217 d5975363 pbrook
218 d5975363 pbrook
#if defined(CONFIG_USER_ONLY)
219 d5975363 pbrook
static inline void spin_lock(spinlock_t *lock)
220 d5975363 pbrook
{
221 d5975363 pbrook
    while (testandset(lock));
222 d5975363 pbrook
}
223 d5975363 pbrook
224 d5975363 pbrook
static inline void spin_unlock(spinlock_t *lock)
225 d5975363 pbrook
{
226 d5975363 pbrook
    resetlock(lock);
227 d5975363 pbrook
}
228 d5975363 pbrook
229 d5975363 pbrook
static inline int spin_trylock(spinlock_t *lock)
230 d5975363 pbrook
{
231 d5975363 pbrook
    return !testandset(lock);
232 d5975363 pbrook
}
233 d5975363 pbrook
#else
234 d5975363 pbrook
static inline void spin_lock(spinlock_t *lock)
235 d5975363 pbrook
{
236 d5975363 pbrook
}
237 d5975363 pbrook
238 d5975363 pbrook
static inline void spin_unlock(spinlock_t *lock)
239 d5975363 pbrook
{
240 d5975363 pbrook
}
241 d5975363 pbrook
242 d5975363 pbrook
static inline int spin_trylock(spinlock_t *lock)
243 d5975363 pbrook
{
244 d5975363 pbrook
    return 1;
245 d5975363 pbrook
}
246 d5975363 pbrook
#endif
247 d5975363 pbrook
248 d5975363 pbrook
#endif