1/* 2 * i386 semaphore implementation. 3 * 4 * (C) Copyright 1999 Linus Torvalds 5 * 6 * Portions Copyright 1999 Red Hat, Inc. 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License 10 * as published by the Free Software Foundation; either version 11 * 2 of the License, or (at your option) any later version. 12 * 13 * rw semaphores implemented November 1999 by Benjamin LaHaise <bcrl@kvack.org> 14 */ 15 16#include <linux/linkage.h> 17#include <asm/rwlock.h> 18#include <asm/alternative-asm.i> 19#include <asm/frame.i> 20#include <asm/dwarf2.h> 21 22/* 23 * The semaphore operations have a special calling sequence that 24 * allow us to do a simpler in-line version of them. These routines 25 * need to convert that sequence back into the C sequence when 26 * there is contention on the semaphore. 27 * 28 * %eax contains the semaphore pointer on entry. Save the C-clobbered 29 * registers (%eax, %edx and %ecx) except %eax whish is either a return 30 * value or just clobbered.. 31 */ 32 .section .sched.text 33ENTRY(__down_failed) 34 CFI_STARTPROC 35 FRAME 36 pushl %edx 37 CFI_ADJUST_CFA_OFFSET 4 38 CFI_REL_OFFSET edx,0 39 pushl %ecx 40 CFI_ADJUST_CFA_OFFSET 4 41 CFI_REL_OFFSET ecx,0 42 call __down 43 popl %ecx 44 CFI_ADJUST_CFA_OFFSET -4 45 CFI_RESTORE ecx 46 popl %edx 47 CFI_ADJUST_CFA_OFFSET -4 48 CFI_RESTORE edx 49 ENDFRAME 50 ret 51 CFI_ENDPROC 52 END(__down_failed) 53 54ENTRY(__down_failed_interruptible) 55 CFI_STARTPROC 56 FRAME 57 pushl %edx 58 CFI_ADJUST_CFA_OFFSET 4 59 CFI_REL_OFFSET edx,0 60 pushl %ecx 61 CFI_ADJUST_CFA_OFFSET 4 62 CFI_REL_OFFSET ecx,0 63 call __down_interruptible 64 popl %ecx 65 CFI_ADJUST_CFA_OFFSET -4 66 CFI_RESTORE ecx 67 popl %edx 68 CFI_ADJUST_CFA_OFFSET -4 69 CFI_RESTORE edx 70 ENDFRAME 71 ret 72 CFI_ENDPROC 73 END(__down_failed_interruptible) 74 75ENTRY(__down_failed_trylock) 76 CFI_STARTPROC 77 FRAME 78 pushl %edx 79 CFI_ADJUST_CFA_OFFSET 4 80 CFI_REL_OFFSET edx,0 81 pushl %ecx 82 CFI_ADJUST_CFA_OFFSET 4 83 CFI_REL_OFFSET ecx,0 84 call __down_trylock 85 popl %ecx 86 CFI_ADJUST_CFA_OFFSET -4 87 CFI_RESTORE ecx 88 popl %edx 89 CFI_ADJUST_CFA_OFFSET -4 90 CFI_RESTORE edx 91 ENDFRAME 92 ret 93 CFI_ENDPROC 94 END(__down_failed_trylock) 95 96ENTRY(__up_wakeup) 97 CFI_STARTPROC 98 FRAME 99 pushl %edx 100 CFI_ADJUST_CFA_OFFSET 4 101 CFI_REL_OFFSET edx,0 102 pushl %ecx 103 CFI_ADJUST_CFA_OFFSET 4 104 CFI_REL_OFFSET ecx,0 105 call __up 106 popl %ecx 107 CFI_ADJUST_CFA_OFFSET -4 108 CFI_RESTORE ecx 109 popl %edx 110 CFI_ADJUST_CFA_OFFSET -4 111 CFI_RESTORE edx 112 ENDFRAME 113 ret 114 CFI_ENDPROC 115 END(__up_wakeup) 116 117/* 118 * rw spinlock fallbacks 119 */ 120#ifdef CONFIG_SMP 121ENTRY(__write_lock_failed) 122 CFI_STARTPROC simple 123 FRAME 1242: LOCK_PREFIX 125 addl $ RW_LOCK_BIAS,(%eax) 1261: rep; nop 127 cmpl $ RW_LOCK_BIAS,(%eax) 128 jne 1b 129 LOCK_PREFIX 130 subl $ RW_LOCK_BIAS,(%eax) 131 jnz 2b 132 ENDFRAME 133 ret 134 CFI_ENDPROC 135 END(__write_lock_failed) 136 137ENTRY(__read_lock_failed) 138 CFI_STARTPROC 139 FRAME 1402: LOCK_PREFIX 141 incl (%eax) 1421: rep; nop 143 cmpl $1,(%eax) 144 js 1b 145 LOCK_PREFIX 146 decl (%eax) 147 js 2b 148 ENDFRAME 149 ret 150 CFI_ENDPROC 151 END(__read_lock_failed) 152 153#endif 154 155#ifdef CONFIG_RWSEM_XCHGADD_ALGORITHM 156 157/* Fix up special calling conventions */ 158ENTRY(call_rwsem_down_read_failed) 159 CFI_STARTPROC 160 push %ecx 161 CFI_ADJUST_CFA_OFFSET 4 162 CFI_REL_OFFSET ecx,0 163 push %edx 164 CFI_ADJUST_CFA_OFFSET 4 165 CFI_REL_OFFSET edx,0 166 call rwsem_down_read_failed 167 pop %edx 168 CFI_ADJUST_CFA_OFFSET -4 169 pop %ecx 170 CFI_ADJUST_CFA_OFFSET -4 171 ret 172 CFI_ENDPROC 173 END(call_rwsem_down_read_failed) 174 175ENTRY(call_rwsem_down_write_failed) 176 CFI_STARTPROC 177 push %ecx 178 CFI_ADJUST_CFA_OFFSET 4 179 CFI_REL_OFFSET ecx,0 180 calll rwsem_down_write_failed 181 pop %ecx 182 CFI_ADJUST_CFA_OFFSET -4 183 ret 184 CFI_ENDPROC 185 END(call_rwsem_down_write_failed) 186 187ENTRY(call_rwsem_wake) 188 CFI_STARTPROC 189 decw %dx /* do nothing if still outstanding active readers */ 190 jnz 1f 191 push %ecx 192 CFI_ADJUST_CFA_OFFSET 4 193 CFI_REL_OFFSET ecx,0 194 call rwsem_wake 195 pop %ecx 196 CFI_ADJUST_CFA_OFFSET -4 1971: ret 198 CFI_ENDPROC 199 END(call_rwsem_wake) 200 201/* Fix up special calling conventions */ 202ENTRY(call_rwsem_downgrade_wake) 203 CFI_STARTPROC 204 push %ecx 205 CFI_ADJUST_CFA_OFFSET 4 206 CFI_REL_OFFSET ecx,0 207 push %edx 208 CFI_ADJUST_CFA_OFFSET 4 209 CFI_REL_OFFSET edx,0 210 call rwsem_downgrade_wake 211 pop %edx 212 CFI_ADJUST_CFA_OFFSET -4 213 pop %ecx 214 CFI_ADJUST_CFA_OFFSET -4 215 ret 216 CFI_ENDPROC 217 END(call_rwsem_downgrade_wake) 218 219#endif 220