locking/arch, x86: Add __down_read_killable()
Similar to __down_write_killable(), add read killable primitive: extract current __down_read() code to macros and teach it to get different functions as slow_path argument: store ax register to ret, and add sp register and preserve its value. Add call_rwsem_down_read_failed_killable() assembly entry similar to call_rwsem_down_read_failed(): push dx register to stack in additional to common registers, as it's not declarated as modifiable in ____down_read(). Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: arnd@arndb.de Cc: avagin@virtuozzo.com Cc: davem@davemloft.net Cc: fenghua.yu@intel.com Cc: gorcunov@virtuozzo.com Cc: heiko.carstens@de.ibm.com Cc: hpa@zytor.com Cc: ink@jurassic.park.msu.ru Cc: mattst88@gmail.com Cc: rientjes@google.com Cc: rth@twiddle.net Cc: schwidefsky@de.ibm.com Cc: tony.luck@intel.com Cc: viro@zeniv.linux.org.uk Link: http://lkml.kernel.org/r/150670118802.23930.1316107715255410256.stgit@localhost.localdomain Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
Родитель
a61ba2c8a4
Коммит
19c6092301
|
@ -60,18 +60,33 @@
|
|||
/*
|
||||
* lock for reading
|
||||
*/
|
||||
#define ____down_read(sem, slow_path) \
|
||||
({ \
|
||||
struct rw_semaphore* ret; \
|
||||
asm volatile("# beginning down_read\n\t" \
|
||||
LOCK_PREFIX _ASM_INC "(%[sem])\n\t" \
|
||||
/* adds 0x00000001 */ \
|
||||
" jns 1f\n" \
|
||||
" call " slow_path "\n" \
|
||||
"1:\n\t" \
|
||||
"# ending down_read\n\t" \
|
||||
: "+m" (sem->count), "=a" (ret), \
|
||||
ASM_CALL_CONSTRAINT \
|
||||
: [sem] "a" (sem) \
|
||||
: "memory", "cc"); \
|
||||
ret; \
|
||||
})
|
||||
|
||||
static inline void __down_read(struct rw_semaphore *sem)
|
||||
{
|
||||
asm volatile("# beginning down_read\n\t"
|
||||
LOCK_PREFIX _ASM_INC "(%[sem])\n\t"
|
||||
/* adds 0x00000001 */
|
||||
" jns 1f\n"
|
||||
" call call_rwsem_down_read_failed\n"
|
||||
"1:\n\t"
|
||||
"# ending down_read\n\t"
|
||||
: "+m" (sem->count)
|
||||
: [sem] "a" (sem)
|
||||
: "memory", "cc");
|
||||
____down_read(sem, "call_rwsem_down_read_failed");
|
||||
}
|
||||
|
||||
static inline int __down_read_killable(struct rw_semaphore *sem)
|
||||
{
|
||||
if (IS_ERR(____down_read(sem, "call_rwsem_down_read_failed_killable")))
|
||||
return -EINTR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -98,6 +98,18 @@ ENTRY(call_rwsem_down_read_failed)
|
|||
ret
|
||||
ENDPROC(call_rwsem_down_read_failed)
|
||||
|
||||
ENTRY(call_rwsem_down_read_failed_killable)
|
||||
FRAME_BEGIN
|
||||
save_common_regs
|
||||
__ASM_SIZE(push,) %__ASM_REG(dx)
|
||||
movq %rax,%rdi
|
||||
call rwsem_down_read_failed_killable
|
||||
__ASM_SIZE(pop,) %__ASM_REG(dx)
|
||||
restore_common_regs
|
||||
FRAME_END
|
||||
ret
|
||||
ENDPROC(call_rwsem_down_read_failed_killable)
|
||||
|
||||
ENTRY(call_rwsem_down_write_failed)
|
||||
FRAME_BEGIN
|
||||
save_common_regs
|
||||
|
|
Загрузка…
Ссылка в новой задаче