os_SunOS_ultrasparc.s (6894B)
1 ! -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 ! 3 ! This Source Code Form is subject to the terms of the Mozilla Public 4 ! License, v. 2.0. If a copy of the MPL was not distributed with this 5 ! file, You can obtain one at http://mozilla.org/MPL/2.0/. 6 7 ! 8 ! atomic increment, decrement and swap routines for V8+ sparc (ultrasparc) 9 ! using CAS (compare-and-swap) atomic instructions 10 ! 11 ! this MUST be compiled with an ultrasparc-aware assembler 12 ! 13 ! standard asm linkage macros; this module must be compiled 14 ! with the -P option (use C preprocessor) 15 16 #include <sys/asm_linkage.h> 17 18 ! ====================================================================== 19 ! 20 ! Perform the sequence a = a + 1 atomically with respect to other 21 ! fetch-and-adds to location a in a wait-free fashion. 22 ! 23 ! usage : val = PR_AtomicIncrement(address) 24 ! return: current value (you'd think this would be old val) 25 ! 26 ! ----------------------- 27 ! Note on REGISTER USAGE: 28 ! as this is a LEAF procedure, a new stack frame is not created; 29 ! we use the caller's stack frame so what would normally be %i (input) 30 ! registers are actually %o (output registers). Also, we must not 31 ! overwrite the contents of %l (local) registers as they are not 32 ! assumed to be volatile during calls. 33 ! 34 ! So, the registers used are: 35 ! %o0 [input] - the address of the value to increment 36 ! %o1 [local] - work register 37 ! %o2 [local] - work register 38 ! %o3 [local] - work register 39 ! ----------------------- 40 41 ENTRY(PR_AtomicIncrement) ! standard assembler/ELF prologue 42 43 retryAI: 44 ld [%o0], %o2 ! set o2 to the current value 45 add %o2, 0x1, %o3 ! calc the new value 46 mov %o3, %o1 ! save the return value 47 cas [%o0], %o2, %o3 ! atomically set if o0 hasn't changed 48 cmp %o2, %o3 ! see if we set the value 49 bne retryAI ! if not, try again 50 nop ! empty out the branch pipeline 51 retl ! return back to the caller 52 mov %o1, %o0 ! set the return code to the new value 53 54 SET_SIZE(PR_AtomicIncrement) ! standard assembler/ELF epilogue 55 56 ! 57 ! end 58 ! 59 ! ====================================================================== 60 ! 61 62 ! ====================================================================== 63 ! 64 ! Perform the sequence a = a - 1 atomically with respect to other 65 ! fetch-and-decs to location a in a wait-free fashion. 66 ! 67 ! usage : val = PR_AtomicDecrement(address) 68 ! return: current value (you'd think this would be old val) 69 ! 70 ! ----------------------- 71 ! Note on REGISTER USAGE: 72 ! as this is a LEAF procedure, a new stack frame is not created; 73 ! we use the caller's stack frame so what would normally be %i (input) 74 ! registers are actually %o (output registers). Also, we must not 75 ! overwrite the contents of %l (local) registers as they are not 76 ! assumed to be volatile during calls. 77 ! 78 ! So, the registers used are: 79 ! %o0 [input] - the address of the value to increment 80 ! %o1 [local] - work register 81 ! %o2 [local] - work register 82 ! %o3 [local] - work register 83 ! ----------------------- 84 85 ENTRY(PR_AtomicDecrement) ! standard assembler/ELF prologue 86 87 retryAD: 88 ld [%o0], %o2 ! set o2 to the current value 89 sub %o2, 0x1, %o3 ! calc the new value 90 mov %o3, %o1 ! save the return value 91 cas [%o0], %o2, %o3 ! atomically set if o0 hasn't changed 92 cmp %o2, %o3 ! see if we set the value 93 bne retryAD ! if not, try again 94 nop ! empty out the branch pipeline 95 retl ! return back to the caller 96 mov %o1, %o0 ! set the return code to the new value 97 98 SET_SIZE(PR_AtomicDecrement) ! standard assembler/ELF epilogue 99 100 ! 101 ! end 102 ! 103 ! ====================================================================== 104 ! 105 106 ! ====================================================================== 107 ! 108 ! Perform the sequence a = b atomically with respect to other 109 ! fetch-and-stores to location a in a wait-free fashion. 110 ! 111 ! usage : old_val = PR_AtomicSet(address, newval) 112 ! 113 ! ----------------------- 114 ! Note on REGISTER USAGE: 115 ! as this is a LEAF procedure, a new stack frame is not created; 116 ! we use the caller's stack frame so what would normally be %i (input) 117 ! registers are actually %o (output registers). Also, we must not 118 ! overwrite the contents of %l (local) registers as they are not 119 ! assumed to be volatile during calls. 120 ! 121 ! So, the registers used are: 122 ! %o0 [input] - the address of the value to increment 123 ! %o1 [input] - the new value to set for [%o0] 124 ! %o2 [local] - work register 125 ! %o3 [local] - work register 126 ! ----------------------- 127 128 ENTRY(PR_AtomicSet) ! standard assembler/ELF prologue 129 130 retryAS: 131 ld [%o0], %o2 ! set o2 to the current value 132 mov %o1, %o3 ! set up the new value 133 cas [%o0], %o2, %o3 ! atomically set if o0 hasn't changed 134 cmp %o2, %o3 ! see if we set the value 135 bne retryAS ! if not, try again 136 nop ! empty out the branch pipeline 137 retl ! return back to the caller 138 mov %o3, %o0 ! set the return code to the prev value 139 140 SET_SIZE(PR_AtomicSet) ! standard assembler/ELF epilogue 141 142 ! 143 ! end 144 ! 145 ! ====================================================================== 146 ! 147 148 ! ====================================================================== 149 ! 150 ! Perform the sequence a = a + b atomically with respect to other 151 ! fetch-and-adds to location a in a wait-free fashion. 152 ! 153 ! usage : newval = PR_AtomicAdd(address, val) 154 ! return: the value after addition 155 ! 156 ENTRY(PR_AtomicAdd) ! standard assembler/ELF prologue 157 158 retryAA: 159 ld [%o0], %o2 ! set o2 to the current value 160 add %o2, %o1, %o3 ! calc the new value 161 mov %o3, %o4 ! save the return value 162 cas [%o0], %o2, %o3 ! atomically set if o0 hasn't changed 163 cmp %o2, %o3 ! see if we set the value 164 bne retryAA ! if not, try again 165 nop ! empty out the branch pipeline 166 retl ! return back to the caller 167 mov %o4, %o0 ! set the return code to the new value 168 169 SET_SIZE(PR_AtomicAdd) ! standard assembler/ELF epilogue 170 171 ! 172 ! end 173 !