1b5073b49SDavid E. O'Brien /*- 24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause 371e3c308SPedro F. Giffuni * 4c563d533SMarcel Moolenaar * Copyright (c) 2008 Marcel Moolenaar 5199a2415SBenno Rice * Copyright (c) 2001 Benno Rice 6b5073b49SDavid E. O'Brien * Copyright (c) 2001 David E. O'Brien 7b5073b49SDavid E. O'Brien * Copyright (c) 1998 Doug Rabson 8b5073b49SDavid E. O'Brien * All rights reserved. 9b5073b49SDavid E. O'Brien * 10b5073b49SDavid E. O'Brien * Redistribution and use in source and binary forms, with or without 11b5073b49SDavid E. O'Brien * modification, are permitted provided that the following conditions 12b5073b49SDavid E. O'Brien * are met: 13b5073b49SDavid E. O'Brien * 1. Redistributions of source code must retain the above copyright 14b5073b49SDavid E. O'Brien * notice, this list of conditions and the following disclaimer. 15b5073b49SDavid E. O'Brien * 2. Redistributions in binary form must reproduce the above copyright 16b5073b49SDavid E. O'Brien * notice, this list of conditions and the following disclaimer in the 17b5073b49SDavid E. O'Brien * documentation and/or other materials provided with the distribution. 18b5073b49SDavid E. O'Brien * 19b5073b49SDavid E. O'Brien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20b5073b49SDavid E. O'Brien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21b5073b49SDavid E. O'Brien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22b5073b49SDavid E. O'Brien * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 23b5073b49SDavid E. O'Brien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24b5073b49SDavid E. O'Brien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25b5073b49SDavid E. O'Brien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26b5073b49SDavid E. O'Brien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27b5073b49SDavid E. O'Brien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28b5073b49SDavid E. O'Brien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29b5073b49SDavid E. O'Brien * SUCH DAMAGE. 30b5073b49SDavid E. O'Brien */ 31b5073b49SDavid E. O'Brien 32b5073b49SDavid E. O'Brien #ifndef _MACHINE_ATOMIC_H_ 33b5073b49SDavid E. O'Brien #define _MACHINE_ATOMIC_H_ 34b5073b49SDavid E. O'Brien 3530d4f9e8SKonstantin Belousov #include <sys/atomic_common.h> 3630d4f9e8SKonstantin Belousov 379aafc7c0SBrandon Bergren #ifndef __powerpc64__ 389aafc7c0SBrandon Bergren #include <sys/_atomic64e.h> 399aafc7c0SBrandon Bergren #endif 409aafc7c0SBrandon Bergren 41a6349a99SNathan Whitehorn /* 42a4cbf436SNathan Whitehorn * The __ATOMIC_REL/ACQ() macros provide memory barriers only in conjunction 43df0bef25SMarcel Moolenaar * with the atomic lXarx/stXcx. sequences below. They are not exposed outside 44df0bef25SMarcel Moolenaar * of this file. See also Appendix B.2 of Book II of the architecture manual. 45df0bef25SMarcel Moolenaar * 46df0bef25SMarcel Moolenaar * Note that not all Book-E processors accept the light-weight sync variant. 47df0bef25SMarcel Moolenaar * In particular, early models of E500 cores are known to wedge. Bank on all 48df0bef25SMarcel Moolenaar * 64-bit capable CPUs to accept lwsync properly and pressimize 32-bit CPUs 49df0bef25SMarcel Moolenaar * to use the heavier-weight sync. 50a6349a99SNathan Whitehorn */ 51df0bef25SMarcel Moolenaar 52df0bef25SMarcel Moolenaar #ifdef __powerpc64__ 530b39ffb3SKonstantin Belousov #define mb() __asm __volatile("sync" : : : "memory") 54df0bef25SMarcel Moolenaar #define rmb() __asm __volatile("lwsync" : : : "memory") 55df0bef25SMarcel Moolenaar #define wmb() __asm __volatile("lwsync" : : : "memory") 56a4cbf436SNathan Whitehorn #define __ATOMIC_REL() __asm __volatile("lwsync" : : : "memory") 57270dc329SNathan Whitehorn #define __ATOMIC_ACQ() __asm __volatile("isync" : : : "memory") 58df0bef25SMarcel Moolenaar #else 5970977949SMarcel Moolenaar #define mb() __asm __volatile("sync" : : : "memory") 6070977949SMarcel Moolenaar #define rmb() __asm __volatile("sync" : : : "memory") 6108c5f330SBjoern A. Zeeb #define wmb() __asm __volatile("sync" : : : "memory") 6270977949SMarcel Moolenaar #define __ATOMIC_REL() __asm __volatile("sync" : : : "memory") 63a4cbf436SNathan Whitehorn #define __ATOMIC_ACQ() __asm __volatile("isync" : : : "memory") 64df0bef25SMarcel Moolenaar #endif 65db7f0b97SKip Macy 660b39ffb3SKonstantin Belousov static __inline void 670b39ffb3SKonstantin Belousov powerpc_lwsync(void) 680b39ffb3SKonstantin Belousov { 690b39ffb3SKonstantin Belousov 700b39ffb3SKonstantin Belousov #ifdef __powerpc64__ 710b39ffb3SKonstantin Belousov __asm __volatile("lwsync" : : : "memory"); 720b39ffb3SKonstantin Belousov #else 730b39ffb3SKonstantin Belousov __asm __volatile("sync" : : : "memory"); 740b39ffb3SKonstantin Belousov #endif 750b39ffb3SKonstantin Belousov } 760b39ffb3SKonstantin Belousov 77b5073b49SDavid E. O'Brien /* 78c563d533SMarcel Moolenaar * atomic_add(p, v) 79c563d533SMarcel Moolenaar * { *p += v; } 80b5073b49SDavid E. O'Brien */ 81b5073b49SDavid E. O'Brien 82dc6dc1f5SAttilio Rao #define __atomic_add_int(p, v, t) \ 83c563d533SMarcel Moolenaar __asm __volatile( \ 84c563d533SMarcel Moolenaar "1: lwarx %0, 0, %2\n" \ 85c563d533SMarcel Moolenaar " add %0, %3, %0\n" \ 86c563d533SMarcel Moolenaar " stwcx. %0, 0, %2\n" \ 87c563d533SMarcel Moolenaar " bne- 1b\n" \ 88c563d533SMarcel Moolenaar : "=&r" (t), "=m" (*p) \ 89c563d533SMarcel Moolenaar : "r" (p), "r" (v), "m" (*p) \ 90181ca73bSJustin Hibbits : "cr0", "memory") \ 91dc6dc1f5SAttilio Rao /* __atomic_add_int */ 92b5073b49SDavid E. O'Brien 93c3e289e1SNathan Whitehorn #ifdef __powerpc64__ 94dc6dc1f5SAttilio Rao #define __atomic_add_long(p, v, t) \ 95c3e289e1SNathan Whitehorn __asm __volatile( \ 96c3e289e1SNathan Whitehorn "1: ldarx %0, 0, %2\n" \ 97c3e289e1SNathan Whitehorn " add %0, %3, %0\n" \ 98c3e289e1SNathan Whitehorn " stdcx. %0, 0, %2\n" \ 99c3e289e1SNathan Whitehorn " bne- 1b\n" \ 100c3e289e1SNathan Whitehorn : "=&r" (t), "=m" (*p) \ 101c3e289e1SNathan Whitehorn : "r" (p), "r" (v), "m" (*p) \ 102181ca73bSJustin Hibbits : "cr0", "memory") \ 103dc6dc1f5SAttilio Rao /* __atomic_add_long */ 104c3e289e1SNathan Whitehorn #else 105dc6dc1f5SAttilio Rao #define __atomic_add_long(p, v, t) \ 106dc6dc1f5SAttilio Rao __asm __volatile( \ 107dc6dc1f5SAttilio Rao "1: lwarx %0, 0, %2\n" \ 108dc6dc1f5SAttilio Rao " add %0, %3, %0\n" \ 109dc6dc1f5SAttilio Rao " stwcx. %0, 0, %2\n" \ 110dc6dc1f5SAttilio Rao " bne- 1b\n" \ 111dc6dc1f5SAttilio Rao : "=&r" (t), "=m" (*p) \ 112dc6dc1f5SAttilio Rao : "r" (p), "r" (v), "m" (*p) \ 113181ca73bSJustin Hibbits : "cr0", "memory") \ 114dc6dc1f5SAttilio Rao /* __atomic_add_long */ 115c3e289e1SNathan Whitehorn #endif 116c563d533SMarcel Moolenaar 117dc6dc1f5SAttilio Rao #define _ATOMIC_ADD(type) \ 118c563d533SMarcel Moolenaar static __inline void \ 119dc6dc1f5SAttilio Rao atomic_add_##type(volatile u_##type *p, u_##type v) { \ 120dc6dc1f5SAttilio Rao u_##type t; \ 121dc6dc1f5SAttilio Rao __atomic_add_##type(p, v, t); \ 122c563d533SMarcel Moolenaar } \ 123c563d533SMarcel Moolenaar \ 124c563d533SMarcel Moolenaar static __inline void \ 125dc6dc1f5SAttilio Rao atomic_add_acq_##type(volatile u_##type *p, u_##type v) { \ 126dc6dc1f5SAttilio Rao u_##type t; \ 127dc6dc1f5SAttilio Rao __atomic_add_##type(p, v, t); \ 128a4cbf436SNathan Whitehorn __ATOMIC_ACQ(); \ 129c563d533SMarcel Moolenaar } \ 130c563d533SMarcel Moolenaar \ 131c563d533SMarcel Moolenaar static __inline void \ 132dc6dc1f5SAttilio Rao atomic_add_rel_##type(volatile u_##type *p, u_##type v) { \ 133dc6dc1f5SAttilio Rao u_##type t; \ 134a4cbf436SNathan Whitehorn __ATOMIC_REL(); \ 135dc6dc1f5SAttilio Rao __atomic_add_##type(p, v, t); \ 136c563d533SMarcel Moolenaar } \ 137c563d533SMarcel Moolenaar /* _ATOMIC_ADD */ 138c563d533SMarcel Moolenaar 139dc6dc1f5SAttilio Rao _ATOMIC_ADD(int) 140dc6dc1f5SAttilio Rao _ATOMIC_ADD(long) 141b5073b49SDavid E. O'Brien 142dc6dc1f5SAttilio Rao #define atomic_add_32 atomic_add_int 143dc6dc1f5SAttilio Rao #define atomic_add_acq_32 atomic_add_acq_int 144dc6dc1f5SAttilio Rao #define atomic_add_rel_32 atomic_add_rel_int 145dc6dc1f5SAttilio Rao 146dc6dc1f5SAttilio Rao #ifdef __powerpc64__ 147dc6dc1f5SAttilio Rao #define atomic_add_64 atomic_add_long 148dc6dc1f5SAttilio Rao #define atomic_add_acq_64 atomic_add_acq_long 149dc6dc1f5SAttilio Rao #define atomic_add_rel_64 atomic_add_rel_long 150dc6dc1f5SAttilio Rao 151dc6dc1f5SAttilio Rao #define atomic_add_ptr atomic_add_long 152dc6dc1f5SAttilio Rao #define atomic_add_acq_ptr atomic_add_acq_long 153dc6dc1f5SAttilio Rao #define atomic_add_rel_ptr atomic_add_rel_long 154dc6dc1f5SAttilio Rao #else 155dc6dc1f5SAttilio Rao #define atomic_add_ptr atomic_add_int 156dc6dc1f5SAttilio Rao #define atomic_add_acq_ptr atomic_add_acq_int 157dc6dc1f5SAttilio Rao #define atomic_add_rel_ptr atomic_add_rel_int 158dc6dc1f5SAttilio Rao #endif 159c563d533SMarcel Moolenaar #undef _ATOMIC_ADD 160dc6dc1f5SAttilio Rao #undef __atomic_add_long 161dc6dc1f5SAttilio Rao #undef __atomic_add_int 162b5073b49SDavid E. O'Brien 163c563d533SMarcel Moolenaar /* 164c563d533SMarcel Moolenaar * atomic_clear(p, v) 165c563d533SMarcel Moolenaar * { *p &= ~v; } 166c563d533SMarcel Moolenaar */ 167c563d533SMarcel Moolenaar 168dc6dc1f5SAttilio Rao #define __atomic_clear_int(p, v, t) \ 169c563d533SMarcel Moolenaar __asm __volatile( \ 170c563d533SMarcel Moolenaar "1: lwarx %0, 0, %2\n" \ 171c563d533SMarcel Moolenaar " andc %0, %0, %3\n" \ 172c563d533SMarcel Moolenaar " stwcx. %0, 0, %2\n" \ 173c563d533SMarcel Moolenaar " bne- 1b\n" \ 174c563d533SMarcel Moolenaar : "=&r" (t), "=m" (*p) \ 175c563d533SMarcel Moolenaar : "r" (p), "r" (v), "m" (*p) \ 176181ca73bSJustin Hibbits : "cr0", "memory") \ 177dc6dc1f5SAttilio Rao /* __atomic_clear_int */ 178c563d533SMarcel Moolenaar 179c3e289e1SNathan Whitehorn #ifdef __powerpc64__ 180dc6dc1f5SAttilio Rao #define __atomic_clear_long(p, v, t) \ 181c3e289e1SNathan Whitehorn __asm __volatile( \ 182c3e289e1SNathan Whitehorn "1: ldarx %0, 0, %2\n" \ 183c3e289e1SNathan Whitehorn " andc %0, %0, %3\n" \ 184c3e289e1SNathan Whitehorn " stdcx. %0, 0, %2\n" \ 185c3e289e1SNathan Whitehorn " bne- 1b\n" \ 186c3e289e1SNathan Whitehorn : "=&r" (t), "=m" (*p) \ 187c3e289e1SNathan Whitehorn : "r" (p), "r" (v), "m" (*p) \ 188181ca73bSJustin Hibbits : "cr0", "memory") \ 189dc6dc1f5SAttilio Rao /* __atomic_clear_long */ 190c3e289e1SNathan Whitehorn #else 191dc6dc1f5SAttilio Rao #define __atomic_clear_long(p, v, t) \ 192dc6dc1f5SAttilio Rao __asm __volatile( \ 193dc6dc1f5SAttilio Rao "1: lwarx %0, 0, %2\n" \ 194dc6dc1f5SAttilio Rao " andc %0, %0, %3\n" \ 195dc6dc1f5SAttilio Rao " stwcx. %0, 0, %2\n" \ 196dc6dc1f5SAttilio Rao " bne- 1b\n" \ 197dc6dc1f5SAttilio Rao : "=&r" (t), "=m" (*p) \ 198dc6dc1f5SAttilio Rao : "r" (p), "r" (v), "m" (*p) \ 199181ca73bSJustin Hibbits : "cr0", "memory") \ 200dc6dc1f5SAttilio Rao /* __atomic_clear_long */ 201c3e289e1SNathan Whitehorn #endif 202c563d533SMarcel Moolenaar 203dc6dc1f5SAttilio Rao #define _ATOMIC_CLEAR(type) \ 204c563d533SMarcel Moolenaar static __inline void \ 205dc6dc1f5SAttilio Rao atomic_clear_##type(volatile u_##type *p, u_##type v) { \ 206dc6dc1f5SAttilio Rao u_##type t; \ 207dc6dc1f5SAttilio Rao __atomic_clear_##type(p, v, t); \ 208c563d533SMarcel Moolenaar } \ 209c563d533SMarcel Moolenaar \ 210c563d533SMarcel Moolenaar static __inline void \ 211dc6dc1f5SAttilio Rao atomic_clear_acq_##type(volatile u_##type *p, u_##type v) { \ 212dc6dc1f5SAttilio Rao u_##type t; \ 213dc6dc1f5SAttilio Rao __atomic_clear_##type(p, v, t); \ 214a4cbf436SNathan Whitehorn __ATOMIC_ACQ(); \ 215c563d533SMarcel Moolenaar } \ 216c563d533SMarcel Moolenaar \ 217c563d533SMarcel Moolenaar static __inline void \ 218dc6dc1f5SAttilio Rao atomic_clear_rel_##type(volatile u_##type *p, u_##type v) { \ 219dc6dc1f5SAttilio Rao u_##type t; \ 220a4cbf436SNathan Whitehorn __ATOMIC_REL(); \ 221dc6dc1f5SAttilio Rao __atomic_clear_##type(p, v, t); \ 222c563d533SMarcel Moolenaar } \ 223c563d533SMarcel Moolenaar /* _ATOMIC_CLEAR */ 224c563d533SMarcel Moolenaar 225dc6dc1f5SAttilio Rao _ATOMIC_CLEAR(int) 226dc6dc1f5SAttilio Rao _ATOMIC_CLEAR(long) 227dc6dc1f5SAttilio Rao 228dc6dc1f5SAttilio Rao #define atomic_clear_32 atomic_clear_int 229dc6dc1f5SAttilio Rao #define atomic_clear_acq_32 atomic_clear_acq_int 230dc6dc1f5SAttilio Rao #define atomic_clear_rel_32 atomic_clear_rel_int 231dc6dc1f5SAttilio Rao 232dc6dc1f5SAttilio Rao #ifdef __powerpc64__ 233dc6dc1f5SAttilio Rao #define atomic_clear_64 atomic_clear_long 234dc6dc1f5SAttilio Rao #define atomic_clear_acq_64 atomic_clear_acq_long 235dc6dc1f5SAttilio Rao #define atomic_clear_rel_64 atomic_clear_rel_long 236dc6dc1f5SAttilio Rao 237dc6dc1f5SAttilio Rao #define atomic_clear_ptr atomic_clear_long 238dc6dc1f5SAttilio Rao #define atomic_clear_acq_ptr atomic_clear_acq_long 239dc6dc1f5SAttilio Rao #define atomic_clear_rel_ptr atomic_clear_rel_long 240dc6dc1f5SAttilio Rao #else 241dc6dc1f5SAttilio Rao #define atomic_clear_ptr atomic_clear_int 242dc6dc1f5SAttilio Rao #define atomic_clear_acq_ptr atomic_clear_acq_int 243dc6dc1f5SAttilio Rao #define atomic_clear_rel_ptr atomic_clear_rel_int 244dc6dc1f5SAttilio Rao #endif 245c563d533SMarcel Moolenaar #undef _ATOMIC_CLEAR 246dc6dc1f5SAttilio Rao #undef __atomic_clear_long 247dc6dc1f5SAttilio Rao #undef __atomic_clear_int 248c563d533SMarcel Moolenaar 249c563d533SMarcel Moolenaar /* 250c563d533SMarcel Moolenaar * atomic_cmpset(p, o, n) 251c563d533SMarcel Moolenaar */ 252c563d533SMarcel Moolenaar /* TODO -- see below */ 253c563d533SMarcel Moolenaar 254c563d533SMarcel Moolenaar /* 255c563d533SMarcel Moolenaar * atomic_load_acq(p) 256c563d533SMarcel Moolenaar */ 257c563d533SMarcel Moolenaar /* TODO -- see below */ 258c563d533SMarcel Moolenaar 259c563d533SMarcel Moolenaar /* 260c563d533SMarcel Moolenaar * atomic_readandclear(p) 261c563d533SMarcel Moolenaar */ 262c563d533SMarcel Moolenaar /* TODO -- see below */ 263c563d533SMarcel Moolenaar 264c563d533SMarcel Moolenaar /* 265c563d533SMarcel Moolenaar * atomic_set(p, v) 266c563d533SMarcel Moolenaar * { *p |= v; } 267c563d533SMarcel Moolenaar */ 268c563d533SMarcel Moolenaar 269dc6dc1f5SAttilio Rao #define __atomic_set_int(p, v, t) \ 270c563d533SMarcel Moolenaar __asm __volatile( \ 271c563d533SMarcel Moolenaar "1: lwarx %0, 0, %2\n" \ 272c563d533SMarcel Moolenaar " or %0, %3, %0\n" \ 273c563d533SMarcel Moolenaar " stwcx. %0, 0, %2\n" \ 274c563d533SMarcel Moolenaar " bne- 1b\n" \ 275c563d533SMarcel Moolenaar : "=&r" (t), "=m" (*p) \ 276c563d533SMarcel Moolenaar : "r" (p), "r" (v), "m" (*p) \ 277181ca73bSJustin Hibbits : "cr0", "memory") \ 278dc6dc1f5SAttilio Rao /* __atomic_set_int */ 279c563d533SMarcel Moolenaar 280c3e289e1SNathan Whitehorn #ifdef __powerpc64__ 281dc6dc1f5SAttilio Rao #define __atomic_set_long(p, v, t) \ 282c3e289e1SNathan Whitehorn __asm __volatile( \ 283c3e289e1SNathan Whitehorn "1: ldarx %0, 0, %2\n" \ 284c3e289e1SNathan Whitehorn " or %0, %3, %0\n" \ 285c3e289e1SNathan Whitehorn " stdcx. %0, 0, %2\n" \ 286c3e289e1SNathan Whitehorn " bne- 1b\n" \ 287c3e289e1SNathan Whitehorn : "=&r" (t), "=m" (*p) \ 288c3e289e1SNathan Whitehorn : "r" (p), "r" (v), "m" (*p) \ 289181ca73bSJustin Hibbits : "cr0", "memory") \ 290dc6dc1f5SAttilio Rao /* __atomic_set_long */ 291c3e289e1SNathan Whitehorn #else 292dc6dc1f5SAttilio Rao #define __atomic_set_long(p, v, t) \ 293dc6dc1f5SAttilio Rao __asm __volatile( \ 294dc6dc1f5SAttilio Rao "1: lwarx %0, 0, %2\n" \ 295dc6dc1f5SAttilio Rao " or %0, %3, %0\n" \ 296dc6dc1f5SAttilio Rao " stwcx. %0, 0, %2\n" \ 297dc6dc1f5SAttilio Rao " bne- 1b\n" \ 298dc6dc1f5SAttilio Rao : "=&r" (t), "=m" (*p) \ 299dc6dc1f5SAttilio Rao : "r" (p), "r" (v), "m" (*p) \ 300181ca73bSJustin Hibbits : "cr0", "memory") \ 301dc6dc1f5SAttilio Rao /* __atomic_set_long */ 302c3e289e1SNathan Whitehorn #endif 303c563d533SMarcel Moolenaar 304dc6dc1f5SAttilio Rao #define _ATOMIC_SET(type) \ 305c563d533SMarcel Moolenaar static __inline void \ 306dc6dc1f5SAttilio Rao atomic_set_##type(volatile u_##type *p, u_##type v) { \ 307dc6dc1f5SAttilio Rao u_##type t; \ 308dc6dc1f5SAttilio Rao __atomic_set_##type(p, v, t); \ 309c563d533SMarcel Moolenaar } \ 310c563d533SMarcel Moolenaar \ 311c563d533SMarcel Moolenaar static __inline void \ 312dc6dc1f5SAttilio Rao atomic_set_acq_##type(volatile u_##type *p, u_##type v) { \ 313dc6dc1f5SAttilio Rao u_##type t; \ 314dc6dc1f5SAttilio Rao __atomic_set_##type(p, v, t); \ 315a4cbf436SNathan Whitehorn __ATOMIC_ACQ(); \ 316c563d533SMarcel Moolenaar } \ 317c563d533SMarcel Moolenaar \ 318c563d533SMarcel Moolenaar static __inline void \ 319dc6dc1f5SAttilio Rao atomic_set_rel_##type(volatile u_##type *p, u_##type v) { \ 320dc6dc1f5SAttilio Rao u_##type t; \ 321a4cbf436SNathan Whitehorn __ATOMIC_REL(); \ 322dc6dc1f5SAttilio Rao __atomic_set_##type(p, v, t); \ 323c563d533SMarcel Moolenaar } \ 324c563d533SMarcel Moolenaar /* _ATOMIC_SET */ 325c563d533SMarcel Moolenaar 326dc6dc1f5SAttilio Rao _ATOMIC_SET(int) 327dc6dc1f5SAttilio Rao _ATOMIC_SET(long) 328c563d533SMarcel Moolenaar 329dc6dc1f5SAttilio Rao #define atomic_set_32 atomic_set_int 330dc6dc1f5SAttilio Rao #define atomic_set_acq_32 atomic_set_acq_int 331dc6dc1f5SAttilio Rao #define atomic_set_rel_32 atomic_set_rel_int 332dc6dc1f5SAttilio Rao 333dc6dc1f5SAttilio Rao #ifdef __powerpc64__ 334dc6dc1f5SAttilio Rao #define atomic_set_64 atomic_set_long 335dc6dc1f5SAttilio Rao #define atomic_set_acq_64 atomic_set_acq_long 336dc6dc1f5SAttilio Rao #define atomic_set_rel_64 atomic_set_rel_long 337dc6dc1f5SAttilio Rao 338dc6dc1f5SAttilio Rao #define atomic_set_ptr atomic_set_long 339dc6dc1f5SAttilio Rao #define atomic_set_acq_ptr atomic_set_acq_long 340dc6dc1f5SAttilio Rao #define atomic_set_rel_ptr atomic_set_rel_long 341dc6dc1f5SAttilio Rao #else 342dc6dc1f5SAttilio Rao #define atomic_set_ptr atomic_set_int 343dc6dc1f5SAttilio Rao #define atomic_set_acq_ptr atomic_set_acq_int 344dc6dc1f5SAttilio Rao #define atomic_set_rel_ptr atomic_set_rel_int 345dc6dc1f5SAttilio Rao #endif 346c563d533SMarcel Moolenaar #undef _ATOMIC_SET 347dc6dc1f5SAttilio Rao #undef __atomic_set_long 348dc6dc1f5SAttilio Rao #undef __atomic_set_int 349c563d533SMarcel Moolenaar 350c563d533SMarcel Moolenaar /* 351c563d533SMarcel Moolenaar * atomic_subtract(p, v) 352c563d533SMarcel Moolenaar * { *p -= v; } 353c563d533SMarcel Moolenaar */ 354c563d533SMarcel Moolenaar 355dc6dc1f5SAttilio Rao #define __atomic_subtract_int(p, v, t) \ 356c563d533SMarcel Moolenaar __asm __volatile( \ 357c563d533SMarcel Moolenaar "1: lwarx %0, 0, %2\n" \ 358c563d533SMarcel Moolenaar " subf %0, %3, %0\n" \ 359c563d533SMarcel Moolenaar " stwcx. %0, 0, %2\n" \ 360c563d533SMarcel Moolenaar " bne- 1b\n" \ 361c563d533SMarcel Moolenaar : "=&r" (t), "=m" (*p) \ 362c563d533SMarcel Moolenaar : "r" (p), "r" (v), "m" (*p) \ 363181ca73bSJustin Hibbits : "cr0", "memory") \ 364dc6dc1f5SAttilio Rao /* __atomic_subtract_int */ 365c563d533SMarcel Moolenaar 366c3e289e1SNathan Whitehorn #ifdef __powerpc64__ 367dc6dc1f5SAttilio Rao #define __atomic_subtract_long(p, v, t) \ 368c3e289e1SNathan Whitehorn __asm __volatile( \ 369c3e289e1SNathan Whitehorn "1: ldarx %0, 0, %2\n" \ 370c3e289e1SNathan Whitehorn " subf %0, %3, %0\n" \ 371c3e289e1SNathan Whitehorn " stdcx. %0, 0, %2\n" \ 372c3e289e1SNathan Whitehorn " bne- 1b\n" \ 373c3e289e1SNathan Whitehorn : "=&r" (t), "=m" (*p) \ 374c3e289e1SNathan Whitehorn : "r" (p), "r" (v), "m" (*p) \ 375181ca73bSJustin Hibbits : "cr0", "memory") \ 376dc6dc1f5SAttilio Rao /* __atomic_subtract_long */ 377c3e289e1SNathan Whitehorn #else 378dc6dc1f5SAttilio Rao #define __atomic_subtract_long(p, v, t) \ 379dc6dc1f5SAttilio Rao __asm __volatile( \ 380dc6dc1f5SAttilio Rao "1: lwarx %0, 0, %2\n" \ 381dc6dc1f5SAttilio Rao " subf %0, %3, %0\n" \ 382dc6dc1f5SAttilio Rao " stwcx. %0, 0, %2\n" \ 383dc6dc1f5SAttilio Rao " bne- 1b\n" \ 384dc6dc1f5SAttilio Rao : "=&r" (t), "=m" (*p) \ 385dc6dc1f5SAttilio Rao : "r" (p), "r" (v), "m" (*p) \ 386181ca73bSJustin Hibbits : "cr0", "memory") \ 387dc6dc1f5SAttilio Rao /* __atomic_subtract_long */ 388c3e289e1SNathan Whitehorn #endif 389c563d533SMarcel Moolenaar 390dc6dc1f5SAttilio Rao #define _ATOMIC_SUBTRACT(type) \ 391c563d533SMarcel Moolenaar static __inline void \ 392dc6dc1f5SAttilio Rao atomic_subtract_##type(volatile u_##type *p, u_##type v) { \ 393dc6dc1f5SAttilio Rao u_##type t; \ 394dc6dc1f5SAttilio Rao __atomic_subtract_##type(p, v, t); \ 395c563d533SMarcel Moolenaar } \ 396c563d533SMarcel Moolenaar \ 397c563d533SMarcel Moolenaar static __inline void \ 398dc6dc1f5SAttilio Rao atomic_subtract_acq_##type(volatile u_##type *p, u_##type v) { \ 399dc6dc1f5SAttilio Rao u_##type t; \ 400dc6dc1f5SAttilio Rao __atomic_subtract_##type(p, v, t); \ 401a4cbf436SNathan Whitehorn __ATOMIC_ACQ(); \ 402c563d533SMarcel Moolenaar } \ 403c563d533SMarcel Moolenaar \ 404c563d533SMarcel Moolenaar static __inline void \ 405dc6dc1f5SAttilio Rao atomic_subtract_rel_##type(volatile u_##type *p, u_##type v) { \ 406dc6dc1f5SAttilio Rao u_##type t; \ 407a4cbf436SNathan Whitehorn __ATOMIC_REL(); \ 408dc6dc1f5SAttilio Rao __atomic_subtract_##type(p, v, t); \ 409c563d533SMarcel Moolenaar } \ 410c563d533SMarcel Moolenaar /* _ATOMIC_SUBTRACT */ 411c563d533SMarcel Moolenaar 412dc6dc1f5SAttilio Rao _ATOMIC_SUBTRACT(int) 413dc6dc1f5SAttilio Rao _ATOMIC_SUBTRACT(long) 414c563d533SMarcel Moolenaar 415dc6dc1f5SAttilio Rao #define atomic_subtract_32 atomic_subtract_int 416dc6dc1f5SAttilio Rao #define atomic_subtract_acq_32 atomic_subtract_acq_int 417dc6dc1f5SAttilio Rao #define atomic_subtract_rel_32 atomic_subtract_rel_int 418dc6dc1f5SAttilio Rao 419dc6dc1f5SAttilio Rao #ifdef __powerpc64__ 420dc6dc1f5SAttilio Rao #define atomic_subtract_64 atomic_subtract_long 421dc6dc1f5SAttilio Rao #define atomic_subtract_acq_64 atomic_subract_acq_long 422dc6dc1f5SAttilio Rao #define atomic_subtract_rel_64 atomic_subtract_rel_long 423dc6dc1f5SAttilio Rao 424dc6dc1f5SAttilio Rao #define atomic_subtract_ptr atomic_subtract_long 425dc6dc1f5SAttilio Rao #define atomic_subtract_acq_ptr atomic_subtract_acq_long 426dc6dc1f5SAttilio Rao #define atomic_subtract_rel_ptr atomic_subtract_rel_long 427dc6dc1f5SAttilio Rao #else 428dc6dc1f5SAttilio Rao #define atomic_subtract_ptr atomic_subtract_int 429dc6dc1f5SAttilio Rao #define atomic_subtract_acq_ptr atomic_subtract_acq_int 430dc6dc1f5SAttilio Rao #define atomic_subtract_rel_ptr atomic_subtract_rel_int 431dc6dc1f5SAttilio Rao #endif 432c563d533SMarcel Moolenaar #undef _ATOMIC_SUBTRACT 433dc6dc1f5SAttilio Rao #undef __atomic_subtract_long 434dc6dc1f5SAttilio Rao #undef __atomic_subtract_int 435c563d533SMarcel Moolenaar 436c563d533SMarcel Moolenaar /* 437c563d533SMarcel Moolenaar * atomic_store_rel(p, v) 438c563d533SMarcel Moolenaar */ 439c563d533SMarcel Moolenaar /* TODO -- see below */ 440c563d533SMarcel Moolenaar 441c563d533SMarcel Moolenaar /* 442c563d533SMarcel Moolenaar * Old/original implementations that still need revisiting. 443c563d533SMarcel Moolenaar */ 444b5073b49SDavid E. O'Brien 445dc6dc1f5SAttilio Rao static __inline u_int 446dc6dc1f5SAttilio Rao atomic_readandclear_int(volatile u_int *addr) 447b5073b49SDavid E. O'Brien { 448dc6dc1f5SAttilio Rao u_int result,temp; 449b5073b49SDavid E. O'Brien 450b5073b49SDavid E. O'Brien __asm __volatile ( 4518e9238c6SPeter Grehan "\tsync\n" /* drain writes */ 4528e9238c6SPeter Grehan "1:\tlwarx %0, 0, %3\n\t" /* load old value */ 453199a2415SBenno Rice "li %1, 0\n\t" /* load new value */ 4548e9238c6SPeter Grehan "stwcx. %1, 0, %3\n\t" /* attempt to store */ 4556e1073f0SPeter Grehan "bne- 1b\n\t" /* spin if failed */ 45680d52f16SJohn Baldwin : "=&r"(result), "=&r"(temp), "=m" (*addr) 45780d52f16SJohn Baldwin : "r" (addr), "m" (*addr) 458181ca73bSJustin Hibbits : "cr0", "memory"); 459b5073b49SDavid E. O'Brien 4608e9238c6SPeter Grehan return (result); 461b5073b49SDavid E. O'Brien } 462b5073b49SDavid E. O'Brien 463c3e289e1SNathan Whitehorn #ifdef __powerpc64__ 464dc6dc1f5SAttilio Rao static __inline u_long 465dc6dc1f5SAttilio Rao atomic_readandclear_long(volatile u_long *addr) 466c3e289e1SNathan Whitehorn { 467dc6dc1f5SAttilio Rao u_long result,temp; 468c3e289e1SNathan Whitehorn 469c3e289e1SNathan Whitehorn __asm __volatile ( 470c3e289e1SNathan Whitehorn "\tsync\n" /* drain writes */ 471c3e289e1SNathan Whitehorn "1:\tldarx %0, 0, %3\n\t" /* load old value */ 472c3e289e1SNathan Whitehorn "li %1, 0\n\t" /* load new value */ 473c3e289e1SNathan Whitehorn "stdcx. %1, 0, %3\n\t" /* attempt to store */ 474c3e289e1SNathan Whitehorn "bne- 1b\n\t" /* spin if failed */ 475c3e289e1SNathan Whitehorn : "=&r"(result), "=&r"(temp), "=m" (*addr) 476c3e289e1SNathan Whitehorn : "r" (addr), "m" (*addr) 477181ca73bSJustin Hibbits : "cr0", "memory"); 478c3e289e1SNathan Whitehorn 479c3e289e1SNathan Whitehorn return (result); 480c3e289e1SNathan Whitehorn } 481c3e289e1SNathan Whitehorn #endif 482c3e289e1SNathan Whitehorn 483dc6dc1f5SAttilio Rao #define atomic_readandclear_32 atomic_readandclear_int 484c3e289e1SNathan Whitehorn 485c3e289e1SNathan Whitehorn #ifdef __powerpc64__ 486dc6dc1f5SAttilio Rao #define atomic_readandclear_64 atomic_readandclear_long 487dc6dc1f5SAttilio Rao 488dc6dc1f5SAttilio Rao #define atomic_readandclear_ptr atomic_readandclear_long 489c3e289e1SNathan Whitehorn #else 490dc6dc1f5SAttilio Rao static __inline u_long 491dc6dc1f5SAttilio Rao atomic_readandclear_long(volatile u_long *addr) 492dc6dc1f5SAttilio Rao { 493dc6dc1f5SAttilio Rao 494dc6dc1f5SAttilio Rao return ((u_long)atomic_readandclear_int((volatile u_int *)addr)); 495dc6dc1f5SAttilio Rao } 496dc6dc1f5SAttilio Rao 497dc6dc1f5SAttilio Rao #define atomic_readandclear_ptr atomic_readandclear_int 498c3e289e1SNathan Whitehorn #endif 499122eceefSJohn Baldwin 500199a2415SBenno Rice /* 501199a2415SBenno Rice * We assume that a = b will do atomic loads and stores. 502199a2415SBenno Rice */ 503dc6dc1f5SAttilio Rao #define ATOMIC_STORE_LOAD(TYPE) \ 504199a2415SBenno Rice static __inline u_##TYPE \ 505*5e9a82e8SOlivier Certner atomic_load_acq_##TYPE(const volatile u_##TYPE *p) \ 506199a2415SBenno Rice { \ 5078e9238c6SPeter Grehan u_##TYPE v; \ 5088e9238c6SPeter Grehan \ 5098e9238c6SPeter Grehan v = *p; \ 5106a0fd1a5SJustin Hibbits powerpc_lwsync(); \ 5118e9238c6SPeter Grehan return (v); \ 512199a2415SBenno Rice } \ 513199a2415SBenno Rice \ 514199a2415SBenno Rice static __inline void \ 515199a2415SBenno Rice atomic_store_rel_##TYPE(volatile u_##TYPE *p, u_##TYPE v) \ 516199a2415SBenno Rice { \ 5170b39ffb3SKonstantin Belousov \ 5180b39ffb3SKonstantin Belousov powerpc_lwsync(); \ 5198e9238c6SPeter Grehan *p = v; \ 520199a2415SBenno Rice } 521199a2415SBenno Rice 522dc6dc1f5SAttilio Rao ATOMIC_STORE_LOAD(int) 523dc6dc1f5SAttilio Rao 524dc6dc1f5SAttilio Rao #define atomic_load_acq_32 atomic_load_acq_int 525dc6dc1f5SAttilio Rao #define atomic_store_rel_32 atomic_store_rel_int 526199a2415SBenno Rice 527c3e289e1SNathan Whitehorn #ifdef __powerpc64__ 528dc6dc1f5SAttilio Rao ATOMIC_STORE_LOAD(long) 529dc6dc1f5SAttilio Rao 530dc6dc1f5SAttilio Rao #define atomic_load_acq_64 atomic_load_acq_long 531dc6dc1f5SAttilio Rao #define atomic_store_rel_64 atomic_store_rel_long 532dc6dc1f5SAttilio Rao 533dc6dc1f5SAttilio Rao #define atomic_load_acq_ptr atomic_load_acq_long 534dc6dc1f5SAttilio Rao #define atomic_store_rel_ptr atomic_store_rel_long 535c3e289e1SNathan Whitehorn #else 536dc6dc1f5SAttilio Rao static __inline u_long 537*5e9a82e8SOlivier Certner atomic_load_acq_long(const volatile u_long *addr) 538dc6dc1f5SAttilio Rao { 539122eceefSJohn Baldwin 540*5e9a82e8SOlivier Certner return ((u_long)atomic_load_acq_int((const volatile u_int *)addr)); 541dc6dc1f5SAttilio Rao } 542dc6dc1f5SAttilio Rao 543dc6dc1f5SAttilio Rao static __inline void 544dc6dc1f5SAttilio Rao atomic_store_rel_long(volatile u_long *addr, u_long val) 545dc6dc1f5SAttilio Rao { 546dc6dc1f5SAttilio Rao 547dc6dc1f5SAttilio Rao atomic_store_rel_int((volatile u_int *)addr, (u_int)val); 548dc6dc1f5SAttilio Rao } 549dc6dc1f5SAttilio Rao 550dc6dc1f5SAttilio Rao #define atomic_load_acq_ptr atomic_load_acq_int 551dc6dc1f5SAttilio Rao #define atomic_store_rel_ptr atomic_store_rel_int 552dc6dc1f5SAttilio Rao #endif 553199a2415SBenno Rice #undef ATOMIC_STORE_LOAD 554199a2415SBenno Rice 555b5073b49SDavid E. O'Brien /* 556b5073b49SDavid E. O'Brien * Atomically compare the value stored at *p with cmpval and if the 557b5073b49SDavid E. O'Brien * two values are equal, update the value of *p with newval. Returns 558b5073b49SDavid E. O'Brien * zero if the compare failed, nonzero otherwise. 559b5073b49SDavid E. O'Brien */ 56084046d16SJustin Hibbits #ifdef ISA_206_ATOMICS 56184046d16SJustin Hibbits static __inline int 56284046d16SJustin Hibbits atomic_cmpset_char(volatile u_char *p, u_char cmpval, u_char newval) 56384046d16SJustin Hibbits { 56484046d16SJustin Hibbits int ret; 56584046d16SJustin Hibbits 56684046d16SJustin Hibbits __asm __volatile ( 56784046d16SJustin Hibbits "1:\tlbarx %0, 0, %2\n\t" /* load old value */ 56884046d16SJustin Hibbits "cmplw %3, %0\n\t" /* compare */ 56984046d16SJustin Hibbits "bne- 2f\n\t" /* exit if not equal */ 57084046d16SJustin Hibbits "stbcx. %4, 0, %2\n\t" /* attempt to store */ 57184046d16SJustin Hibbits "bne- 1b\n\t" /* spin if failed */ 57284046d16SJustin Hibbits "li %0, 1\n\t" /* success - retval = 1 */ 57384046d16SJustin Hibbits "b 3f\n\t" /* we've succeeded */ 57484046d16SJustin Hibbits "2:\n\t" 57584046d16SJustin Hibbits "stbcx. %0, 0, %2\n\t" /* clear reservation (74xx) */ 57684046d16SJustin Hibbits "li %0, 0\n\t" /* failure - retval = 0 */ 57784046d16SJustin Hibbits "3:\n\t" 57884046d16SJustin Hibbits : "=&r" (ret), "=m" (*p) 57984046d16SJustin Hibbits : "r" (p), "r" (cmpval), "r" (newval), "m" (*p) 58084046d16SJustin Hibbits : "cr0", "memory"); 58184046d16SJustin Hibbits 58284046d16SJustin Hibbits return (ret); 58384046d16SJustin Hibbits } 58484046d16SJustin Hibbits 58584046d16SJustin Hibbits static __inline int 58684046d16SJustin Hibbits atomic_cmpset_short(volatile u_short *p, u_short cmpval, u_short newval) 58784046d16SJustin Hibbits { 58884046d16SJustin Hibbits int ret; 58984046d16SJustin Hibbits 59084046d16SJustin Hibbits __asm __volatile ( 59184046d16SJustin Hibbits "1:\tlharx %0, 0, %2\n\t" /* load old value */ 59284046d16SJustin Hibbits "cmplw %3, %0\n\t" /* compare */ 59384046d16SJustin Hibbits "bne- 2f\n\t" /* exit if not equal */ 59484046d16SJustin Hibbits "sthcx. %4, 0, %2\n\t" /* attempt to store */ 59584046d16SJustin Hibbits "bne- 1b\n\t" /* spin if failed */ 59684046d16SJustin Hibbits "li %0, 1\n\t" /* success - retval = 1 */ 59784046d16SJustin Hibbits "b 3f\n\t" /* we've succeeded */ 59884046d16SJustin Hibbits "2:\n\t" 59984046d16SJustin Hibbits "sthcx. %0, 0, %2\n\t" /* clear reservation (74xx) */ 60084046d16SJustin Hibbits "li %0, 0\n\t" /* failure - retval = 0 */ 60184046d16SJustin Hibbits "3:\n\t" 60284046d16SJustin Hibbits : "=&r" (ret), "=m" (*p) 60384046d16SJustin Hibbits : "r" (p), "r" (cmpval), "r" (newval), "m" (*p) 60484046d16SJustin Hibbits : "cr0", "memory"); 60584046d16SJustin Hibbits 60684046d16SJustin Hibbits return (ret); 60784046d16SJustin Hibbits } 608d0bdb111SJustin Hibbits #else 609d0bdb111SJustin Hibbits static __inline int 610d0bdb111SJustin Hibbits atomic_cmpset_masked(uint32_t *p, uint32_t cmpval, uint32_t newval, 611d0bdb111SJustin Hibbits uint32_t mask) 612d0bdb111SJustin Hibbits { 613d0bdb111SJustin Hibbits int ret; 614d0bdb111SJustin Hibbits uint32_t tmp; 615d0bdb111SJustin Hibbits 616d0bdb111SJustin Hibbits __asm __volatile ( 6179941cb06SBrandon Bergren "1:\tlwarx %2, 0, %3\n\t" /* load old value */ 618d0bdb111SJustin Hibbits "and %0, %2, %7\n\t" 619d0bdb111SJustin Hibbits "cmplw %4, %0\n\t" /* compare */ 620d0bdb111SJustin Hibbits "bne- 2f\n\t" /* exit if not equal */ 621d0bdb111SJustin Hibbits "andc %2, %2, %7\n\t" 622d0bdb111SJustin Hibbits "or %2, %2, %5\n\t" 623d0bdb111SJustin Hibbits "stwcx. %2, 0, %3\n\t" /* attempt to store */ 624d0bdb111SJustin Hibbits "bne- 1b\n\t" /* spin if failed */ 625d0bdb111SJustin Hibbits "li %0, 1\n\t" /* success - retval = 1 */ 626d0bdb111SJustin Hibbits "b 3f\n\t" /* we've succeeded */ 627d0bdb111SJustin Hibbits "2:\n\t" 628d0bdb111SJustin Hibbits "stwcx. %2, 0, %3\n\t" /* clear reservation (74xx) */ 629d0bdb111SJustin Hibbits "li %0, 0\n\t" /* failure - retval = 0 */ 630d0bdb111SJustin Hibbits "3:\n\t" 631d0bdb111SJustin Hibbits : "=&r" (ret), "=m" (*p), "+&r" (tmp) 632d0bdb111SJustin Hibbits : "r" (p), "r" (cmpval), "r" (newval), "m" (*p), 633d0bdb111SJustin Hibbits "r" (mask) 634d0bdb111SJustin Hibbits : "cr0", "memory"); 635d0bdb111SJustin Hibbits 636d0bdb111SJustin Hibbits return (ret); 637d0bdb111SJustin Hibbits } 638d0bdb111SJustin Hibbits 639d0bdb111SJustin Hibbits #define _atomic_cmpset_masked_word(a,o,v,m) atomic_cmpset_masked(a, o, v, m) 64084046d16SJustin Hibbits #endif 64184046d16SJustin Hibbits 642c3e289e1SNathan Whitehorn static __inline int 643dc6dc1f5SAttilio Rao atomic_cmpset_int(volatile u_int* p, u_int cmpval, u_int newval) 644b5073b49SDavid E. O'Brien { 645c3e289e1SNathan Whitehorn int ret; 646b5073b49SDavid E. O'Brien 647b5073b49SDavid E. O'Brien __asm __volatile ( 6488e9238c6SPeter Grehan "1:\tlwarx %0, 0, %2\n\t" /* load old value */ 6498e9238c6SPeter Grehan "cmplw %3, %0\n\t" /* compare */ 650e44ed9d3SJustin Hibbits "bne- 2f\n\t" /* exit if not equal */ 6518e9238c6SPeter Grehan "stwcx. %4, 0, %2\n\t" /* attempt to store */ 652d27f1d4cSBenno Rice "bne- 1b\n\t" /* spin if failed */ 6538e9238c6SPeter Grehan "li %0, 1\n\t" /* success - retval = 1 */ 654dfc02c30SBenno Rice "b 3f\n\t" /* we've succeeded */ 6558e9238c6SPeter Grehan "2:\n\t" 6568e9238c6SPeter Grehan "stwcx. %0, 0, %2\n\t" /* clear reservation (74xx) */ 6578e9238c6SPeter Grehan "li %0, 0\n\t" /* failure - retval = 0 */ 6588e9238c6SPeter Grehan "3:\n\t" 65980d52f16SJohn Baldwin : "=&r" (ret), "=m" (*p) 66080d52f16SJohn Baldwin : "r" (p), "r" (cmpval), "r" (newval), "m" (*p) 661181ca73bSJustin Hibbits : "cr0", "memory"); 662b5073b49SDavid E. O'Brien 6638e9238c6SPeter Grehan return (ret); 664b5073b49SDavid E. O'Brien } 665c3e289e1SNathan Whitehorn static __inline int 666ba90c265SJohn Birrell atomic_cmpset_long(volatile u_long* p, u_long cmpval, u_long newval) 667ba90c265SJohn Birrell { 668c3e289e1SNathan Whitehorn int ret; 669ba90c265SJohn Birrell 670ba90c265SJohn Birrell __asm __volatile ( 671c3e289e1SNathan Whitehorn #ifdef __powerpc64__ 672c3e289e1SNathan Whitehorn "1:\tldarx %0, 0, %2\n\t" /* load old value */ 673c3e289e1SNathan Whitehorn "cmpld %3, %0\n\t" /* compare */ 674e44ed9d3SJustin Hibbits "bne- 2f\n\t" /* exit if not equal */ 675c3e289e1SNathan Whitehorn "stdcx. %4, 0, %2\n\t" /* attempt to store */ 676c3e289e1SNathan Whitehorn #else 677ba90c265SJohn Birrell "1:\tlwarx %0, 0, %2\n\t" /* load old value */ 678ba90c265SJohn Birrell "cmplw %3, %0\n\t" /* compare */ 679e44ed9d3SJustin Hibbits "bne- 2f\n\t" /* exit if not equal */ 680ba90c265SJohn Birrell "stwcx. %4, 0, %2\n\t" /* attempt to store */ 681c3e289e1SNathan Whitehorn #endif 682ba90c265SJohn Birrell "bne- 1b\n\t" /* spin if failed */ 683ba90c265SJohn Birrell "li %0, 1\n\t" /* success - retval = 1 */ 684ba90c265SJohn Birrell "b 3f\n\t" /* we've succeeded */ 685ba90c265SJohn Birrell "2:\n\t" 686c3e289e1SNathan Whitehorn #ifdef __powerpc64__ 687c3e289e1SNathan Whitehorn "stdcx. %0, 0, %2\n\t" /* clear reservation (74xx) */ 688c3e289e1SNathan Whitehorn #else 689ba90c265SJohn Birrell "stwcx. %0, 0, %2\n\t" /* clear reservation (74xx) */ 690c3e289e1SNathan Whitehorn #endif 691ba90c265SJohn Birrell "li %0, 0\n\t" /* failure - retval = 0 */ 692ba90c265SJohn Birrell "3:\n\t" 693ba90c265SJohn Birrell : "=&r" (ret), "=m" (*p) 694ba90c265SJohn Birrell : "r" (p), "r" (cmpval), "r" (newval), "m" (*p) 695181ca73bSJustin Hibbits : "cr0", "memory"); 696ba90c265SJohn Birrell 697ba90c265SJohn Birrell return (ret); 698ba90c265SJohn Birrell } 699ba90c265SJohn Birrell 70084046d16SJustin Hibbits #define ATOMIC_CMPSET_ACQ_REL(type) \ 70184046d16SJustin Hibbits static __inline int \ 70284046d16SJustin Hibbits atomic_cmpset_acq_##type(volatile u_##type *p, \ 70384046d16SJustin Hibbits u_##type cmpval, u_##type newval)\ 70484046d16SJustin Hibbits {\ 70584046d16SJustin Hibbits u_##type retval; \ 70684046d16SJustin Hibbits retval = atomic_cmpset_##type(p, cmpval, newval);\ 70784046d16SJustin Hibbits __ATOMIC_ACQ();\ 70884046d16SJustin Hibbits return (retval);\ 70984046d16SJustin Hibbits }\ 71084046d16SJustin Hibbits static __inline int \ 71184046d16SJustin Hibbits atomic_cmpset_rel_##type(volatile u_##type *p, \ 71284046d16SJustin Hibbits u_##type cmpval, u_##type newval)\ 71384046d16SJustin Hibbits {\ 7149551397fSJustin Hibbits __ATOMIC_REL();\ 71584046d16SJustin Hibbits return (atomic_cmpset_##type(p, cmpval, newval));\ 71684046d16SJustin Hibbits }\ 71784046d16SJustin Hibbits struct hack 718199a2415SBenno Rice 71984046d16SJustin Hibbits ATOMIC_CMPSET_ACQ_REL(int); 72084046d16SJustin Hibbits ATOMIC_CMPSET_ACQ_REL(long); 721199a2415SBenno Rice 722ca0ec73cSConrad Meyer #ifdef ISA_206_ATOMICS 72384046d16SJustin Hibbits #define atomic_cmpset_8 atomic_cmpset_char 724ca0ec73cSConrad Meyer #endif 72584046d16SJustin Hibbits #define atomic_cmpset_acq_8 atomic_cmpset_acq_char 72684046d16SJustin Hibbits #define atomic_cmpset_rel_8 atomic_cmpset_rel_char 727ba90c265SJohn Birrell 728ca0ec73cSConrad Meyer #ifdef ISA_206_ATOMICS 72984046d16SJustin Hibbits #define atomic_cmpset_16 atomic_cmpset_short 730ca0ec73cSConrad Meyer #endif 73184046d16SJustin Hibbits #define atomic_cmpset_acq_16 atomic_cmpset_acq_short 73284046d16SJustin Hibbits #define atomic_cmpset_rel_16 atomic_cmpset_rel_short 733ba90c265SJohn Birrell 734dc6dc1f5SAttilio Rao #define atomic_cmpset_32 atomic_cmpset_int 735dc6dc1f5SAttilio Rao #define atomic_cmpset_acq_32 atomic_cmpset_acq_int 736dc6dc1f5SAttilio Rao #define atomic_cmpset_rel_32 atomic_cmpset_rel_int 737c108b80cSMarcel Moolenaar 738c3e289e1SNathan Whitehorn #ifdef __powerpc64__ 739dc6dc1f5SAttilio Rao #define atomic_cmpset_64 atomic_cmpset_long 740dc6dc1f5SAttilio Rao #define atomic_cmpset_acq_64 atomic_cmpset_acq_long 741dc6dc1f5SAttilio Rao #define atomic_cmpset_rel_64 atomic_cmpset_rel_long 742dc6dc1f5SAttilio Rao 743dc6dc1f5SAttilio Rao #define atomic_cmpset_ptr atomic_cmpset_long 744dc6dc1f5SAttilio Rao #define atomic_cmpset_acq_ptr atomic_cmpset_acq_long 745dc6dc1f5SAttilio Rao #define atomic_cmpset_rel_ptr atomic_cmpset_rel_long 746c3e289e1SNathan Whitehorn #else 747dc6dc1f5SAttilio Rao #define atomic_cmpset_ptr atomic_cmpset_int 748dc6dc1f5SAttilio Rao #define atomic_cmpset_acq_ptr atomic_cmpset_acq_int 749dc6dc1f5SAttilio Rao #define atomic_cmpset_rel_ptr atomic_cmpset_rel_int 750c3e289e1SNathan Whitehorn #endif 751199a2415SBenno Rice 75202f151d4SJustin Hibbits /* 75302f151d4SJustin Hibbits * Atomically compare the value stored at *p with *cmpval and if the 75402f151d4SJustin Hibbits * two values are equal, update the value of *p with newval. Returns 75502f151d4SJustin Hibbits * zero if the compare failed and sets *cmpval to the read value from *p, 75602f151d4SJustin Hibbits * nonzero otherwise. 75702f151d4SJustin Hibbits */ 75884046d16SJustin Hibbits #ifdef ISA_206_ATOMICS 75984046d16SJustin Hibbits static __inline int 76084046d16SJustin Hibbits atomic_fcmpset_char(volatile u_char *p, u_char *cmpval, u_char newval) 76184046d16SJustin Hibbits { 76284046d16SJustin Hibbits int ret; 76384046d16SJustin Hibbits 76484046d16SJustin Hibbits __asm __volatile ( 76584046d16SJustin Hibbits "lbarx %0, 0, %3\n\t" /* load old value */ 76684046d16SJustin Hibbits "cmplw %4, %0\n\t" /* compare */ 76784046d16SJustin Hibbits "bne- 1f\n\t" /* exit if not equal */ 76884046d16SJustin Hibbits "stbcx. %5, 0, %3\n\t" /* attempt to store */ 76984046d16SJustin Hibbits "bne- 1f\n\t" /* exit if failed */ 77084046d16SJustin Hibbits "li %0, 1\n\t" /* success - retval = 1 */ 77184046d16SJustin Hibbits "b 2f\n\t" /* we've succeeded */ 77284046d16SJustin Hibbits "1:\n\t" 77384046d16SJustin Hibbits "stbcx. %0, 0, %3\n\t" /* clear reservation (74xx) */ 774895a2258SJustin Hibbits "stbx %0, 0, %7\n\t" 77584046d16SJustin Hibbits "li %0, 0\n\t" /* failure - retval = 0 */ 77684046d16SJustin Hibbits "2:\n\t" 77784046d16SJustin Hibbits : "=&r" (ret), "=m" (*p), "=m" (*cmpval) 77884046d16SJustin Hibbits : "r" (p), "r" (*cmpval), "r" (newval), "m" (*p), "r"(cmpval) 77984046d16SJustin Hibbits : "cr0", "memory"); 78084046d16SJustin Hibbits 78184046d16SJustin Hibbits return (ret); 78284046d16SJustin Hibbits } 78384046d16SJustin Hibbits 78484046d16SJustin Hibbits static __inline int 78584046d16SJustin Hibbits atomic_fcmpset_short(volatile u_short *p, u_short *cmpval, u_short newval) 78684046d16SJustin Hibbits { 78784046d16SJustin Hibbits int ret; 78884046d16SJustin Hibbits 78984046d16SJustin Hibbits __asm __volatile ( 79084046d16SJustin Hibbits "lharx %0, 0, %3\n\t" /* load old value */ 79184046d16SJustin Hibbits "cmplw %4, %0\n\t" /* compare */ 79284046d16SJustin Hibbits "bne- 1f\n\t" /* exit if not equal */ 79384046d16SJustin Hibbits "sthcx. %5, 0, %3\n\t" /* attempt to store */ 79484046d16SJustin Hibbits "bne- 1f\n\t" /* exit if failed */ 79584046d16SJustin Hibbits "li %0, 1\n\t" /* success - retval = 1 */ 79684046d16SJustin Hibbits "b 2f\n\t" /* we've succeeded */ 79784046d16SJustin Hibbits "1:\n\t" 79884046d16SJustin Hibbits "sthcx. %0, 0, %3\n\t" /* clear reservation (74xx) */ 799895a2258SJustin Hibbits "sthx %0, 0, %7\n\t" 80084046d16SJustin Hibbits "li %0, 0\n\t" /* failure - retval = 0 */ 80184046d16SJustin Hibbits "2:\n\t" 80284046d16SJustin Hibbits : "=&r" (ret), "=m" (*p), "=m" (*cmpval) 80384046d16SJustin Hibbits : "r" (p), "r" (*cmpval), "r" (newval), "m" (*p), "r"(cmpval) 80484046d16SJustin Hibbits : "cr0", "memory"); 80584046d16SJustin Hibbits 80684046d16SJustin Hibbits return (ret); 80784046d16SJustin Hibbits } 80884046d16SJustin Hibbits #endif /* ISA_206_ATOMICS */ 80984046d16SJustin Hibbits 81002f151d4SJustin Hibbits static __inline int 81102f151d4SJustin Hibbits atomic_fcmpset_int(volatile u_int *p, u_int *cmpval, u_int newval) 81202f151d4SJustin Hibbits { 81302f151d4SJustin Hibbits int ret; 81402f151d4SJustin Hibbits 81502f151d4SJustin Hibbits __asm __volatile ( 816d3a8234cSJustin Hibbits "lwarx %0, 0, %3\n\t" /* load old value */ 81702f151d4SJustin Hibbits "cmplw %4, %0\n\t" /* compare */ 818e44ed9d3SJustin Hibbits "bne- 1f\n\t" /* exit if not equal */ 81902f151d4SJustin Hibbits "stwcx. %5, 0, %3\n\t" /* attempt to store */ 820d3a8234cSJustin Hibbits "bne- 1f\n\t" /* exit if failed */ 82102f151d4SJustin Hibbits "li %0, 1\n\t" /* success - retval = 1 */ 822d3a8234cSJustin Hibbits "b 2f\n\t" /* we've succeeded */ 823d3a8234cSJustin Hibbits "1:\n\t" 82402f151d4SJustin Hibbits "stwcx. %0, 0, %3\n\t" /* clear reservation (74xx) */ 82502f151d4SJustin Hibbits "stwx %0, 0, %7\n\t" 82602f151d4SJustin Hibbits "li %0, 0\n\t" /* failure - retval = 0 */ 827d3a8234cSJustin Hibbits "2:\n\t" 82802f151d4SJustin Hibbits : "=&r" (ret), "=m" (*p), "=m" (*cmpval) 82902f151d4SJustin Hibbits : "r" (p), "r" (*cmpval), "r" (newval), "m" (*p), "r"(cmpval) 83002f151d4SJustin Hibbits : "cr0", "memory"); 83102f151d4SJustin Hibbits 83202f151d4SJustin Hibbits return (ret); 83302f151d4SJustin Hibbits } 83402f151d4SJustin Hibbits static __inline int 83502f151d4SJustin Hibbits atomic_fcmpset_long(volatile u_long *p, u_long *cmpval, u_long newval) 83602f151d4SJustin Hibbits { 83702f151d4SJustin Hibbits int ret; 83802f151d4SJustin Hibbits 83902f151d4SJustin Hibbits __asm __volatile ( 84002f151d4SJustin Hibbits #ifdef __powerpc64__ 841d3a8234cSJustin Hibbits "ldarx %0, 0, %3\n\t" /* load old value */ 84202f151d4SJustin Hibbits "cmpld %4, %0\n\t" /* compare */ 843e44ed9d3SJustin Hibbits "bne- 1f\n\t" /* exit if not equal */ 84402f151d4SJustin Hibbits "stdcx. %5, 0, %3\n\t" /* attempt to store */ 84502f151d4SJustin Hibbits #else 846d3a8234cSJustin Hibbits "lwarx %0, 0, %3\n\t" /* load old value */ 84702f151d4SJustin Hibbits "cmplw %4, %0\n\t" /* compare */ 848e44ed9d3SJustin Hibbits "bne- 1f\n\t" /* exit if not equal */ 84902f151d4SJustin Hibbits "stwcx. %5, 0, %3\n\t" /* attempt to store */ 85002f151d4SJustin Hibbits #endif 851d3a8234cSJustin Hibbits "bne- 1f\n\t" /* exit if failed */ 85202f151d4SJustin Hibbits "li %0, 1\n\t" /* success - retval = 1 */ 853d3a8234cSJustin Hibbits "b 2f\n\t" /* we've succeeded */ 854d3a8234cSJustin Hibbits "1:\n\t" 85502f151d4SJustin Hibbits #ifdef __powerpc64__ 85602f151d4SJustin Hibbits "stdcx. %0, 0, %3\n\t" /* clear reservation (74xx) */ 85702f151d4SJustin Hibbits "stdx %0, 0, %7\n\t" 85802f151d4SJustin Hibbits #else 85902f151d4SJustin Hibbits "stwcx. %0, 0, %3\n\t" /* clear reservation (74xx) */ 86002f151d4SJustin Hibbits "stwx %0, 0, %7\n\t" 86102f151d4SJustin Hibbits #endif 86202f151d4SJustin Hibbits "li %0, 0\n\t" /* failure - retval = 0 */ 863d3a8234cSJustin Hibbits "2:\n\t" 86402f151d4SJustin Hibbits : "=&r" (ret), "=m" (*p), "=m" (*cmpval) 86502f151d4SJustin Hibbits : "r" (p), "r" (*cmpval), "r" (newval), "m" (*p), "r"(cmpval) 86602f151d4SJustin Hibbits : "cr0", "memory"); 86702f151d4SJustin Hibbits 86802f151d4SJustin Hibbits return (ret); 86902f151d4SJustin Hibbits } 87002f151d4SJustin Hibbits 87184046d16SJustin Hibbits #define ATOMIC_FCMPSET_ACQ_REL(type) \ 87284046d16SJustin Hibbits static __inline int \ 87384046d16SJustin Hibbits atomic_fcmpset_acq_##type(volatile u_##type *p, \ 87484046d16SJustin Hibbits u_##type *cmpval, u_##type newval)\ 87584046d16SJustin Hibbits {\ 87684046d16SJustin Hibbits u_##type retval; \ 87784046d16SJustin Hibbits retval = atomic_fcmpset_##type(p, cmpval, newval);\ 87884046d16SJustin Hibbits __ATOMIC_ACQ();\ 87984046d16SJustin Hibbits return (retval);\ 88084046d16SJustin Hibbits }\ 88184046d16SJustin Hibbits static __inline int \ 88284046d16SJustin Hibbits atomic_fcmpset_rel_##type(volatile u_##type *p, \ 88384046d16SJustin Hibbits u_##type *cmpval, u_##type newval)\ 88484046d16SJustin Hibbits {\ 88584046d16SJustin Hibbits __ATOMIC_REL();\ 88684046d16SJustin Hibbits return (atomic_fcmpset_##type(p, cmpval, newval));\ 88784046d16SJustin Hibbits }\ 88884046d16SJustin Hibbits struct hack 88902f151d4SJustin Hibbits 89084046d16SJustin Hibbits ATOMIC_FCMPSET_ACQ_REL(int); 89184046d16SJustin Hibbits ATOMIC_FCMPSET_ACQ_REL(long); 89202f151d4SJustin Hibbits 893ca0ec73cSConrad Meyer #ifdef ISA_206_ATOMICS 89484046d16SJustin Hibbits #define atomic_fcmpset_8 atomic_fcmpset_char 895ca0ec73cSConrad Meyer #endif 89684046d16SJustin Hibbits #define atomic_fcmpset_acq_8 atomic_fcmpset_acq_char 89784046d16SJustin Hibbits #define atomic_fcmpset_rel_8 atomic_fcmpset_rel_char 89802f151d4SJustin Hibbits 899ca0ec73cSConrad Meyer #ifdef ISA_206_ATOMICS 90084046d16SJustin Hibbits #define atomic_fcmpset_16 atomic_fcmpset_short 901ca0ec73cSConrad Meyer #endif 90284046d16SJustin Hibbits #define atomic_fcmpset_acq_16 atomic_fcmpset_acq_short 90384046d16SJustin Hibbits #define atomic_fcmpset_rel_16 atomic_fcmpset_rel_short 90402f151d4SJustin Hibbits 90502f151d4SJustin Hibbits #define atomic_fcmpset_32 atomic_fcmpset_int 90602f151d4SJustin Hibbits #define atomic_fcmpset_acq_32 atomic_fcmpset_acq_int 90702f151d4SJustin Hibbits #define atomic_fcmpset_rel_32 atomic_fcmpset_rel_int 90802f151d4SJustin Hibbits 90902f151d4SJustin Hibbits #ifdef __powerpc64__ 91002f151d4SJustin Hibbits #define atomic_fcmpset_64 atomic_fcmpset_long 91102f151d4SJustin Hibbits #define atomic_fcmpset_acq_64 atomic_fcmpset_acq_long 91202f151d4SJustin Hibbits #define atomic_fcmpset_rel_64 atomic_fcmpset_rel_long 91302f151d4SJustin Hibbits 91402f151d4SJustin Hibbits #define atomic_fcmpset_ptr atomic_fcmpset_long 91502f151d4SJustin Hibbits #define atomic_fcmpset_acq_ptr atomic_fcmpset_acq_long 91602f151d4SJustin Hibbits #define atomic_fcmpset_rel_ptr atomic_fcmpset_rel_long 91702f151d4SJustin Hibbits #else 91802f151d4SJustin Hibbits #define atomic_fcmpset_ptr atomic_fcmpset_int 91902f151d4SJustin Hibbits #define atomic_fcmpset_acq_ptr atomic_fcmpset_acq_int 92002f151d4SJustin Hibbits #define atomic_fcmpset_rel_ptr atomic_fcmpset_rel_int 92102f151d4SJustin Hibbits #endif 92202f151d4SJustin Hibbits 923dc6dc1f5SAttilio Rao static __inline u_int 924dc6dc1f5SAttilio Rao atomic_fetchadd_int(volatile u_int *p, u_int v) 9253c2bc2bfSJohn Baldwin { 926dc6dc1f5SAttilio Rao u_int value; 9273c2bc2bfSJohn Baldwin 9283c2bc2bfSJohn Baldwin do { 9293c2bc2bfSJohn Baldwin value = *p; 930dc6dc1f5SAttilio Rao } while (!atomic_cmpset_int(p, value, value + v)); 9313c2bc2bfSJohn Baldwin return (value); 9323c2bc2bfSJohn Baldwin } 9333c2bc2bfSJohn Baldwin 934dc6dc1f5SAttilio Rao static __inline u_long 935dc6dc1f5SAttilio Rao atomic_fetchadd_long(volatile u_long *p, u_long v) 936c3e289e1SNathan Whitehorn { 937dc6dc1f5SAttilio Rao u_long value; 938c3e289e1SNathan Whitehorn 939c3e289e1SNathan Whitehorn do { 940c3e289e1SNathan Whitehorn value = *p; 941c3e289e1SNathan Whitehorn } while (!atomic_cmpset_long(p, value, value + v)); 942c3e289e1SNathan Whitehorn return (value); 943c3e289e1SNathan Whitehorn } 944c3e289e1SNathan Whitehorn 945feb86bbeSAndreas Tobler static __inline u_int 946feb86bbeSAndreas Tobler atomic_swap_32(volatile u_int *p, u_int v) 947feb86bbeSAndreas Tobler { 948feb86bbeSAndreas Tobler u_int prev; 949feb86bbeSAndreas Tobler 950feb86bbeSAndreas Tobler __asm __volatile( 951feb86bbeSAndreas Tobler "1: lwarx %0,0,%2\n" 952feb86bbeSAndreas Tobler " stwcx. %3,0,%2\n" 953feb86bbeSAndreas Tobler " bne- 1b\n" 954feb86bbeSAndreas Tobler : "=&r" (prev), "+m" (*(volatile u_int *)p) 955feb86bbeSAndreas Tobler : "r" (p), "r" (v) 956181ca73bSJustin Hibbits : "cr0", "memory"); 957feb86bbeSAndreas Tobler 958feb86bbeSAndreas Tobler return (prev); 959feb86bbeSAndreas Tobler } 960feb86bbeSAndreas Tobler 961feb86bbeSAndreas Tobler #ifdef __powerpc64__ 962feb86bbeSAndreas Tobler static __inline u_long 963feb86bbeSAndreas Tobler atomic_swap_64(volatile u_long *p, u_long v) 964feb86bbeSAndreas Tobler { 965feb86bbeSAndreas Tobler u_long prev; 966feb86bbeSAndreas Tobler 967feb86bbeSAndreas Tobler __asm __volatile( 968feb86bbeSAndreas Tobler "1: ldarx %0,0,%2\n" 969feb86bbeSAndreas Tobler " stdcx. %3,0,%2\n" 970feb86bbeSAndreas Tobler " bne- 1b\n" 971feb86bbeSAndreas Tobler : "=&r" (prev), "+m" (*(volatile u_long *)p) 972feb86bbeSAndreas Tobler : "r" (p), "r" (v) 973181ca73bSJustin Hibbits : "cr0", "memory"); 974feb86bbeSAndreas Tobler 975feb86bbeSAndreas Tobler return (prev); 976feb86bbeSAndreas Tobler } 977feb86bbeSAndreas Tobler #endif 978feb86bbeSAndreas Tobler 979dc6dc1f5SAttilio Rao #define atomic_fetchadd_32 atomic_fetchadd_int 980feb86bbeSAndreas Tobler #define atomic_swap_int atomic_swap_32 981dc6dc1f5SAttilio Rao 982dc6dc1f5SAttilio Rao #ifdef __powerpc64__ 983dc6dc1f5SAttilio Rao #define atomic_fetchadd_64 atomic_fetchadd_long 984feb86bbeSAndreas Tobler #define atomic_swap_long atomic_swap_64 985feb86bbeSAndreas Tobler #define atomic_swap_ptr atomic_swap_64 986d7a9bfeeSHans Petter Selasky #else 987d7a9bfeeSHans Petter Selasky #define atomic_swap_long(p,v) atomic_swap_32((volatile u_int *)(p), v) 988d7a9bfeeSHans Petter Selasky #define atomic_swap_ptr(p,v) atomic_swap_32((volatile u_int *)(p), v) 989c3e289e1SNathan Whitehorn #endif 9903c2bc2bfSJohn Baldwin 991b5d227b0SJustin Hibbits static __inline int 992b5d227b0SJustin Hibbits atomic_testandset_int(volatile u_int *p, u_int v) 993b5d227b0SJustin Hibbits { 994aa473645SJustin Hibbits u_int m = (1u << (v & 0x1f)); 995b5d227b0SJustin Hibbits u_int res; 996b5d227b0SJustin Hibbits u_int tmp; 997b5d227b0SJustin Hibbits 998b5d227b0SJustin Hibbits __asm __volatile( 999b5d227b0SJustin Hibbits "1: lwarx %0,0,%3\n" 1000aa473645SJustin Hibbits " and %1,%0,%4\n" 1001b5d227b0SJustin Hibbits " or %0,%0,%4\n" 1002b5d227b0SJustin Hibbits " stwcx. %0,0,%3\n" 1003b5d227b0SJustin Hibbits " bne- 1b\n" 1004b5d227b0SJustin Hibbits : "=&r"(tmp), "=&r"(res), "+m"(*p) 1005b5d227b0SJustin Hibbits : "r"(p), "r"(m) 1006b5d227b0SJustin Hibbits : "cr0", "memory"); 1007b5d227b0SJustin Hibbits 1008b5d227b0SJustin Hibbits return (res != 0); 1009b5d227b0SJustin Hibbits } 1010b5d227b0SJustin Hibbits 1011b5d227b0SJustin Hibbits static __inline int 1012b5d227b0SJustin Hibbits atomic_testandclear_int(volatile u_int *p, u_int v) 1013b5d227b0SJustin Hibbits { 1014aa473645SJustin Hibbits u_int m = (1u << (v & 0x1f)); 1015b5d227b0SJustin Hibbits u_int res; 1016b5d227b0SJustin Hibbits u_int tmp; 1017b5d227b0SJustin Hibbits 1018b5d227b0SJustin Hibbits __asm __volatile( 1019b5d227b0SJustin Hibbits "1: lwarx %0,0,%3\n" 1020aa473645SJustin Hibbits " and %1,%0,%4\n" 1021b5d227b0SJustin Hibbits " andc %0,%0,%4\n" 1022b5d227b0SJustin Hibbits " stwcx. %0,0,%3\n" 1023b5d227b0SJustin Hibbits " bne- 1b\n" 1024b5d227b0SJustin Hibbits : "=&r"(tmp), "=&r"(res), "+m"(*p) 1025b5d227b0SJustin Hibbits : "r"(p), "r"(m) 1026b5d227b0SJustin Hibbits : "cr0", "memory"); 1027b5d227b0SJustin Hibbits 1028b5d227b0SJustin Hibbits return (res != 0); 1029b5d227b0SJustin Hibbits } 1030b5d227b0SJustin Hibbits 1031b5d227b0SJustin Hibbits #ifdef __powerpc64__ 1032b5d227b0SJustin Hibbits static __inline int 1033b5d227b0SJustin Hibbits atomic_testandset_long(volatile u_long *p, u_int v) 1034b5d227b0SJustin Hibbits { 1035aa473645SJustin Hibbits u_long m = (1ul << (v & 0x3f)); 1036b5d227b0SJustin Hibbits u_long res; 1037b5d227b0SJustin Hibbits u_long tmp; 1038b5d227b0SJustin Hibbits 1039b5d227b0SJustin Hibbits __asm __volatile( 1040b5d227b0SJustin Hibbits "1: ldarx %0,0,%3\n" 1041aa473645SJustin Hibbits " and %1,%0,%4\n" 1042b5d227b0SJustin Hibbits " or %0,%0,%4\n" 1043b5d227b0SJustin Hibbits " stdcx. %0,0,%3\n" 1044b5d227b0SJustin Hibbits " bne- 1b\n" 1045b5d227b0SJustin Hibbits : "=&r"(tmp), "=&r"(res), "+m"(*(volatile u_long *)p) 1046b5d227b0SJustin Hibbits : "r"(p), "r"(m) 1047b5d227b0SJustin Hibbits : "cr0", "memory"); 1048b5d227b0SJustin Hibbits 1049b5d227b0SJustin Hibbits return (res != 0); 1050b5d227b0SJustin Hibbits } 1051b5d227b0SJustin Hibbits 1052b5d227b0SJustin Hibbits static __inline int 1053b5d227b0SJustin Hibbits atomic_testandclear_long(volatile u_long *p, u_int v) 1054b5d227b0SJustin Hibbits { 1055aa473645SJustin Hibbits u_long m = (1ul << (v & 0x3f)); 1056b5d227b0SJustin Hibbits u_long res; 1057b5d227b0SJustin Hibbits u_long tmp; 1058b5d227b0SJustin Hibbits 1059b5d227b0SJustin Hibbits __asm __volatile( 1060b5d227b0SJustin Hibbits "1: ldarx %0,0,%3\n" 1061aa473645SJustin Hibbits " and %1,%0,%4\n" 1062b5d227b0SJustin Hibbits " andc %0,%0,%4\n" 1063b5d227b0SJustin Hibbits " stdcx. %0,0,%3\n" 1064b5d227b0SJustin Hibbits " bne- 1b\n" 1065b5d227b0SJustin Hibbits : "=&r"(tmp), "=&r"(res), "+m"(*p) 1066b5d227b0SJustin Hibbits : "r"(p), "r"(m) 1067b5d227b0SJustin Hibbits : "cr0", "memory"); 1068b5d227b0SJustin Hibbits 1069b5d227b0SJustin Hibbits return (res != 0); 1070b5d227b0SJustin Hibbits } 1071b5d227b0SJustin Hibbits #else 1072b5d227b0SJustin Hibbits static __inline int 1073b5d227b0SJustin Hibbits atomic_testandset_long(volatile u_long *p, u_int v) 1074b5d227b0SJustin Hibbits { 107562b4e25fSLi-Wen Hsu return (atomic_testandset_int((volatile u_int *)p, v)); 1076b5d227b0SJustin Hibbits } 1077b5d227b0SJustin Hibbits 1078b5d227b0SJustin Hibbits static __inline int 1079b5d227b0SJustin Hibbits atomic_testandclear_long(volatile u_long *p, u_int v) 1080b5d227b0SJustin Hibbits { 108162b4e25fSLi-Wen Hsu return (atomic_testandclear_int((volatile u_int *)p, v)); 1082b5d227b0SJustin Hibbits } 1083b5d227b0SJustin Hibbits #endif 1084b5d227b0SJustin Hibbits 1085b5d227b0SJustin Hibbits #define atomic_testandclear_32 atomic_testandclear_int 1086b5d227b0SJustin Hibbits #define atomic_testandset_32 atomic_testandset_int 1087b5d227b0SJustin Hibbits 1088b5d227b0SJustin Hibbits static __inline int 1089b5d227b0SJustin Hibbits atomic_testandset_acq_long(volatile u_long *p, u_int v) 1090b5d227b0SJustin Hibbits { 1091b5d227b0SJustin Hibbits u_int a = atomic_testandset_long(p, v); 1092b5d227b0SJustin Hibbits __ATOMIC_ACQ(); 1093b5d227b0SJustin Hibbits return (a); 1094b5d227b0SJustin Hibbits } 1095b5d227b0SJustin Hibbits 1096a80b9ee1SJohn Baldwin #ifdef __powerpc64__ 1097a80b9ee1SJohn Baldwin #define atomic_testandclear_ptr atomic_testandclear_long 1098a80b9ee1SJohn Baldwin #define atomic_testandset_ptr atomic_testandset_long 1099a80b9ee1SJohn Baldwin #else 1100a80b9ee1SJohn Baldwin #define atomic_testandclear_ptr(p,v) \ 1101a80b9ee1SJohn Baldwin atomic_testandclear_32((volatile u_int *)(p), v) 1102a80b9ee1SJohn Baldwin #define atomic_testandset_ptr(p,v) \ 1103a80b9ee1SJohn Baldwin atomic_testandset_32((volatile u_int *)(p), v) 1104a80b9ee1SJohn Baldwin #endif 1105a80b9ee1SJohn Baldwin 11068954a9a4SKonstantin Belousov static __inline void 11078954a9a4SKonstantin Belousov atomic_thread_fence_acq(void) 11088954a9a4SKonstantin Belousov { 11098954a9a4SKonstantin Belousov 11100b39ffb3SKonstantin Belousov powerpc_lwsync(); 11118954a9a4SKonstantin Belousov } 11128954a9a4SKonstantin Belousov 11138954a9a4SKonstantin Belousov static __inline void 11148954a9a4SKonstantin Belousov atomic_thread_fence_rel(void) 11158954a9a4SKonstantin Belousov { 11168954a9a4SKonstantin Belousov 11170b39ffb3SKonstantin Belousov powerpc_lwsync(); 11188954a9a4SKonstantin Belousov } 11198954a9a4SKonstantin Belousov 11208954a9a4SKonstantin Belousov static __inline void 11218954a9a4SKonstantin Belousov atomic_thread_fence_acq_rel(void) 11228954a9a4SKonstantin Belousov { 11238954a9a4SKonstantin Belousov 11240b39ffb3SKonstantin Belousov powerpc_lwsync(); 11258954a9a4SKonstantin Belousov } 11268954a9a4SKonstantin Belousov 11278954a9a4SKonstantin Belousov static __inline void 11288954a9a4SKonstantin Belousov atomic_thread_fence_seq_cst(void) 11298954a9a4SKonstantin Belousov { 11308954a9a4SKonstantin Belousov 11318954a9a4SKonstantin Belousov __asm __volatile("sync" : : : "memory"); 11328954a9a4SKonstantin Belousov } 11338954a9a4SKonstantin Belousov 113484046d16SJustin Hibbits #ifndef ISA_206_ATOMICS 113584046d16SJustin Hibbits #include <sys/_atomic_subword.h> 1136ca0ec73cSConrad Meyer #define atomic_cmpset_char atomic_cmpset_8 1137ca0ec73cSConrad Meyer #define atomic_cmpset_short atomic_cmpset_16 1138ca0ec73cSConrad Meyer #define atomic_fcmpset_char atomic_fcmpset_8 1139ca0ec73cSConrad Meyer #define atomic_fcmpset_short atomic_fcmpset_16 114084046d16SJustin Hibbits #endif 114184046d16SJustin Hibbits 114284046d16SJustin Hibbits /* These need sys/_atomic_subword.h on non-ISA-2.06-atomic platforms. */ 114384046d16SJustin Hibbits ATOMIC_CMPSET_ACQ_REL(char); 114484046d16SJustin Hibbits ATOMIC_CMPSET_ACQ_REL(short); 114584046d16SJustin Hibbits 114684046d16SJustin Hibbits ATOMIC_FCMPSET_ACQ_REL(char); 114784046d16SJustin Hibbits ATOMIC_FCMPSET_ACQ_REL(short); 114884046d16SJustin Hibbits 114984046d16SJustin Hibbits #undef __ATOMIC_REL 115084046d16SJustin Hibbits #undef __ATOMIC_ACQ 115184046d16SJustin Hibbits 1152b5073b49SDavid E. O'Brien #endif /* ! _MACHINE_ATOMIC_H_ */ 1153