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