xref: /openbsd-src/sys/arch/i386/include/atomic.h (revision 91f110e064cd7c194e59e019b83bb7496c1c84d4)
1 /*	$OpenBSD: atomic.h,v 1.11 2012/11/19 15:18:06 pirofti Exp $	*/
2 /* $NetBSD: atomic.h,v 1.1.2.2 2000/02/21 18:54:07 sommerfeld Exp $ */
3 
4 /*-
5  * Copyright (c) 2000 The NetBSD Foundation, Inc.
6  * All rights reserved.
7  *
8  * This code is derived from software contributed to The NetBSD Foundation
9  * by RedBack Networks Inc.
10  *
11  * Author: Bill Sommerfeld
12  *
13  * Redistribution and use in source and binary forms, with or without
14  * modification, are permitted provided that the following conditions
15  * are met:
16  * 1. Redistributions of source code must retain the above copyright
17  *    notice, this list of conditions and the following disclaimer.
18  * 2. Redistributions in binary form must reproduce the above copyright
19  *    notice, this list of conditions and the following disclaimer in the
20  *    documentation and/or other materials provided with the distribution.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
23  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
25  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
26  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  */
34 
35 #ifndef _MACHINE_ATOMIC_H_
36 #define _MACHINE_ATOMIC_H_
37 
38 /*
39  * Perform atomic operations on memory. Should be atomic with respect
40  * to interrupts and multiple processors.
41  *
42  * void atomic_setbits_int(volatile u_int *a, u_int mask) { *a |= mask; }
43  * void atomic_clearbits_int(volatile u_int *a, u_int mas) { *a &= ~mask; }
44  */
45 #if defined(_KERNEL) && !defined(_LOCORE)
46 
47 #ifdef MULTIPROCESSOR
48 #define LOCK "lock"
49 #else
50 #define LOCK
51 #endif
52 
53 static __inline u_int64_t
54 i386_atomic_testset_uq(volatile u_int64_t *ptr, u_int64_t val)
55 {
56 	__asm__ volatile ("\n1:\t" LOCK " cmpxchg8b (%1); jnz 1b" : "+A" (val) :
57 	    "r" (ptr), "b" ((u_int32_t)val), "c" ((u_int32_t)(val >> 32)));
58 	return val;
59 }
60 
61 static __inline u_int32_t
62 i386_atomic_testset_ul(volatile u_int32_t *ptr, unsigned long val)
63 {
64 	__asm__ volatile ("xchgl %0,(%2)" :"=r" (val):"0" (val),"r" (ptr));
65 	return val;
66 }
67 
68 static __inline int
69 i386_atomic_testset_i(volatile int *ptr, unsigned long val)
70 {
71 	__asm__ volatile ("xchgl %0,(%2)" :"=r" (val):"0" (val),"r" (ptr));
72 	return val;
73 }
74 
75 static __inline void
76 i386_atomic_setbits_l(volatile u_int32_t *ptr, unsigned long bits)
77 {
78 	__asm __volatile(LOCK " orl %1,%0" :  "=m" (*ptr) : "ir" (bits));
79 }
80 
81 static __inline void
82 i386_atomic_clearbits_l(volatile u_int32_t *ptr, unsigned long bits)
83 {
84 	bits = ~bits;
85 	__asm __volatile(LOCK " andl %1,%0" :  "=m" (*ptr) : "ir" (bits));
86 }
87 
88 /*
89  * cas = compare and set
90  */
91 static __inline int
92 i486_atomic_cas_int(volatile u_int *ptr, u_int expect, u_int set)
93 {
94 	int res;
95 
96 	__asm volatile(LOCK " cmpxchgl %2, %1" : "=a" (res), "=m" (*ptr)
97 	     : "r" (set), "a" (expect), "m" (*ptr) : "memory");
98 
99 	return (res);
100 }
101 
102 static __inline int
103 i386_atomic_cas_int32(volatile int32_t *ptr, int32_t expect, int32_t set)
104 {
105 	int res;
106 
107 	__asm volatile(LOCK " cmpxchgl %2, %1" : "=a" (res), "=m" (*ptr)
108 	    : "r" (set), "a" (expect), "m" (*ptr) : "memory");
109 
110 	return (res);
111 }
112 
113 int ucas_32(volatile int32_t *, int32_t, int32_t);
114 #define futex_atomic_ucas_int32 ucas_32
115 
116 #define atomic_setbits_int i386_atomic_setbits_l
117 #define atomic_clearbits_int i386_atomic_clearbits_l
118 
119 #undef LOCK
120 
121 #endif /* defined(_KERNEL) && !defined(_LOCORE) */
122 #endif /* _MACHINE_ATOMIC_H_ */
123