#include "opt_multiprocessor.h"
#include "opt_lockdebug.h"
#include <machine/asm.h>
#include <machine/frameasm.h>
#include "assym.h"
#define LOCK \
HOTPATCH(HP_NAME_NOLOCK, 1) ; \
lock
#define RET \
HOTPATCH(HP_NAME_RETFENCE, 3) ; \
ret; nop; nop ; \
ret
#ifndef LOCKDEBUG
.align 64
ENTRY(mutex_enter)
movq CPUVAR(CURLWP), %rcx
xorq %rax, %rax
LOCK
cmpxchgq %rcx, (%rdi)
jnz 1f
RET
1:
jmp _C_LABEL(mutex_vector_enter)
END(mutex_enter)
ENTRY(mutex_exit)
movq CPUVAR(CURLWP), %rax
xorq %rdx, %rdx
cmpxchgq %rdx, (%rdi)
jnz 1f
ret
1:
jmp _C_LABEL(mutex_vector_exit)
END(mutex_exit)
ENTRY(mutex_spin_enter)
movl $1, %eax
movzbl CPUVAR(ILEVEL), %esi
movzbl MTX_IPL(%rdi), %ecx
cmpl %ecx, %esi
cmovgl %esi, %ecx
movb %cl, CPUVAR(ILEVEL)
subl %eax, CPUVAR(MTX_COUNT)
cmovncl CPUVAR(MTX_OLDSPL), %esi
movl %esi, CPUVAR(MTX_OLDSPL)
xchgb %al, MTX_LOCK(%rdi)
#ifdef MULTIPROCESSOR
testb %al, %al
jnz 1f
#endif
RET
1:
jmp _C_LABEL(mutex_spin_retry)
END(mutex_spin_enter)
ENTRY(mutex_spin_exit)
#ifdef DIAGNOSTIC
movl $0x0001, %eax
movq CPUVAR(SELF), %r8
cmpxchgb %ah, MTX_LOCK(%rdi)
jnz _C_LABEL(mutex_vector_exit)
movl CPU_INFO_MTX_OLDSPL(%r8), %edi
incl CPU_INFO_MTX_COUNT(%r8)
jnz 1f
cmpb CPU_INFO_ILEVEL(%r8), %dil
jae 1f
movq CPU_INFO_IUNMASK(%r8,%rdi,8), %rsi
CLI(ax)
testq CPU_INFO_IPENDING(%r8), %rsi
jnz _C_LABEL(Xspllower)
movb %dil, CPU_INFO_ILEVEL(%r8)
STI(ax)
1: rep
ret
#else
movq CPUVAR(SELF), %rsi
movb $0x00, MTX_LOCK(%rdi)
movl CPU_INFO_MTX_OLDSPL(%rsi), %ecx
incl CPU_INFO_MTX_COUNT(%rsi)
movzbl CPU_INFO_ILEVEL(%rsi),%edx
cmovnzl %edx,%ecx
cmpl %edx,%ecx
jae 2f
xorq %rdi,%rdi
notq %rdi
shrq $8,%rdi
movq %rcx,%r9
shlq $56,%r9
1:
movq CPU_INFO_IPENDING(%rsi),%rax
testq %rax,CPU_INFO_IUNMASK(%rsi,%rcx,8)
jnz 3f
movq %rax,%r8
andq %rdi,%r8
orq %r9,%r8
cmpxchgq %r8,CPU_INFO_ISTATE(%rsi)
jnz 4f
2:
ret
3:
movl %ecx, %edi
jmp _C_LABEL(Xspllower)
4:
jmp 1b
#endif
END(mutex_spin_exit)
ENTRY(rw_enter)
cmpl $RW_READER, %esi
jne 2f
movq (%rdi), %rax
0:
testb $(RW_WRITE_LOCKED|RW_WRITE_WANTED), %al
jnz 3f
leaq RW_READ_INCR(%rax), %rdx
LOCK
cmpxchgq %rdx, (%rdi)
jnz 1f
RET
1:
jmp 0b
2: movq CPUVAR(CURLWP), %rcx
xorq %rax, %rax
orq $RW_WRITE_LOCKED, %rcx
LOCK
cmpxchgq %rcx, (%rdi)
jnz 3f
RET
3:
jmp _C_LABEL(rw_vector_enter)
END(rw_enter)
ENTRY(rw_exit)
movq (%rdi), %rax
testb $RW_WRITE_LOCKED, %al
jnz 2f
0: testb $RW_HAS_WAITERS, %al
jnz 3f
cmpq $RW_READ_INCR, %rax
jb 3f
leaq -RW_READ_INCR(%rax), %rdx
LOCK
cmpxchgq %rdx, (%rdi)
jnz 1f
ret
1:
jmp 0b
2: leaq -RW_WRITE_LOCKED(%rax), %rdx
subq CPUVAR(CURLWP), %rdx
jnz 3f
LOCK
cmpxchgq %rdx, (%rdi)
jnz 3f
ret
3: jmp _C_LABEL(rw_vector_exit)
END(rw_exit)
ENTRY(rw_tryenter)
cmpl $RW_READER, %esi
jne 2f
movq (%rdi), %rax
0:
testb $(RW_WRITE_LOCKED|RW_WRITE_WANTED), %al
jnz 4f
leaq RW_READ_INCR(%rax), %rdx
LOCK
cmpxchgq %rdx, (%rdi)
jnz 1f
movl %edx, %eax
RET
1:
jmp 0b
2: movq CPUVAR(CURLWP), %rcx
xorq %rax, %rax
orq $RW_WRITE_LOCKED, %rcx
LOCK
cmpxchgq %rcx, (%rdi)
movl $0, %eax
setz %al
3:
RET
ret
4:
xorl %eax, %eax
jmp 3b
END(rw_tryenter)
#endif
ENTRY(__cpu_simple_lock_init)
movb $0, (%rdi)
ret
END(__cpu_simple_lock_init)
ENTRY(__cpu_simple_lock)
movl $0x0100, %eax
1:
LOCK
cmpxchgb %ah, (%rdi)
jnz 2f
RET
2:
movl $0x0100, %eax
pause
nop
nop
cmpb $0, (%rdi)
je 1b
jmp 2b
END(__cpu_simple_lock)
ENTRY(__cpu_simple_unlock)
movb $0, (%rdi)
ret
END(__cpu_simple_unlock)
ENTRY(__cpu_simple_lock_try)
movl $0x0100, %eax
LOCK
cmpxchgb %ah, (%rdi)
movl $0, %eax
setz %al
KMSAN_INIT_RET(4)
RET
END(__cpu_simple_lock_try)