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.h> 19#include <asm/frame.h> 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, "ax" 33 34/* 35 * rw spinlock fallbacks 36 */ 37#ifdef CONFIG_SMP 38ENTRY(__write_lock_failed) 39 CFI_STARTPROC simple 40 FRAME 412: LOCK_PREFIX 42 addl $ RW_LOCK_BIAS,(%eax) 431: rep; nop 44 cmpl $ RW_LOCK_BIAS,(%eax) 45 jne 1b 46 LOCK_PREFIX 47 subl $ RW_LOCK_BIAS,(%eax) 48 jnz 2b 49 ENDFRAME 50 ret 51 CFI_ENDPROC 52 ENDPROC(__write_lock_failed) 53 54ENTRY(__read_lock_failed) 55 CFI_STARTPROC 56 FRAME 572: LOCK_PREFIX 58 incl (%eax) 591: rep; nop 60 cmpl $1,(%eax) 61 js 1b 62 LOCK_PREFIX 63 decl (%eax) 64 js 2b 65 ENDFRAME 66 ret 67 CFI_ENDPROC 68 ENDPROC(__read_lock_failed) 69 70#endif 71 72#ifdef CONFIG_RWSEM_XCHGADD_ALGORITHM 73 74/* Fix up special calling conventions */ 75ENTRY(call_rwsem_down_read_failed) 76 CFI_STARTPROC 77 push %ecx 78 CFI_ADJUST_CFA_OFFSET 4 79 CFI_REL_OFFSET ecx,0 80 push %edx 81 CFI_ADJUST_CFA_OFFSET 4 82 CFI_REL_OFFSET edx,0 83 call rwsem_down_read_failed 84 pop %edx 85 CFI_ADJUST_CFA_OFFSET -4 86 pop %ecx 87 CFI_ADJUST_CFA_OFFSET -4 88 ret 89 CFI_ENDPROC 90 ENDPROC(call_rwsem_down_read_failed) 91 92ENTRY(call_rwsem_down_write_failed) 93 CFI_STARTPROC 94 push %ecx 95 CFI_ADJUST_CFA_OFFSET 4 96 CFI_REL_OFFSET ecx,0 97 calll rwsem_down_write_failed 98 pop %ecx 99 CFI_ADJUST_CFA_OFFSET -4 100 ret 101 CFI_ENDPROC 102 ENDPROC(call_rwsem_down_write_failed) 103 104ENTRY(call_rwsem_wake) 105 CFI_STARTPROC 106 decw %dx /* do nothing if still outstanding active readers */ 107 jnz 1f 108 push %ecx 109 CFI_ADJUST_CFA_OFFSET 4 110 CFI_REL_OFFSET ecx,0 111 call rwsem_wake 112 pop %ecx 113 CFI_ADJUST_CFA_OFFSET -4 1141: ret 115 CFI_ENDPROC 116 ENDPROC(call_rwsem_wake) 117 118/* Fix up special calling conventions */ 119ENTRY(call_rwsem_downgrade_wake) 120 CFI_STARTPROC 121 push %ecx 122 CFI_ADJUST_CFA_OFFSET 4 123 CFI_REL_OFFSET ecx,0 124 push %edx 125 CFI_ADJUST_CFA_OFFSET 4 126 CFI_REL_OFFSET edx,0 127 call rwsem_downgrade_wake 128 pop %edx 129 CFI_ADJUST_CFA_OFFSET -4 130 pop %ecx 131 CFI_ADJUST_CFA_OFFSET -4 132 ret 133 CFI_ENDPROC 134 ENDPROC(call_rwsem_downgrade_wake) 135 136#endif 137