]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - sys/i386/include/atomic.h
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / sys / i386 / include / atomic.h
1 /*-
2  * Copyright (c) 1998 Doug Rabson
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  * $FreeBSD$
27  */
28 #ifndef _MACHINE_ATOMIC_H_
29 #define _MACHINE_ATOMIC_H_
30
31 #ifndef _SYS_CDEFS_H_
32 #error this file needs sys/cdefs.h as a prerequisite
33 #endif
34
35 #define mb()    __asm __volatile("lock; addl $0,(%%esp)" : : : "memory", "cc")
36 #define wmb()   __asm __volatile("lock; addl $0,(%%esp)" : : : "memory", "cc")
37 #define rmb()   __asm __volatile("lock; addl $0,(%%esp)" : : : "memory", "cc")
38
39 /*
40  * Various simple operations on memory, each of which is atomic in the
41  * presence of interrupts and multiple processors.
42  *
43  * atomic_set_char(P, V)        (*(u_char *)(P) |= (V))
44  * atomic_clear_char(P, V)      (*(u_char *)(P) &= ~(V))
45  * atomic_add_char(P, V)        (*(u_char *)(P) += (V))
46  * atomic_subtract_char(P, V)   (*(u_char *)(P) -= (V))
47  *
48  * atomic_set_short(P, V)       (*(u_short *)(P) |= (V))
49  * atomic_clear_short(P, V)     (*(u_short *)(P) &= ~(V))
50  * atomic_add_short(P, V)       (*(u_short *)(P) += (V))
51  * atomic_subtract_short(P, V)  (*(u_short *)(P) -= (V))
52  *
53  * atomic_set_int(P, V)         (*(u_int *)(P) |= (V))
54  * atomic_clear_int(P, V)       (*(u_int *)(P) &= ~(V))
55  * atomic_add_int(P, V)         (*(u_int *)(P) += (V))
56  * atomic_subtract_int(P, V)    (*(u_int *)(P) -= (V))
57  * atomic_readandclear_int(P)   (return (*(u_int *)(P)); *(u_int *)(P) = 0;)
58  *
59  * atomic_set_long(P, V)        (*(u_long *)(P) |= (V))
60  * atomic_clear_long(P, V)      (*(u_long *)(P) &= ~(V))
61  * atomic_add_long(P, V)        (*(u_long *)(P) += (V))
62  * atomic_subtract_long(P, V)   (*(u_long *)(P) -= (V))
63  * atomic_readandclear_long(P)  (return (*(u_long *)(P)); *(u_long *)(P) = 0;)
64  */
65
66 /*
67  * The above functions are expanded inline in the statically-linked
68  * kernel.  Lock prefixes are generated if an SMP kernel is being
69  * built.
70  *
71  * Kernel modules call real functions which are built into the kernel.
72  * This allows kernel modules to be portable between UP and SMP systems.
73  */
74 #if defined(KLD_MODULE) || !defined(__GNUCLIKE_ASM)
75 #define ATOMIC_ASM(NAME, TYPE, OP, CONS, V)                     \
76 void atomic_##NAME##_##TYPE(volatile u_##TYPE *p, u_##TYPE v);  \
77 void atomic_##NAME##_barr_##TYPE(volatile u_##TYPE *p, u_##TYPE v)
78
79 int     atomic_cmpset_int(volatile u_int *dst, u_int expect, u_int src);
80 u_int   atomic_fetchadd_int(volatile u_int *p, u_int v);
81
82 #define ATOMIC_LOAD(TYPE, LOP)                                  \
83 u_##TYPE        atomic_load_acq_##TYPE(volatile u_##TYPE *p)
84 #define ATOMIC_STORE(TYPE)                                      \
85 void            atomic_store_rel_##TYPE(volatile u_##TYPE *p, u_##TYPE v)
86
87 #else /* !KLD_MODULE && __GNUCLIKE_ASM */
88
89 /*
90  * For userland, always use lock prefixes so that the binaries will run
91  * on both SMP and !SMP systems.
92  */
93 #if defined(SMP) || !defined(_KERNEL)
94 #define MPLOCKED        "lock ; "
95 #else
96 #define MPLOCKED
97 #endif
98
99 /*
100  * The assembly is volatilized to avoid code chunk removal by the compiler.
101  * GCC aggressively reorders operations and memory clobbering is necessary
102  * in order to avoid that for memory barriers.
103  */
104 #define ATOMIC_ASM(NAME, TYPE, OP, CONS, V)             \
105 static __inline void                                    \
106 atomic_##NAME##_##TYPE(volatile u_##TYPE *p, u_##TYPE v)\
107 {                                                       \
108         __asm __volatile(MPLOCKED OP                    \
109         : "=m" (*p)                                     \
110         : CONS (V), "m" (*p)                            \
111         : "cc");                                        \
112 }                                                       \
113                                                         \
114 static __inline void                                    \
115 atomic_##NAME##_barr_##TYPE(volatile u_##TYPE *p, u_##TYPE v)\
116 {                                                       \
117         __asm __volatile(MPLOCKED OP                    \
118         : "=m" (*p)                                     \
119         : CONS (V), "m" (*p)                            \
120         : "memory", "cc");                              \
121 }                                                       \
122 struct __hack
123
124 #if defined(_KERNEL) && !defined(WANT_FUNCTIONS)
125
126 /* I486 does not support SMP or CMPXCHG8B. */
127 static __inline uint64_t
128 atomic_load_acq_64_i386(volatile uint64_t *p)
129 {
130         volatile uint32_t *high, *low;
131         uint64_t res;
132
133         low = (volatile uint32_t *)p;
134         high = (volatile uint32_t *)p + 1;
135         __asm __volatile(
136         "       pushfl ;                "
137         "       cli ;                   "
138         "       movl %1,%%eax ;         "
139         "       movl %2,%%edx ;         "
140         "       popfl"
141         : "=&A" (res)                   /* 0 */
142         : "m" (*low),                   /* 1 */
143           "m" (*high)                   /* 2 */
144         : "memory");
145
146         return (res);
147 }
148
149 static __inline void
150 atomic_store_rel_64_i386(volatile uint64_t *p, uint64_t v)
151 {
152         volatile uint32_t *high, *low;
153
154         low = (volatile uint32_t *)p;
155         high = (volatile uint32_t *)p + 1;
156         __asm __volatile(
157         "       pushfl ;                "
158         "       cli ;                   "
159         "       movl %%eax,%0 ;         "
160         "       movl %%edx,%1 ;         "
161         "       popfl"
162         : "=m" (*low),                  /* 0 */
163           "=m" (*high)                  /* 1 */
164         : "A" (v)                       /* 2 */
165         : "memory");
166 }
167
168 static __inline uint64_t
169 atomic_load_acq_64_i586(volatile uint64_t *p)
170 {
171         uint64_t res;
172
173         __asm __volatile(
174         "       movl %%ebx,%%eax ;      "
175         "       movl %%ecx,%%edx ;      "
176         "       " MPLOCKED "            "
177         "       cmpxchg8b %2"
178         : "=&A" (res),                  /* 0 */
179           "=m" (*p)                     /* 1 */
180         : "m" (*p)                      /* 2 */
181         : "memory", "cc");
182
183         return (res);
184 }
185
186 static __inline void
187 atomic_store_rel_64_i586(volatile uint64_t *p, uint64_t v)
188 {
189
190         __asm __volatile(
191         "       movl %%eax,%%ebx ;      "
192         "       movl %%edx,%%ecx ;      "
193         "1:                             "
194         "       " MPLOCKED "            "
195         "       cmpxchg8b %2 ;          "
196         "       jne 1b"
197         : "=m" (*p),                    /* 0 */
198           "+A" (v)                      /* 1 */
199         : "m" (*p)                      /* 2 */
200         : "ebx", "ecx", "memory", "cc");
201 }
202
203 #endif /* _KERNEL && !WANT_FUNCTIONS */
204
205 /*
206  * Atomic compare and set, used by the mutex functions
207  *
208  * if (*dst == expect) *dst = src (all 32 bit words)
209  *
210  * Returns 0 on failure, non-zero on success
211  */
212
213 #ifdef CPU_DISABLE_CMPXCHG
214
215 static __inline int
216 atomic_cmpset_int(volatile u_int *dst, u_int expect, u_int src)
217 {
218         u_char res;
219
220         __asm __volatile(
221         "       pushfl ;                "
222         "       cli ;                   "
223         "       cmpl    %3,%4 ;         "
224         "       jne     1f ;            "
225         "       movl    %2,%1 ;         "
226         "1:                             "
227         "       sete    %0 ;            "
228         "       popfl ;                 "
229         "# atomic_cmpset_int"
230         : "=q" (res),                   /* 0 */
231           "=m" (*dst)                   /* 1 */
232         : "r" (src),                    /* 2 */
233           "r" (expect),                 /* 3 */
234           "m" (*dst)                    /* 4 */
235         : "memory");
236
237         return (res);
238 }
239
240 #else /* !CPU_DISABLE_CMPXCHG */
241
242 static __inline int
243 atomic_cmpset_int(volatile u_int *dst, u_int expect, u_int src)
244 {
245         u_char res;
246
247         __asm __volatile(
248         "       " MPLOCKED "            "
249         "       cmpxchgl %2,%1 ;        "
250         "       sete    %0 ;            "
251         "1:                             "
252         "# atomic_cmpset_int"
253         : "=a" (res),                   /* 0 */
254           "=m" (*dst)                   /* 1 */
255         : "r" (src),                    /* 2 */
256           "a" (expect),                 /* 3 */
257           "m" (*dst)                    /* 4 */
258         : "memory", "cc");
259
260         return (res);
261 }
262
263 #endif /* CPU_DISABLE_CMPXCHG */
264
265 /*
266  * Atomically add the value of v to the integer pointed to by p and return
267  * the previous value of *p.
268  */
269 static __inline u_int
270 atomic_fetchadd_int(volatile u_int *p, u_int v)
271 {
272
273         __asm __volatile(
274         "       " MPLOCKED "            "
275         "       xaddl   %0, %1 ;        "
276         "# atomic_fetchadd_int"
277         : "+r" (v),                     /* 0 (result) */
278           "=m" (*p)                     /* 1 */
279         : "m" (*p)                      /* 2 */
280         : "cc");
281         return (v);
282 }
283
284 /*
285  * We assume that a = b will do atomic loads and stores.  Due to the
286  * IA32 memory model, a simple store guarantees release semantics.
287  *
288  * However, loads may pass stores, so for atomic_load_acq we have to
289  * ensure a Store/Load barrier to do the load in SMP kernels.  We use
290  * "lock cmpxchg" as recommended by the AMD Software Optimization
291  * Guide, and not mfence.  For UP kernels, however, the cache of the
292  * single processor is always consistent, so we only need to take care
293  * of the compiler.
294  */
295 #define ATOMIC_STORE(TYPE)                              \
296 static __inline void                                    \
297 atomic_store_rel_##TYPE(volatile u_##TYPE *p, u_##TYPE v)\
298 {                                                       \
299         __asm __volatile("" : : : "memory");            \
300         *p = v;                                         \
301 }                                                       \
302 struct __hack
303
304 #if defined(_KERNEL) && !defined(SMP)
305
306 #define ATOMIC_LOAD(TYPE, LOP)                          \
307 static __inline u_##TYPE                                \
308 atomic_load_acq_##TYPE(volatile u_##TYPE *p)            \
309 {                                                       \
310         u_##TYPE tmp;                                   \
311                                                         \
312         tmp = *p;                                       \
313         __asm __volatile("" : : : "memory");            \
314         return (tmp);                                   \
315 }                                                       \
316 struct __hack
317
318 #else /* !(_KERNEL && !SMP) */
319
320 #define ATOMIC_LOAD(TYPE, LOP)                          \
321 static __inline u_##TYPE                                \
322 atomic_load_acq_##TYPE(volatile u_##TYPE *p)            \
323 {                                                       \
324         u_##TYPE res;                                   \
325                                                         \
326         __asm __volatile(MPLOCKED LOP                   \
327         : "=a" (res),                   /* 0 */         \
328           "=m" (*p)                     /* 1 */         \
329         : "m" (*p)                      /* 2 */         \
330         : "memory", "cc");                              \
331                                                         \
332         return (res);                                   \
333 }                                                       \
334 struct __hack
335
336 #endif /* _KERNEL && !SMP */
337
338 #endif /* KLD_MODULE || !__GNUCLIKE_ASM */
339
340 ATOMIC_ASM(set,      char,  "orb %b1,%0",  "iq",  v);
341 ATOMIC_ASM(clear,    char,  "andb %b1,%0", "iq", ~v);
342 ATOMIC_ASM(add,      char,  "addb %b1,%0", "iq",  v);
343 ATOMIC_ASM(subtract, char,  "subb %b1,%0", "iq",  v);
344
345 ATOMIC_ASM(set,      short, "orw %w1,%0",  "ir",  v);
346 ATOMIC_ASM(clear,    short, "andw %w1,%0", "ir", ~v);
347 ATOMIC_ASM(add,      short, "addw %w1,%0", "ir",  v);
348 ATOMIC_ASM(subtract, short, "subw %w1,%0", "ir",  v);
349
350 ATOMIC_ASM(set,      int,   "orl %1,%0",   "ir",  v);
351 ATOMIC_ASM(clear,    int,   "andl %1,%0",  "ir", ~v);
352 ATOMIC_ASM(add,      int,   "addl %1,%0",  "ir",  v);
353 ATOMIC_ASM(subtract, int,   "subl %1,%0",  "ir",  v);
354
355 ATOMIC_ASM(set,      long,  "orl %1,%0",   "ir",  v);
356 ATOMIC_ASM(clear,    long,  "andl %1,%0",  "ir", ~v);
357 ATOMIC_ASM(add,      long,  "addl %1,%0",  "ir",  v);
358 ATOMIC_ASM(subtract, long,  "subl %1,%0",  "ir",  v);
359
360 ATOMIC_LOAD(char,  "cmpxchgb %b0,%1");
361 ATOMIC_LOAD(short, "cmpxchgw %w0,%1");
362 ATOMIC_LOAD(int,   "cmpxchgl %0,%1");
363 ATOMIC_LOAD(long,  "cmpxchgl %0,%1");
364
365 ATOMIC_STORE(char);
366 ATOMIC_STORE(short);
367 ATOMIC_STORE(int);
368 ATOMIC_STORE(long);
369
370 #undef ATOMIC_ASM
371 #undef ATOMIC_LOAD
372 #undef ATOMIC_STORE
373
374 #ifndef WANT_FUNCTIONS
375
376 #ifdef _KERNEL
377 extern uint64_t (*atomic_load_acq_64)(volatile uint64_t *);
378 extern void (*atomic_store_rel_64)(volatile uint64_t *, uint64_t);
379 #endif
380
381 static __inline int
382 atomic_cmpset_long(volatile u_long *dst, u_long expect, u_long src)
383 {
384
385         return (atomic_cmpset_int((volatile u_int *)dst, (u_int)expect,
386             (u_int)src));
387 }
388
389 static __inline u_long
390 atomic_fetchadd_long(volatile u_long *p, u_long v)
391 {
392
393         return (atomic_fetchadd_int((volatile u_int *)p, (u_int)v));
394 }
395
396 /* Read the current value and store a zero in the destination. */
397 #ifdef __GNUCLIKE_ASM
398
399 static __inline u_int
400 atomic_readandclear_int(volatile u_int *addr)
401 {
402         u_int res;
403
404         res = 0;
405         __asm __volatile(
406         "       xchgl   %1,%0 ;         "
407         "# atomic_readandclear_int"
408         : "+r" (res),                   /* 0 */
409           "=m" (*addr)                  /* 1 */
410         : "m" (*addr));
411
412         return (res);
413 }
414
415 static __inline u_long
416 atomic_readandclear_long(volatile u_long *addr)
417 {
418         u_long res;
419
420         res = 0;
421         __asm __volatile(
422         "       xchgl   %1,%0 ;         "
423         "# atomic_readandclear_long"
424         : "+r" (res),                   /* 0 */
425           "=m" (*addr)                  /* 1 */
426         : "m" (*addr));
427
428         return (res);
429 }
430
431 #else /* !__GNUCLIKE_ASM */
432
433 u_int   atomic_readandclear_int(volatile u_int *addr);
434 u_long  atomic_readandclear_long(volatile u_long *addr);
435
436 #endif /* __GNUCLIKE_ASM */
437
438 #define atomic_set_acq_char             atomic_set_barr_char
439 #define atomic_set_rel_char             atomic_set_barr_char
440 #define atomic_clear_acq_char           atomic_clear_barr_char
441 #define atomic_clear_rel_char           atomic_clear_barr_char
442 #define atomic_add_acq_char             atomic_add_barr_char
443 #define atomic_add_rel_char             atomic_add_barr_char
444 #define atomic_subtract_acq_char        atomic_subtract_barr_char
445 #define atomic_subtract_rel_char        atomic_subtract_barr_char
446
447 #define atomic_set_acq_short            atomic_set_barr_short
448 #define atomic_set_rel_short            atomic_set_barr_short
449 #define atomic_clear_acq_short          atomic_clear_barr_short
450 #define atomic_clear_rel_short          atomic_clear_barr_short
451 #define atomic_add_acq_short            atomic_add_barr_short
452 #define atomic_add_rel_short            atomic_add_barr_short
453 #define atomic_subtract_acq_short       atomic_subtract_barr_short
454 #define atomic_subtract_rel_short       atomic_subtract_barr_short
455
456 #define atomic_set_acq_int              atomic_set_barr_int
457 #define atomic_set_rel_int              atomic_set_barr_int
458 #define atomic_clear_acq_int            atomic_clear_barr_int
459 #define atomic_clear_rel_int            atomic_clear_barr_int
460 #define atomic_add_acq_int              atomic_add_barr_int
461 #define atomic_add_rel_int              atomic_add_barr_int
462 #define atomic_subtract_acq_int         atomic_subtract_barr_int
463 #define atomic_subtract_rel_int         atomic_subtract_barr_int
464 #define atomic_cmpset_acq_int           atomic_cmpset_int
465 #define atomic_cmpset_rel_int           atomic_cmpset_int
466
467 #define atomic_set_acq_long             atomic_set_barr_long
468 #define atomic_set_rel_long             atomic_set_barr_long
469 #define atomic_clear_acq_long           atomic_clear_barr_long
470 #define atomic_clear_rel_long           atomic_clear_barr_long
471 #define atomic_add_acq_long             atomic_add_barr_long
472 #define atomic_add_rel_long             atomic_add_barr_long
473 #define atomic_subtract_acq_long        atomic_subtract_barr_long
474 #define atomic_subtract_rel_long        atomic_subtract_barr_long
475 #define atomic_cmpset_acq_long          atomic_cmpset_long
476 #define atomic_cmpset_rel_long          atomic_cmpset_long
477
478 /* Operations on 8-bit bytes. */
479 #define atomic_set_8            atomic_set_char
480 #define atomic_set_acq_8        atomic_set_acq_char
481 #define atomic_set_rel_8        atomic_set_rel_char
482 #define atomic_clear_8          atomic_clear_char
483 #define atomic_clear_acq_8      atomic_clear_acq_char
484 #define atomic_clear_rel_8      atomic_clear_rel_char
485 #define atomic_add_8            atomic_add_char
486 #define atomic_add_acq_8        atomic_add_acq_char
487 #define atomic_add_rel_8        atomic_add_rel_char
488 #define atomic_subtract_8       atomic_subtract_char
489 #define atomic_subtract_acq_8   atomic_subtract_acq_char
490 #define atomic_subtract_rel_8   atomic_subtract_rel_char
491 #define atomic_load_acq_8       atomic_load_acq_char
492 #define atomic_store_rel_8      atomic_store_rel_char
493
494 /* Operations on 16-bit words. */
495 #define atomic_set_16           atomic_set_short
496 #define atomic_set_acq_16       atomic_set_acq_short
497 #define atomic_set_rel_16       atomic_set_rel_short
498 #define atomic_clear_16         atomic_clear_short
499 #define atomic_clear_acq_16     atomic_clear_acq_short
500 #define atomic_clear_rel_16     atomic_clear_rel_short
501 #define atomic_add_16           atomic_add_short
502 #define atomic_add_acq_16       atomic_add_acq_short
503 #define atomic_add_rel_16       atomic_add_rel_short
504 #define atomic_subtract_16      atomic_subtract_short
505 #define atomic_subtract_acq_16  atomic_subtract_acq_short
506 #define atomic_subtract_rel_16  atomic_subtract_rel_short
507 #define atomic_load_acq_16      atomic_load_acq_short
508 #define atomic_store_rel_16     atomic_store_rel_short
509
510 /* Operations on 32-bit double words. */
511 #define atomic_set_32           atomic_set_int
512 #define atomic_set_acq_32       atomic_set_acq_int
513 #define atomic_set_rel_32       atomic_set_rel_int
514 #define atomic_clear_32         atomic_clear_int
515 #define atomic_clear_acq_32     atomic_clear_acq_int
516 #define atomic_clear_rel_32     atomic_clear_rel_int
517 #define atomic_add_32           atomic_add_int
518 #define atomic_add_acq_32       atomic_add_acq_int
519 #define atomic_add_rel_32       atomic_add_rel_int
520 #define atomic_subtract_32      atomic_subtract_int
521 #define atomic_subtract_acq_32  atomic_subtract_acq_int
522 #define atomic_subtract_rel_32  atomic_subtract_rel_int
523 #define atomic_load_acq_32      atomic_load_acq_int
524 #define atomic_store_rel_32     atomic_store_rel_int
525 #define atomic_cmpset_32        atomic_cmpset_int
526 #define atomic_cmpset_acq_32    atomic_cmpset_acq_int
527 #define atomic_cmpset_rel_32    atomic_cmpset_rel_int
528 #define atomic_readandclear_32  atomic_readandclear_int
529 #define atomic_fetchadd_32      atomic_fetchadd_int
530
531 /* Operations on pointers. */
532 #define atomic_set_ptr(p, v) \
533         atomic_set_int((volatile u_int *)(p), (u_int)(v))
534 #define atomic_set_acq_ptr(p, v) \
535         atomic_set_acq_int((volatile u_int *)(p), (u_int)(v))
536 #define atomic_set_rel_ptr(p, v) \
537         atomic_set_rel_int((volatile u_int *)(p), (u_int)(v))
538 #define atomic_clear_ptr(p, v) \
539         atomic_clear_int((volatile u_int *)(p), (u_int)(v))
540 #define atomic_clear_acq_ptr(p, v) \
541         atomic_clear_acq_int((volatile u_int *)(p), (u_int)(v))
542 #define atomic_clear_rel_ptr(p, v) \
543         atomic_clear_rel_int((volatile u_int *)(p), (u_int)(v))
544 #define atomic_add_ptr(p, v) \
545         atomic_add_int((volatile u_int *)(p), (u_int)(v))
546 #define atomic_add_acq_ptr(p, v) \
547         atomic_add_acq_int((volatile u_int *)(p), (u_int)(v))
548 #define atomic_add_rel_ptr(p, v) \
549         atomic_add_rel_int((volatile u_int *)(p), (u_int)(v))
550 #define atomic_subtract_ptr(p, v) \
551         atomic_subtract_int((volatile u_int *)(p), (u_int)(v))
552 #define atomic_subtract_acq_ptr(p, v) \
553         atomic_subtract_acq_int((volatile u_int *)(p), (u_int)(v))
554 #define atomic_subtract_rel_ptr(p, v) \
555         atomic_subtract_rel_int((volatile u_int *)(p), (u_int)(v))
556 #define atomic_load_acq_ptr(p) \
557         atomic_load_acq_int((volatile u_int *)(p))
558 #define atomic_store_rel_ptr(p, v) \
559         atomic_store_rel_int((volatile u_int *)(p), (v))
560 #define atomic_cmpset_ptr(dst, old, new) \
561         atomic_cmpset_int((volatile u_int *)(dst), (u_int)(old), (u_int)(new))
562 #define atomic_cmpset_acq_ptr(dst, old, new) \
563         atomic_cmpset_acq_int((volatile u_int *)(dst), (u_int)(old), \
564             (u_int)(new))
565 #define atomic_cmpset_rel_ptr(dst, old, new) \
566         atomic_cmpset_rel_int((volatile u_int *)(dst), (u_int)(old), \
567             (u_int)(new))
568 #define atomic_readandclear_ptr(p) \
569         atomic_readandclear_int((volatile u_int *)(p))
570
571 #endif /* !WANT_FUNCTIONS */
572
573 #endif /* !_MACHINE_ATOMIC_H_ */