1 1.13 martin /* $NetBSD: atomic_cas.S,v 1.13 2014/02/21 16:21:02 martin Exp $ */ 2 1.2 ad 3 1.2 ad /*- 4 1.5 ad * Copyright (c) 2007, 2008 The NetBSD Foundation, Inc. 5 1.2 ad * All rights reserved. 6 1.2 ad * 7 1.2 ad * This code is derived from software contributed to The NetBSD Foundation 8 1.2 ad * by Andrew Doran and Jason R. Thorpe. 9 1.2 ad * 10 1.2 ad * Redistribution and use in source and binary forms, with or without 11 1.2 ad * modification, are permitted provided that the following conditions 12 1.2 ad * are met: 13 1.2 ad * 1. Redistributions of source code must retain the above copyright 14 1.2 ad * notice, this list of conditions and the following disclaimer. 15 1.2 ad * 2. Redistributions in binary form must reproduce the above copyright 16 1.2 ad * notice, this list of conditions and the following disclaimer in the 17 1.2 ad * documentation and/or other materials provided with the distribution. 18 1.2 ad * 19 1.2 ad * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.2 ad * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.2 ad * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.2 ad * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.2 ad * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.2 ad * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.2 ad * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.2 ad * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.2 ad * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.2 ad * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.2 ad * POSSIBILITY OF SUCH DAMAGE. 30 1.2 ad */ 31 1.2 ad 32 1.9 pooka #include <sys/param.h> 33 1.2 ad #include "atomic_op_asm.h" 34 1.2 ad 35 1.10 nakayama #if defined(_HARDKERNEL) 36 1.2 ad 37 1.3 ad #include <machine/psl.h> 38 1.3 ad 39 1.2 ad #include "opt_multiprocessor.h" 40 1.2 ad 41 1.2 ad #define DISABLE_INTERRUPTS \ 42 1.3 ad rd %psr, %o4 /* disable interrupts */;\ 43 1.3 ad or %o4, PSR_PIL, %o5 ;\ 44 1.2 ad wr %o5, 0, %psr ;\ 45 1.2 ad nop ;\ 46 1.2 ad nop ;\ 47 1.2 ad nop 48 1.2 ad 49 1.2 ad #define RESTORE_INTERRUPTS \ 50 1.3 ad wr %o4, 0, %psr /* enable interrupts */ ;\ 51 1.2 ad nop ;\ 52 1.2 ad nop ;\ 53 1.2 ad nop 54 1.2 ad 55 1.8 pooka #else /* _HARDKERNEL */ 56 1.4 ad 57 1.4 ad #define MULTIPROCESSOR 1 58 1.4 ad #define DISABLE_INTERRUPTS /* nothing */ 59 1.4 ad #define RESTORE_INTERRUPTS /* nothing */ 60 1.4 ad 61 1.8 pooka #endif /* _HARDKERNEL */ 62 1.4 ad 63 1.2 ad #if defined(MULTIPROCESSOR) 64 1.2 ad .section .bss 65 1.2 ad .align 1024 66 1.12 joerg #ifdef __PIC__ 67 1.11 pooka .globl _C_LABEL(_atomic_cas_locktab) 68 1.11 pooka #endif 69 1.2 ad OTYPE(_C_LABEL(_atomic_cas_locktab)) 70 1.2 ad _C_LABEL(_atomic_cas_locktab): 71 1.2 ad .space 1024 72 1.2 ad 73 1.12 joerg #ifdef __PIC__ 74 1.11 pooka /* o4 is not used for PSR in PIC cases, so we can use it here */ 75 1.11 pooka #define GETLOCKTAB \ 76 1.11 pooka PIC_PROLOGUE(%o3,%o4) ;\ 77 1.11 pooka set _C_LABEL(_atomic_cas_locktab), %o4 ;\ 78 1.11 pooka ld [%o3 + %o4], %o3 79 1.11 pooka #else 80 1.11 pooka #define GETLOCKTAB \ 81 1.11 pooka sethi %hi(_C_LABEL(_atomic_cas_locktab)), %o3 82 1.11 pooka #endif 83 1.11 pooka 84 1.2 ad #define ACQUIRE_INTERLOCK \ 85 1.2 ad DISABLE_INTERRUPTS ;\ 86 1.3 ad srl %o0, 3, %o5 /* get lock address */ ;\ 87 1.2 ad and %o5, 1023, %o5 ;\ 88 1.11 pooka GETLOCKTAB ;\ 89 1.2 ad add %o5, %o3, %o5 ;\ 90 1.2 ad ;\ 91 1.3 ad /* %o5 has interlock address */ ;\ 92 1.2 ad ;\ 93 1.3 ad 1: ldstub [%o5], %o3 /* acquire lock */ ;\ 94 1.2 ad tst %o3 ;\ 95 1.2 ad bz,a 2f ;\ 96 1.2 ad nop ;\ 97 1.2 ad nop ;\ 98 1.2 ad nop ;\ 99 1.3 ad b,a 1b /* spin */ ;\ 100 1.2 ad nop ;\ 101 1.3 ad /* We now hold the interlock */ ;\ 102 1.2 ad 2: 103 1.2 ad 104 1.2 ad #define RELEASE_INTERLOCK \ 105 1.3 ad stb %g0, [%o5] /* release interlock */ ;\ 106 1.2 ad RESTORE_INTERRUPTS 107 1.2 ad 108 1.2 ad #else /* ! MULTIPROCESSOR */ 109 1.2 ad 110 1.2 ad #define ACQUIRE_INTERLOCK DISABLE_INTERRUPTS 111 1.2 ad 112 1.2 ad #define RELEASE_INTERLOCK RESTORE_INTERRUPTS 113 1.2 ad 114 1.2 ad #endif /* MULTIPROCESSOR */ 115 1.2 ad 116 1.2 ad .text 117 1.2 ad 118 1.2 ad /* 119 1.2 ad * The v7 and v8 SPARC doesn't have compare-and-swap, so we block interrupts 120 1.2 ad * and use an interlock. 121 1.2 ad * 122 1.2 ad * XXX On single CPU systems, this should use a restartable sequence: 123 1.2 ad * XXX there we don't need the overhead of interlocking. 124 1.2 ad * 125 1.2 ad * XXX NOTE! The interlock trick only works if EVERYTHING writes to 126 1.2 ad * XXX the memory cell through this code path! 127 1.2 ad */ 128 1.7 chs ENTRY(_atomic_cas_32) 129 1.2 ad ACQUIRE_INTERLOCK 130 1.2 ad ! %o4 has saved PSR value 131 1.2 ad ! %o5 has interlock address 132 1.2 ad 133 1.2 ad ld [%o0], %o3 ! get old value 134 1.2 ad cmp %o1, %o3 ! old == new? 135 1.2 ad beq,a 3f ! yes, do the store 136 1.2 ad st %o2, [%o0] ! (in the delay slot) 137 1.2 ad 138 1.2 ad 3: RELEASE_INTERLOCK 139 1.2 ad 140 1.2 ad retl 141 1.2 ad mov %o3, %o0 ! return old value 142 1.2 ad 143 1.2 ad ATOMIC_OP_ALIAS(atomic_cas_32,_atomic_cas_32) 144 1.2 ad ATOMIC_OP_ALIAS(atomic_cas_uint,_atomic_cas_32) 145 1.2 ad STRONG_ALIAS(_atomic_cas_uint,_atomic_cas_32) 146 1.2 ad ATOMIC_OP_ALIAS(atomic_cas_ulong,_atomic_cas_32) 147 1.2 ad STRONG_ALIAS(_atomic_cas_ulong,_atomic_cas_32) 148 1.2 ad ATOMIC_OP_ALIAS(atomic_cas_ptr,_atomic_cas_32) 149 1.2 ad STRONG_ALIAS(_atomic_cas_ptr,_atomic_cas_32) 150 1.13 martin STRONG_ALIAS(__sync_val_compare_and_swap_4,_atomic_cas_32) 151 1.5 ad 152 1.5 ad ATOMIC_OP_ALIAS(atomic_cas_32_ni,_atomic_cas_32) 153 1.5 ad STRONG_ALIAS(_atomic_cas_32_ni,_atomic_cas_32) 154 1.5 ad ATOMIC_OP_ALIAS(atomic_cas_uint_ni,_atomic_cas_32) 155 1.5 ad STRONG_ALIAS(_atomic_cas_uint_ni,_atomic_cas_32) 156 1.5 ad ATOMIC_OP_ALIAS(atomic_cas_ulong_ni,_atomic_cas_32) 157 1.5 ad STRONG_ALIAS(_atomic_cas_ulong_ni,_atomic_cas_32) 158 1.5 ad ATOMIC_OP_ALIAS(atomic_cas_ptr_ni,_atomic_cas_32) 159 1.5 ad STRONG_ALIAS(_atomic_cas_ptr_ni,_atomic_cas_32) 160