diff options
| -rw-r--r-- | arch/x86/include/asm/spinlock.h | 4 | ||||
| -rw-r--r-- | include/linux/spinlock.h | 5 | ||||
| -rw-r--r-- | include/net/sock.h | 5 |
3 files changed, 13 insertions, 1 deletions
diff --git a/arch/x86/include/asm/spinlock.h b/arch/x86/include/asm/spinlock.h index b7e5db87639..4e77853321d 100644 --- a/arch/x86/include/asm/spinlock.h +++ b/arch/x86/include/asm/spinlock.h | |||
| @@ -302,4 +302,8 @@ static inline void __raw_write_unlock(raw_rwlock_t *rw) | |||
| 302 | #define _raw_read_relax(lock) cpu_relax() | 302 | #define _raw_read_relax(lock) cpu_relax() |
| 303 | #define _raw_write_relax(lock) cpu_relax() | 303 | #define _raw_write_relax(lock) cpu_relax() |
| 304 | 304 | ||
| 305 | /* The {read|write|spin}_lock() on x86 are full memory barriers. */ | ||
| 306 | static inline void smp_mb__after_lock(void) { } | ||
| 307 | #define ARCH_HAS_SMP_MB_AFTER_LOCK | ||
| 308 | |||
| 305 | #endif /* _ASM_X86_SPINLOCK_H */ | 309 | #endif /* _ASM_X86_SPINLOCK_H */ |
diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h index 252b245cfcf..4be57ab0347 100644 --- a/include/linux/spinlock.h +++ b/include/linux/spinlock.h | |||
| @@ -132,6 +132,11 @@ do { \ | |||
| 132 | #endif /*__raw_spin_is_contended*/ | 132 | #endif /*__raw_spin_is_contended*/ |
| 133 | #endif | 133 | #endif |
| 134 | 134 | ||
| 135 | /* The lock does not imply full memory barrier. */ | ||
| 136 | #ifndef ARCH_HAS_SMP_MB_AFTER_LOCK | ||
| 137 | static inline void smp_mb__after_lock(void) { smp_mb(); } | ||
| 138 | #endif | ||
| 139 | |||
| 135 | /** | 140 | /** |
| 136 | * spin_unlock_wait - wait until the spinlock gets unlocked | 141 | * spin_unlock_wait - wait until the spinlock gets unlocked |
| 137 | * @lock: the spinlock in question. | 142 | * @lock: the spinlock in question. |
diff --git a/include/net/sock.h b/include/net/sock.h index 4eb8409249f..2c0da9239b9 100644 --- a/include/net/sock.h +++ b/include/net/sock.h | |||
| @@ -1271,6 +1271,9 @@ static inline int sk_has_allocations(const struct sock *sk) | |||
| 1271 | * in its cache, and so does the tp->rcv_nxt update on CPU2 side. The CPU1 | 1271 | * in its cache, and so does the tp->rcv_nxt update on CPU2 side. The CPU1 |
| 1272 | * could then endup calling schedule and sleep forever if there are no more | 1272 | * could then endup calling schedule and sleep forever if there are no more |
| 1273 | * data on the socket. | 1273 | * data on the socket. |
| 1274 | * | ||
| 1275 | * The sk_has_sleeper is always called right after a call to read_lock, so we | ||
| 1276 | * can use smp_mb__after_lock barrier. | ||
| 1274 | */ | 1277 | */ |
| 1275 | static inline int sk_has_sleeper(struct sock *sk) | 1278 | static inline int sk_has_sleeper(struct sock *sk) |
| 1276 | { | 1279 | { |
| @@ -1280,7 +1283,7 @@ static inline int sk_has_sleeper(struct sock *sk) | |||
| 1280 | * | 1283 | * |
| 1281 | * This memory barrier is paired in the sock_poll_wait. | 1284 | * This memory barrier is paired in the sock_poll_wait. |
| 1282 | */ | 1285 | */ |
| 1283 | smp_mb(); | 1286 | smp_mb__after_lock(); |
| 1284 | return sk->sk_sleep && waitqueue_active(sk->sk_sleep); | 1287 | return sk->sk_sleep && waitqueue_active(sk->sk_sleep); |
| 1285 | } | 1288 | } |
| 1286 | 1289 | ||
