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