mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-16 19:31:42 -04:00
net: use try_cmpxchg() in lock_sock_nested()
Add a fast path in lock_sock_nested(), to avoid acquiring
the socket spinlock only to set @owned to one:
spin_lock_bh(&sk->sk_lock.slock);
if (unlikely(sock_owned_by_user_nocheck(sk)))
__lock_sock(sk);
sk->sk_lock.owned = 1;
spin_unlock_bh(&sk->sk_lock.slock);
On x86_64 compiler generates something quite efficient:
00000000000077c0 <lock_sock_nested>:
77c0: f3 0f 1e fa endbr64
77c4: e8 00 00 00 00 call __fentry__
77c9: b9 01 00 00 00 mov $0x1,%ecx
77ce: 31 c0 xor %eax,%eax
77d0: f0 48 0f b1 8f 48 01 00 00 lock cmpxchg %rcx,0x148(%rdi)
77d9: 75 06 jne slow_path
77db: 2e e9 00 00 00 00 cs jmp __x86_return_thunk-0x4
slow_path: ...
Signed-off-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
Reviewed-by: Jason Xing <kerneljasonxing@gmail.com>
Link: https://patch.msgid.link/20260226021215.1764237-1-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
committed by
Jakub Kicinski
parent
b99ccb37ed
commit
5151ec54f5
@@ -81,8 +81,13 @@
|
||||
* mini-semaphore synchronizes multiple users amongst themselves.
|
||||
*/
|
||||
typedef struct {
|
||||
spinlock_t slock;
|
||||
int owned;
|
||||
union {
|
||||
struct slock_owned {
|
||||
int owned;
|
||||
spinlock_t slock;
|
||||
};
|
||||
long combined;
|
||||
};
|
||||
wait_queue_head_t wq;
|
||||
/*
|
||||
* We express the mutex-alike socket_lock semantics
|
||||
|
||||
@@ -3780,6 +3780,19 @@ void noinline lock_sock_nested(struct sock *sk, int subclass)
|
||||
mutex_acquire(&sk->sk_lock.dep_map, subclass, 0, _RET_IP_);
|
||||
|
||||
might_sleep();
|
||||
#ifdef CONFIG_64BIT
|
||||
if (sizeof(struct slock_owned) == sizeof(long)) {
|
||||
socket_lock_t tmp, old;
|
||||
|
||||
tmp.slock = __SPIN_LOCK_UNLOCKED(tmp.slock);
|
||||
tmp.owned = 1;
|
||||
old.slock = __SPIN_LOCK_UNLOCKED(old.slock);
|
||||
old.owned = 0;
|
||||
if (likely(try_cmpxchg(&sk->sk_lock.combined,
|
||||
&old.combined, tmp.combined)))
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
spin_lock_bh(&sk->sk_lock.slock);
|
||||
if (unlikely(sock_owned_by_user_nocheck(sk)))
|
||||
__lock_sock(sk);
|
||||
|
||||
Reference in New Issue
Block a user