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 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 pushl_cfi %ecx 78 CFI_REL_OFFSET ecx,0 79 pushl_cfi %edx 80 CFI_REL_OFFSET edx,0 81 call rwsem_down_read_failed 82 popl_cfi %edx 83 popl_cfi %ecx 84 ret 85 CFI_ENDPROC 86 ENDPROC(call_rwsem_down_read_failed) 87 88ENTRY(call_rwsem_down_write_failed) 89 CFI_STARTPROC 90 pushl_cfi %ecx 91 CFI_REL_OFFSET ecx,0 92 calll rwsem_down_write_failed 93 popl_cfi %ecx 94 ret 95 CFI_ENDPROC 96 ENDPROC(call_rwsem_down_write_failed) 97 98ENTRY(call_rwsem_wake) 99 CFI_STARTPROC 100 decw %dx /* do nothing if still outstanding active readers */ 101 jnz 1f 102 pushl_cfi %ecx 103 CFI_REL_OFFSET ecx,0 104 call rwsem_wake 105 popl_cfi %ecx 1061: ret 107 CFI_ENDPROC 108 ENDPROC(call_rwsem_wake) 109 110/* Fix up special calling conventions */ 111ENTRY(call_rwsem_downgrade_wake) 112 CFI_STARTPROC 113 pushl_cfi %ecx 114 CFI_REL_OFFSET ecx,0 115 pushl_cfi %edx 116 CFI_REL_OFFSET edx,0 117 call rwsem_downgrade_wake 118 popl_cfi %edx 119 popl_cfi %ecx 120 ret 121 CFI_ENDPROC 122 ENDPROC(call_rwsem_downgrade_wake) 123 124#endif 125