aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ipc/sem.c13
1 files changed, 10 insertions, 3 deletions
diff --git a/ipc/sem.c b/ipc/sem.c
index 53c3310f41c6..6115146563f9 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -326,10 +326,17 @@ static inline int sem_lock(struct sem_array *sma, struct sembuf *sops,
326 326
327 /* Then check that the global lock is free */ 327 /* Then check that the global lock is free */
328 if (!spin_is_locked(&sma->sem_perm.lock)) { 328 if (!spin_is_locked(&sma->sem_perm.lock)) {
329 /* spin_is_locked() is not a memory barrier */ 329 /*
330 smp_mb(); 330 * The ipc object lock check must be visible on all
331 * cores before rechecking the complex count. Otherwise
332 * we can race with another thread that does:
333 * complex_count++;
334 * spin_unlock(sem_perm.lock);
335 */
336 smp_rmb();
331 337
332 /* Now repeat the test of complex_count: 338 /*
339 * Now repeat the test of complex_count:
333 * It can't change anymore until we drop sem->lock. 340 * It can't change anymore until we drop sem->lock.
334 * Thus: if is now 0, then it will stay 0. 341 * Thus: if is now 0, then it will stay 0.
335 */ 342 */