1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
2 /*
3 * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
4 * University Research and Technology
5 * Corporation. All rights reserved.
6 * Copyright (c) 2004-2010 The University of Tennessee and The University
7 * of Tennessee Research Foundation. All rights
8 * reserved.
9 * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
10 * University of Stuttgart. All rights reserved.
11 * Copyright (c) 2004-2005 The Regents of the University of California.
12 * All rights reserved.
13 * Copyright (c) 2007-2010 Oracle and/or its affiliates. All rights reserved.
14 * Copyright (c) 2015 Research Organization for Information Science
15 * and Technology (RIST). All rights reserved.
16 * Copyright (c) 2015-2018 Los Alamos National Security, LLC. All rights
17 * reserved.
18 * $COPYRIGHT$
19 *
20 * Additional copyrights may follow
21 *
22 * $HEADER$
23 */
24
25 #ifndef OPAL_SYS_ARCH_ATOMIC_H
26 #define OPAL_SYS_ARCH_ATOMIC_H 1
27
28 /*
29 * On ia32, we use cmpxchg.
30 */
31
32 #define SMPLOCK "lock; "
33 #define MB() __asm__ __volatile__("": : :"memory")
34
35
36 /**********************************************************************
37 *
38 * Define constants for IA32
39 *
40 *********************************************************************/
41 #define OPAL_HAVE_ATOMIC_MEM_BARRIER 1
42
43 #define OPAL_HAVE_ATOMIC_COMPARE_EXCHANGE_32 1
44
45 #define OPAL_HAVE_ATOMIC_MATH_32 1
46 #define OPAL_HAVE_ATOMIC_ADD_32 1
47 #define OPAL_HAVE_ATOMIC_SUB_32 1
48
49 /**********************************************************************
50 *
51 * Memory Barriers
52 *
53 *********************************************************************/
54 #if OPAL_GCC_INLINE_ASSEMBLY
55
56 static inline void opal_atomic_mb(void)
57 {
58 MB();
59 }
60
61
62 static inline void opal_atomic_rmb(void)
63 {
64 MB();
65 }
66
67
68 static inline void opal_atomic_wmb(void)
69 {
70 MB();
71 }
72
73 static inline void opal_atomic_isync(void)
74 {
75 }
76
77 #endif /* OPAL_GCC_INLINE_ASSEMBLY */
78
79
80 /**********************************************************************
81 *
82 * Atomic math operations
83 *
84 *********************************************************************/
85 #if OPAL_GCC_INLINE_ASSEMBLY
86
87 static inline bool opal_atomic_compare_exchange_strong_32 (opal_atomic_int32_t *addr, int32_t *oldval, int32_t newval)
88 {
89 unsigned char ret;
90 __asm__ __volatile__ (
91 SMPLOCK "cmpxchgl %3,%2 \n\t"
92 "sete %0 \n\t"
93 : "=qm" (ret), "+a" (*oldval), "+m" (*addr)
94 : "q"(newval)
95 : "memory", "cc");
96
97 return (bool) ret;
98 }
99
100 #endif /* OPAL_GCC_INLINE_ASSEMBLY */
101
102 #define opal_atomic_compare_exchange_strong_acq_32 opal_atomic_compare_exchange_strong_32
103 #define opal_atomic_compare_exchange_strong_rel_32 opal_atomic_compare_exchange_strong_32
104
105 #if OPAL_GCC_INLINE_ASSEMBLY
106
107 #define OPAL_HAVE_ATOMIC_SWAP_32 1
108
109 static inline int32_t opal_atomic_swap_32( opal_atomic_int32_t *addr,
110 int32_t newval)
111 {
112 int32_t oldval;
113
114 __asm__ __volatile__("xchg %1, %0" :
115 "=r" (oldval), "=m" (*addr) :
116 "0" (newval), "m" (*addr) :
117 "memory");
118 return oldval;
119 }
120
121 #endif /* OPAL_GCC_INLINE_ASSEMBLY */
122
123
124 #if OPAL_GCC_INLINE_ASSEMBLY
125
126 /**
127 * atomic_add - add integer to atomic variable
128 * @i: integer value to add
129 * @v: pointer of type int
130 *
131 * Atomically adds @i to @v.
132 */
133 static inline int32_t opal_atomic_fetch_add_32(opal_atomic_int32_t* v, int i)
134 {
135 int ret = i;
136 __asm__ __volatile__(
137 SMPLOCK "xaddl %1,%0"
138 :"+m" (*v), "+r" (ret)
139 :
140 :"memory", "cc"
141 );
142 return ret;
143 }
144
145
146 /**
147 * atomic_sub - subtract the atomic variable
148 * @i: integer value to subtract
149 * @v: pointer of type int
150 *
151 * Atomically subtracts @i from @v.
152 */
153 static inline int32_t opal_atomic_fetch_sub_32(opal_atomic_int32_t* v, int i)
154 {
155 int ret = -i;
156 __asm__ __volatile__(
157 SMPLOCK "xaddl %1,%0"
158 :"+m" (*v), "+r" (ret)
159 :
160 :"memory", "cc"
161 );
162 return ret;
163 }
164
165 #endif /* OPAL_GCC_INLINE_ASSEMBLY */
166
167 #endif /* ! OPAL_SYS_ARCH_ATOMIC_H */