Statistics
| Branch: | Revision:

root / qemu-lock.h @ a5f1b965

History | View | Annotate | Download (6.1 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 d5975363 pbrook
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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 d5975363 pbrook
#if defined(__powerpc__)
62 d5975363 pbrook
static inline int testandset (int *p)
63 d5975363 pbrook
{
64 d5975363 pbrook
    int ret;
65 d5975363 pbrook
    __asm__ __volatile__ (
66 d5975363 pbrook
                          "0:    lwarx %0,0,%1\n"
67 d5975363 pbrook
                          "      xor. %0,%3,%0\n"
68 d5975363 pbrook
                          "      bne 1f\n"
69 d5975363 pbrook
                          "      stwcx. %2,0,%1\n"
70 d5975363 pbrook
                          "      bne- 0b\n"
71 d5975363 pbrook
                          "1:    "
72 d5975363 pbrook
                          : "=&r" (ret)
73 d5975363 pbrook
                          : "r" (p), "r" (1), "r" (0)
74 d5975363 pbrook
                          : "cr0", "memory");
75 d5975363 pbrook
    return ret;
76 d5975363 pbrook
}
77 d5975363 pbrook
#elif defined(__i386__)
78 d5975363 pbrook
static inline int testandset (int *p)
79 d5975363 pbrook
{
80 d5975363 pbrook
    long int readval = 0;
81 d5975363 pbrook
82 d5975363 pbrook
    __asm__ __volatile__ ("lock; cmpxchgl %2, %0"
83 d5975363 pbrook
                          : "+m" (*p), "+a" (readval)
84 d5975363 pbrook
                          : "r" (1)
85 d5975363 pbrook
                          : "cc");
86 d5975363 pbrook
    return readval;
87 d5975363 pbrook
}
88 d5975363 pbrook
#elif defined(__x86_64__)
89 d5975363 pbrook
static inline int testandset (int *p)
90 d5975363 pbrook
{
91 d5975363 pbrook
    long int readval = 0;
92 d5975363 pbrook
93 d5975363 pbrook
    __asm__ __volatile__ ("lock; cmpxchgl %2, %0"
94 d5975363 pbrook
                          : "+m" (*p), "+a" (readval)
95 d5975363 pbrook
                          : "r" (1)
96 d5975363 pbrook
                          : "cc");
97 d5975363 pbrook
    return readval;
98 d5975363 pbrook
}
99 d5975363 pbrook
#elif defined(__s390__)
100 d5975363 pbrook
static inline int testandset (int *p)
101 d5975363 pbrook
{
102 d5975363 pbrook
    int ret;
103 d5975363 pbrook
104 d5975363 pbrook
    __asm__ __volatile__ ("0: cs    %0,%1,0(%2)\n"
105 d5975363 pbrook
                          "   jl    0b"
106 d5975363 pbrook
                          : "=&d" (ret)
107 d5975363 pbrook
                          : "r" (1), "a" (p), "0" (*p)
108 d5975363 pbrook
                          : "cc", "memory" );
109 d5975363 pbrook
    return ret;
110 d5975363 pbrook
}
111 d5975363 pbrook
#elif defined(__alpha__)
112 d5975363 pbrook
static inline int testandset (int *p)
113 d5975363 pbrook
{
114 d5975363 pbrook
    int ret;
115 d5975363 pbrook
    unsigned long one;
116 d5975363 pbrook
117 d5975363 pbrook
    __asm__ __volatile__ ("0:        mov 1,%2\n"
118 d5975363 pbrook
                          "        ldl_l %0,%1\n"
119 d5975363 pbrook
                          "        stl_c %2,%1\n"
120 d5975363 pbrook
                          "        beq %2,1f\n"
121 d5975363 pbrook
                          ".subsection 2\n"
122 d5975363 pbrook
                          "1:        br 0b\n"
123 d5975363 pbrook
                          ".previous"
124 d5975363 pbrook
                          : "=r" (ret), "=m" (*p), "=r" (one)
125 d5975363 pbrook
                          : "m" (*p));
126 d5975363 pbrook
    return ret;
127 d5975363 pbrook
}
128 d5975363 pbrook
#elif defined(__sparc__)
129 d5975363 pbrook
static inline int testandset (int *p)
130 d5975363 pbrook
{
131 d5975363 pbrook
        int ret;
132 d5975363 pbrook
133 d5975363 pbrook
        __asm__ __volatile__("ldstub        [%1], %0"
134 d5975363 pbrook
                             : "=r" (ret)
135 d5975363 pbrook
                             : "r" (p)
136 d5975363 pbrook
                             : "memory");
137 d5975363 pbrook
138 d5975363 pbrook
        return (ret ? 1 : 0);
139 d5975363 pbrook
}
140 d5975363 pbrook
#elif defined(__arm__)
141 d5975363 pbrook
static inline int testandset (int *spinlock)
142 d5975363 pbrook
{
143 d5975363 pbrook
    register unsigned int ret;
144 d5975363 pbrook
    __asm__ __volatile__("swp %0, %1, [%2]"
145 d5975363 pbrook
                         : "=r"(ret)
146 d5975363 pbrook
                         : "0"(1), "r"(spinlock));
147 d5975363 pbrook
148 d5975363 pbrook
    return ret;
149 d5975363 pbrook
}
150 d5975363 pbrook
#elif defined(__mc68000)
151 d5975363 pbrook
static inline int testandset (int *p)
152 d5975363 pbrook
{
153 d5975363 pbrook
    char ret;
154 d5975363 pbrook
    __asm__ __volatile__("tas %1; sne %0"
155 d5975363 pbrook
                         : "=r" (ret)
156 d5975363 pbrook
                         : "m" (p)
157 d5975363 pbrook
                         : "cc","memory");
158 d5975363 pbrook
    return ret;
159 d5975363 pbrook
}
160 d5975363 pbrook
#elif defined(__hppa__)
161 d5975363 pbrook
162 d5975363 pbrook
/* Because malloc only guarantees 8-byte alignment for malloc'd data,
163 d5975363 pbrook
   and GCC only guarantees 8-byte alignment for stack locals, we can't
164 d5975363 pbrook
   be assured of 16-byte alignment for atomic lock data even if we
165 d5975363 pbrook
   specify "__attribute ((aligned(16)))" in the type declaration.  So,
166 d5975363 pbrook
   we use a struct containing an array of four ints for the atomic lock
167 d5975363 pbrook
   type and dynamically select the 16-byte aligned int from the array
168 d5975363 pbrook
   for the semaphore.  */
169 d5975363 pbrook
#define __PA_LDCW_ALIGNMENT 16
170 d5975363 pbrook
static inline void *ldcw_align (void *p) {
171 d5975363 pbrook
    unsigned long a = (unsigned long)p;
172 d5975363 pbrook
    a = (a + __PA_LDCW_ALIGNMENT - 1) & ~(__PA_LDCW_ALIGNMENT - 1);
173 d5975363 pbrook
    return (void *)a;
174 d5975363 pbrook
}
175 d5975363 pbrook
176 d5975363 pbrook
static inline int testandset (spinlock_t *p)
177 d5975363 pbrook
{
178 d5975363 pbrook
    unsigned int ret;
179 d5975363 pbrook
    p = ldcw_align(p);
180 d5975363 pbrook
    __asm__ __volatile__("ldcw 0(%1),%0"
181 d5975363 pbrook
                         : "=r" (ret)
182 d5975363 pbrook
                         : "r" (p)
183 d5975363 pbrook
                         : "memory" );
184 d5975363 pbrook
    return !ret;
185 d5975363 pbrook
}
186 d5975363 pbrook
187 d5975363 pbrook
#elif defined(__ia64)
188 d5975363 pbrook
189 d5975363 pbrook
#include <ia64intrin.h>
190 d5975363 pbrook
191 d5975363 pbrook
static inline int testandset (int *p)
192 d5975363 pbrook
{
193 d5975363 pbrook
    return __sync_lock_test_and_set (p, 1);
194 d5975363 pbrook
}
195 d5975363 pbrook
#elif defined(__mips__)
196 d5975363 pbrook
static inline int testandset (int *p)
197 d5975363 pbrook
{
198 d5975363 pbrook
    int ret;
199 d5975363 pbrook
200 d5975363 pbrook
    __asm__ __volatile__ (
201 d5975363 pbrook
        "        .set push                \n"
202 d5975363 pbrook
        "        .set noat                \n"
203 d5975363 pbrook
        "        .set mips2                \n"
204 d5975363 pbrook
        "1:        li        $1, 1                \n"
205 d5975363 pbrook
        "        ll        %0, %1                \n"
206 d5975363 pbrook
        "        sc        $1, %1                \n"
207 d5975363 pbrook
        "        beqz        $1, 1b                \n"
208 d5975363 pbrook
        "        .set pop                "
209 d5975363 pbrook
        : "=r" (ret), "+R" (*p)
210 d5975363 pbrook
        :
211 d5975363 pbrook
        : "memory");
212 d5975363 pbrook
213 d5975363 pbrook
    return ret;
214 d5975363 pbrook
}
215 d5975363 pbrook
#else
216 d5975363 pbrook
#error unimplemented CPU support
217 d5975363 pbrook
#endif
218 d5975363 pbrook
219 d5975363 pbrook
#if defined(CONFIG_USER_ONLY)
220 d5975363 pbrook
static inline void spin_lock(spinlock_t *lock)
221 d5975363 pbrook
{
222 d5975363 pbrook
    while (testandset(lock));
223 d5975363 pbrook
}
224 d5975363 pbrook
225 d5975363 pbrook
static inline void spin_unlock(spinlock_t *lock)
226 d5975363 pbrook
{
227 d5975363 pbrook
    resetlock(lock);
228 d5975363 pbrook
}
229 d5975363 pbrook
230 d5975363 pbrook
static inline int spin_trylock(spinlock_t *lock)
231 d5975363 pbrook
{
232 d5975363 pbrook
    return !testandset(lock);
233 d5975363 pbrook
}
234 d5975363 pbrook
#else
235 d5975363 pbrook
static inline void spin_lock(spinlock_t *lock)
236 d5975363 pbrook
{
237 d5975363 pbrook
}
238 d5975363 pbrook
239 d5975363 pbrook
static inline void spin_unlock(spinlock_t *lock)
240 d5975363 pbrook
{
241 d5975363 pbrook
}
242 d5975363 pbrook
243 d5975363 pbrook
static inline int spin_trylock(spinlock_t *lock)
244 d5975363 pbrook
{
245 d5975363 pbrook
    return 1;
246 d5975363 pbrook
}
247 d5975363 pbrook
#endif
248 d5975363 pbrook
249 d5975363 pbrook
#endif