diff for duplicates of <20150123140832.GE23058@arm.com> diff --git a/a/1.txt b/N1/1.txt index 3e715b4..04541de 100644 --- a/a/1.txt +++ b/N1/1.txt @@ -33,442 +33,3 @@ Anyway, kicking this out there for comments. Will --->8 - -From 23d1db44f20a12924d2addeb73231f10d90e9f05 Mon Sep 17 00:00:00 2001 -From: Will Deacon <will.deacon@arm.com> -Date: Fri, 23 Jan 2015 13:55:34 +0000 -Subject: [PATCH] memory-barriers: remove smp_mb__after_unlock_lock() - -smp_mb__after_unlock_lock is used to promote an UNLOCK + LOCK sequence -into a full memory barrier. - -However: - - - This ordering guarantee is already provided without the barrier on - all architectures apart from PowerPC - - - The barrier only applies to UNLOCK + LOCK, not general - RELEASE + ACQUIRE operations - - - The barrier is not well used outside of RCU and, because it was - retrofitted into the kernel, it's not clear whether other areas of - the kernel are incorrectly relying on UNLOCK + LOCK implying a full - barrier - -This patch removes the barrier and instead requires architectures to -provide full barrier semantics for an UNLOCK + LOCK sequence. - -TODO: add a barrier to PowerPC unlock? - -Signed-off-by: Will Deacon <will.deacon@arm.com> ---- - Documentation/memory-barriers.txt | 77 ++----------------------------------- - arch/powerpc/include/asm/spinlock.h | 2 - - include/linux/spinlock.h | 10 ----- - kernel/locking/mcs_spinlock.h | 9 ----- - kernel/rcu/tree.c | 19 +-------- - kernel/rcu/tree_plugin.h | 13 ------- - 6 files changed, 4 insertions(+), 126 deletions(-) - -diff --git a/Documentation/memory-barriers.txt b/Documentation/memory-barriers.txt -index 9c0e3c45a807..fed47737e4c6 100644 ---- a/Documentation/memory-barriers.txt -+++ b/Documentation/memory-barriers.txt -@@ -1777,74 +1777,9 @@ RELEASE are to the same lock variable, but only from the perspective of - another CPU not holding that lock. In short, a ACQUIRE followed by an - RELEASE may -not- be assumed to be a full memory barrier. - --Similarly, the reverse case of a RELEASE followed by an ACQUIRE does not --imply a full memory barrier. If it is necessary for a RELEASE-ACQUIRE --pair to produce a full barrier, the ACQUIRE can be followed by an --smp_mb__after_unlock_lock() invocation. This will produce a full barrier --if either (a) the RELEASE and the ACQUIRE are executed by the same --CPU or task, or (b) the RELEASE and ACQUIRE act on the same variable. --The smp_mb__after_unlock_lock() primitive is free on many architectures. --Without smp_mb__after_unlock_lock(), the CPU's execution of the critical --sections corresponding to the RELEASE and the ACQUIRE can cross, so that: -- -- *A = a; -- RELEASE M -- ACQUIRE N -- *B = b; -- --could occur as: -- -- ACQUIRE N, STORE *B, STORE *A, RELEASE M -- --It might appear that this reordering could introduce a deadlock. --However, this cannot happen because if such a deadlock threatened, --the RELEASE would simply complete, thereby avoiding the deadlock. -- -- Why does this work? -- -- One key point is that we are only talking about the CPU doing -- the reordering, not the compiler. If the compiler (or, for -- that matter, the developer) switched the operations, deadlock -- -could- occur. -- -- But suppose the CPU reordered the operations. In this case, -- the unlock precedes the lock in the assembly code. The CPU -- simply elected to try executing the later lock operation first. -- If there is a deadlock, this lock operation will simply spin (or -- try to sleep, but more on that later). The CPU will eventually -- execute the unlock operation (which preceded the lock operation -- in the assembly code), which will unravel the potential deadlock, -- allowing the lock operation to succeed. -- -- But what if the lock is a sleeplock? In that case, the code will -- try to enter the scheduler, where it will eventually encounter -- a memory barrier, which will force the earlier unlock operation -- to complete, again unraveling the deadlock. There might be -- a sleep-unlock race, but the locking primitive needs to resolve -- such races properly in any case. -- --With smp_mb__after_unlock_lock(), the two critical sections cannot overlap. --For example, with the following code, the store to *A will always be --seen by other CPUs before the store to *B: -- -- *A = a; -- RELEASE M -- ACQUIRE N -- smp_mb__after_unlock_lock(); -- *B = b; -- --The operations will always occur in one of the following orders: -- -- STORE *A, RELEASE, ACQUIRE, smp_mb__after_unlock_lock(), STORE *B -- STORE *A, ACQUIRE, RELEASE, smp_mb__after_unlock_lock(), STORE *B -- ACQUIRE, STORE *A, RELEASE, smp_mb__after_unlock_lock(), STORE *B -- --If the RELEASE and ACQUIRE were instead both operating on the same lock --variable, only the first of these alternatives can occur. In addition, --the more strongly ordered systems may rule out some of the above orders. --But in any case, as noted earlier, the smp_mb__after_unlock_lock() --ensures that the store to *A will always be seen as happening before --the store to *B. -+However, the reverse case of a RELEASE followed by an ACQUIRE _does_ -+imply a full memory barrier when these accesses are performed as a pair -+of UNLOCK and LOCK operations, irrespective of the lock variable. - - Locks and semaphores may not provide any guarantee of ordering on UP compiled - systems, and so cannot be counted on in such a situation to actually achieve -@@ -2087,7 +2022,6 @@ However, if the following occurs: - RELEASE M [1] - ACCESS_ONCE(*D) = d; ACCESS_ONCE(*E) = e; - ACQUIRE M [2] -- smp_mb__after_unlock_lock(); - ACCESS_ONCE(*F) = f; - ACCESS_ONCE(*G) = g; - RELEASE M [2] -@@ -2105,11 +2039,6 @@ But assuming CPU 1 gets the lock first, CPU 3 won't see any of: - *F, *G or *H preceding ACQUIRE M [2] - *A, *B, *C, *E, *F or *G following RELEASE M [2] - --Note that the smp_mb__after_unlock_lock() is critically important --here: Without it CPU 3 might see some of the above orderings. --Without smp_mb__after_unlock_lock(), the accesses are not guaranteed --to be seen in order unless CPU 3 holds lock M. -- - - ACQUIRES VS I/O ACCESSES - ------------------------ -diff --git a/arch/powerpc/include/asm/spinlock.h b/arch/powerpc/include/asm/spinlock.h -index 4dbe072eecbe..523673d7583c 100644 ---- a/arch/powerpc/include/asm/spinlock.h -+++ b/arch/powerpc/include/asm/spinlock.h -@@ -28,8 +28,6 @@ - #include <asm/synch.h> - #include <asm/ppc-opcode.h> - --#define smp_mb__after_unlock_lock() smp_mb() /* Full ordering for lock. */ -- - #ifdef CONFIG_PPC64 - /* use 0x800000yy when locked, where yy == CPU number */ - #ifdef __BIG_ENDIAN__ -diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h -index 262ba4ef9a8e..9e8ba39640ce 100644 ---- a/include/linux/spinlock.h -+++ b/include/linux/spinlock.h -@@ -130,16 +130,6 @@ do { \ - #define smp_mb__before_spinlock() smp_wmb() - #endif - --/* -- * Place this after a lock-acquisition primitive to guarantee that -- * an UNLOCK+LOCK pair act as a full barrier. This guarantee applies -- * if the UNLOCK and LOCK are executed by the same CPU or if the -- * UNLOCK and LOCK operate on the same lock variable. -- */ --#ifndef smp_mb__after_unlock_lock --#define smp_mb__after_unlock_lock() do { } while (0) --#endif -- - /** - * raw_spin_unlock_wait - wait until the spinlock gets unlocked - * @lock: the spinlock in question. -diff --git a/kernel/locking/mcs_spinlock.h b/kernel/locking/mcs_spinlock.h -index 4d60986fcbee..6d60c9f7dc87 100644 ---- a/kernel/locking/mcs_spinlock.h -+++ b/kernel/locking/mcs_spinlock.h -@@ -42,15 +42,6 @@ do { \ - #endif - - /* -- * Note: the smp_load_acquire/smp_store_release pair is not -- * sufficient to form a full memory barrier across -- * cpus for many architectures (except x86) for mcs_unlock and mcs_lock. -- * For applications that need a full barrier across multiple cpus -- * with mcs_unlock and mcs_lock pair, smp_mb__after_unlock_lock() should be -- * used after mcs_lock. -- */ -- --/* - * In order to acquire the lock, the caller should declare a local node and - * pass a reference of the node to this function in addition to the lock. - * If the lock has already been acquired, then this will proceed to spin -diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c -index 7680fc275036..86595ead34ec 100644 ---- a/kernel/rcu/tree.c -+++ b/kernel/rcu/tree.c -@@ -1322,10 +1322,8 @@ rcu_start_future_gp(struct rcu_node *rnp, struct rcu_data *rdp, - * hold it, acquire the root rcu_node structure's lock in order to - * start one (if needed). - */ -- if (rnp != rnp_root) { -+ if (rnp != rnp_root) - raw_spin_lock(&rnp_root->lock); -- smp_mb__after_unlock_lock(); -- } - - /* - * Get a new grace-period number. If there really is no grace -@@ -1574,7 +1572,6 @@ static void note_gp_changes(struct rcu_state *rsp, struct rcu_data *rdp) - local_irq_restore(flags); - return; - } -- smp_mb__after_unlock_lock(); - needwake = __note_gp_changes(rsp, rnp, rdp); - raw_spin_unlock_irqrestore(&rnp->lock, flags); - if (needwake) -@@ -1591,7 +1588,6 @@ static int rcu_gp_init(struct rcu_state *rsp) - - rcu_bind_gp_kthread(); - raw_spin_lock_irq(&rnp->lock); -- smp_mb__after_unlock_lock(); - if (!ACCESS_ONCE(rsp->gp_flags)) { - /* Spurious wakeup, tell caller to go back to sleep. */ - raw_spin_unlock_irq(&rnp->lock); -@@ -1617,7 +1613,6 @@ static int rcu_gp_init(struct rcu_state *rsp) - - /* Exclude any concurrent CPU-hotplug operations. */ - mutex_lock(&rsp->onoff_mutex); -- smp_mb__after_unlock_lock(); /* ->gpnum increment before GP! */ - - /* - * Set the quiescent-state-needed bits in all the rcu_node -@@ -1634,7 +1629,6 @@ static int rcu_gp_init(struct rcu_state *rsp) - */ - rcu_for_each_node_breadth_first(rsp, rnp) { - raw_spin_lock_irq(&rnp->lock); -- smp_mb__after_unlock_lock(); - rdp = this_cpu_ptr(rsp->rda); - rcu_preempt_check_blocked_tasks(rnp); - rnp->qsmask = rnp->qsmaskinit; -@@ -1684,7 +1678,6 @@ static int rcu_gp_fqs(struct rcu_state *rsp, int fqs_state_in) - /* Clear flag to prevent immediate re-entry. */ - if (ACCESS_ONCE(rsp->gp_flags) & RCU_GP_FLAG_FQS) { - raw_spin_lock_irq(&rnp->lock); -- smp_mb__after_unlock_lock(); - ACCESS_ONCE(rsp->gp_flags) = - ACCESS_ONCE(rsp->gp_flags) & ~RCU_GP_FLAG_FQS; - raw_spin_unlock_irq(&rnp->lock); -@@ -1704,7 +1697,6 @@ static void rcu_gp_cleanup(struct rcu_state *rsp) - struct rcu_node *rnp = rcu_get_root(rsp); - - raw_spin_lock_irq(&rnp->lock); -- smp_mb__after_unlock_lock(); - gp_duration = jiffies - rsp->gp_start; - if (gp_duration > rsp->gp_max) - rsp->gp_max = gp_duration; -@@ -1730,7 +1722,6 @@ static void rcu_gp_cleanup(struct rcu_state *rsp) - */ - rcu_for_each_node_breadth_first(rsp, rnp) { - raw_spin_lock_irq(&rnp->lock); -- smp_mb__after_unlock_lock(); - ACCESS_ONCE(rnp->completed) = rsp->gpnum; - rdp = this_cpu_ptr(rsp->rda); - if (rnp == rdp->mynode) -@@ -1742,7 +1733,6 @@ static void rcu_gp_cleanup(struct rcu_state *rsp) - } - rnp = rcu_get_root(rsp); - raw_spin_lock_irq(&rnp->lock); -- smp_mb__after_unlock_lock(); /* Order GP before ->completed update. */ - rcu_nocb_gp_set(rnp, nocb); - - /* Declare grace period done. */ -@@ -1978,7 +1968,6 @@ rcu_report_qs_rnp(unsigned long mask, struct rcu_state *rsp, - rnp_c = rnp; - rnp = rnp->parent; - raw_spin_lock_irqsave(&rnp->lock, flags); -- smp_mb__after_unlock_lock(); - WARN_ON_ONCE(rnp_c->qsmask); - } - -@@ -2009,7 +1998,6 @@ rcu_report_qs_rdp(int cpu, struct rcu_state *rsp, struct rcu_data *rdp) - - rnp = rdp->mynode; - raw_spin_lock_irqsave(&rnp->lock, flags); -- smp_mb__after_unlock_lock(); - if (rdp->passed_quiesce == 0 || rdp->gpnum != rnp->gpnum || - rnp->completed == rnp->gpnum) { - -@@ -2224,7 +2212,6 @@ static void rcu_cleanup_dead_cpu(int cpu, struct rcu_state *rsp) - mask = rdp->grpmask; /* rnp->grplo is constant. */ - do { - raw_spin_lock(&rnp->lock); /* irqs already disabled. */ -- smp_mb__after_unlock_lock(); - rnp->qsmaskinit &= ~mask; - if (rnp->qsmaskinit != 0) { - if (rnp != rdp->mynode) -@@ -2437,7 +2424,6 @@ static void force_qs_rnp(struct rcu_state *rsp, - cond_resched_rcu_qs(); - mask = 0; - raw_spin_lock_irqsave(&rnp->lock, flags); -- smp_mb__after_unlock_lock(); - if (!rcu_gp_in_progress(rsp)) { - raw_spin_unlock_irqrestore(&rnp->lock, flags); - return; -@@ -2467,7 +2453,6 @@ static void force_qs_rnp(struct rcu_state *rsp, - rnp = rcu_get_root(rsp); - if (rnp->qsmask == 0) { - raw_spin_lock_irqsave(&rnp->lock, flags); -- smp_mb__after_unlock_lock(); - rcu_initiate_boost(rnp, flags); /* releases rnp->lock. */ - } - } -@@ -2500,7 +2485,6 @@ static void force_quiescent_state(struct rcu_state *rsp) - - /* Reached the root of the rcu_node tree, acquire lock. */ - raw_spin_lock_irqsave(&rnp_old->lock, flags); -- smp_mb__after_unlock_lock(); - raw_spin_unlock(&rnp_old->fqslock); - if (ACCESS_ONCE(rsp->gp_flags) & RCU_GP_FLAG_FQS) { - rsp->n_force_qs_lh++; -@@ -2625,7 +2609,6 @@ static void __call_rcu_core(struct rcu_state *rsp, struct rcu_data *rdp, - struct rcu_node *rnp_root = rcu_get_root(rsp); - - raw_spin_lock(&rnp_root->lock); -- smp_mb__after_unlock_lock(); - needwake = rcu_start_gp(rsp); - raw_spin_unlock(&rnp_root->lock); - if (needwake) -diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h -index 3ec85cb5d544..a89523605545 100644 ---- a/kernel/rcu/tree_plugin.h -+++ b/kernel/rcu/tree_plugin.h -@@ -180,7 +180,6 @@ static void rcu_preempt_note_context_switch(void) - rdp = this_cpu_ptr(rcu_preempt_state.rda); - rnp = rdp->mynode; - raw_spin_lock_irqsave(&rnp->lock, flags); -- smp_mb__after_unlock_lock(); - t->rcu_read_unlock_special.b.blocked = true; - t->rcu_blocked_node = rnp; - -@@ -287,7 +286,6 @@ static void rcu_report_unblock_qs_rnp(struct rcu_node *rnp, unsigned long flags) - mask = rnp->grpmask; - raw_spin_unlock(&rnp->lock); /* irqs remain disabled. */ - raw_spin_lock(&rnp_p->lock); /* irqs already disabled. */ -- smp_mb__after_unlock_lock(); - rcu_report_qs_rnp(mask, &rcu_preempt_state, rnp_p, flags); - } - -@@ -362,7 +360,6 @@ void rcu_read_unlock_special(struct task_struct *t) - for (;;) { - rnp = t->rcu_blocked_node; - raw_spin_lock(&rnp->lock); /* irqs already disabled. */ -- smp_mb__after_unlock_lock(); - if (rnp == t->rcu_blocked_node) - break; - raw_spin_unlock(&rnp->lock); /* irqs remain disabled. */ -@@ -576,7 +573,6 @@ static int rcu_preempt_offline_tasks(struct rcu_state *rsp, - while (!list_empty(lp)) { - t = list_entry(lp->next, typeof(*t), rcu_node_entry); - raw_spin_lock(&rnp_root->lock); /* irqs already disabled */ -- smp_mb__after_unlock_lock(); - list_del(&t->rcu_node_entry); - t->rcu_blocked_node = rnp_root; - list_add(&t->rcu_node_entry, lp_root); -@@ -601,7 +597,6 @@ static int rcu_preempt_offline_tasks(struct rcu_state *rsp, - * in this case. - */ - raw_spin_lock(&rnp_root->lock); /* irqs already disabled */ -- smp_mb__after_unlock_lock(); - if (rnp_root->boost_tasks != NULL && - rnp_root->boost_tasks != rnp_root->gp_tasks && - rnp_root->boost_tasks != rnp_root->exp_tasks) -@@ -732,7 +727,6 @@ static void rcu_report_exp_rnp(struct rcu_state *rsp, struct rcu_node *rnp, - unsigned long mask; - - raw_spin_lock_irqsave(&rnp->lock, flags); -- smp_mb__after_unlock_lock(); - for (;;) { - if (!sync_rcu_preempt_exp_done(rnp)) { - raw_spin_unlock_irqrestore(&rnp->lock, flags); -@@ -750,7 +744,6 @@ static void rcu_report_exp_rnp(struct rcu_state *rsp, struct rcu_node *rnp, - raw_spin_unlock(&rnp->lock); /* irqs remain disabled */ - rnp = rnp->parent; - raw_spin_lock(&rnp->lock); /* irqs already disabled */ -- smp_mb__after_unlock_lock(); - rnp->expmask &= ~mask; - } - } -@@ -770,7 +763,6 @@ sync_rcu_preempt_exp_init(struct rcu_state *rsp, struct rcu_node *rnp) - int must_wait = 0; - - raw_spin_lock_irqsave(&rnp->lock, flags); -- smp_mb__after_unlock_lock(); - if (list_empty(&rnp->blkd_tasks)) { - raw_spin_unlock_irqrestore(&rnp->lock, flags); - } else { -@@ -850,7 +842,6 @@ void synchronize_rcu_expedited(void) - /* Initialize ->expmask for all non-leaf rcu_node structures. */ - rcu_for_each_nonleaf_node_breadth_first(rsp, rnp) { - raw_spin_lock_irqsave(&rnp->lock, flags); -- smp_mb__after_unlock_lock(); - rnp->expmask = rnp->qsmaskinit; - raw_spin_unlock_irqrestore(&rnp->lock, flags); - } -@@ -1131,7 +1122,6 @@ static int rcu_boost(struct rcu_node *rnp) - return 0; /* Nothing left to boost. */ - - raw_spin_lock_irqsave(&rnp->lock, flags); -- smp_mb__after_unlock_lock(); - - /* - * Recheck under the lock: all tasks in need of boosting -@@ -1323,7 +1313,6 @@ static int rcu_spawn_one_boost_kthread(struct rcu_state *rsp, - if (IS_ERR(t)) - return PTR_ERR(t); - raw_spin_lock_irqsave(&rnp->lock, flags); -- smp_mb__after_unlock_lock(); - rnp->boost_kthread_task = t; - raw_spin_unlock_irqrestore(&rnp->lock, flags); - sp.sched_priority = kthread_prio; -@@ -1717,7 +1706,6 @@ static void rcu_prepare_for_idle(void) - continue; - rnp = rdp->mynode; - raw_spin_lock(&rnp->lock); /* irqs already disabled. */ -- smp_mb__after_unlock_lock(); - needwake = rcu_accelerate_cbs(rsp, rnp, rdp); - raw_spin_unlock(&rnp->lock); /* irqs remain disabled. */ - if (needwake) -@@ -2226,7 +2214,6 @@ static void rcu_nocb_wait_gp(struct rcu_data *rdp) - struct rcu_node *rnp = rdp->mynode; - - raw_spin_lock_irqsave(&rnp->lock, flags); -- smp_mb__after_unlock_lock(); - needwake = rcu_start_future_gp(rnp, rdp, &c); - raw_spin_unlock_irqrestore(&rnp->lock, flags); - if (needwake) --- -2.1.4 diff --git a/a/content_digest b/N1/content_digest index d54a6c3..d2b08dc 100644 --- a/a/content_digest +++ b/N1/content_digest @@ -47,445 +47,6 @@ "\n" "Will\n" "\n" - "--->8\n" - "\n" - "From 23d1db44f20a12924d2addeb73231f10d90e9f05 Mon Sep 17 00:00:00 2001\n" - "From: Will Deacon <will.deacon@arm.com>\n" - "Date: Fri, 23 Jan 2015 13:55:34 +0000\n" - "Subject: [PATCH] memory-barriers: remove smp_mb__after_unlock_lock()\n" - "\n" - "smp_mb__after_unlock_lock is used to promote an UNLOCK + LOCK sequence\n" - "into a full memory barrier.\n" - "\n" - "However:\n" - "\n" - " - This ordering guarantee is already provided without the barrier on\n" - " all architectures apart from PowerPC\n" - "\n" - " - The barrier only applies to UNLOCK + LOCK, not general\n" - " RELEASE + ACQUIRE operations\n" - "\n" - " - The barrier is not well used outside of RCU and, because it was\n" - " retrofitted into the kernel, it's not clear whether other areas of\n" - " the kernel are incorrectly relying on UNLOCK + LOCK implying a full\n" - " barrier\n" - "\n" - "This patch removes the barrier and instead requires architectures to\n" - "provide full barrier semantics for an UNLOCK + LOCK sequence.\n" - "\n" - "TODO: add a barrier to PowerPC unlock?\n" - "\n" - "Signed-off-by: Will Deacon <will.deacon@arm.com>\n" - "---\n" - " Documentation/memory-barriers.txt | 77 ++-----------------------------------\n" - " arch/powerpc/include/asm/spinlock.h | 2 -\n" - " include/linux/spinlock.h | 10 -----\n" - " kernel/locking/mcs_spinlock.h | 9 -----\n" - " kernel/rcu/tree.c | 19 +--------\n" - " kernel/rcu/tree_plugin.h | 13 -------\n" - " 6 files changed, 4 insertions(+), 126 deletions(-)\n" - "\n" - "diff --git a/Documentation/memory-barriers.txt b/Documentation/memory-barriers.txt\n" - "index 9c0e3c45a807..fed47737e4c6 100644\n" - "--- a/Documentation/memory-barriers.txt\n" - "+++ b/Documentation/memory-barriers.txt\n" - "@@ -1777,74 +1777,9 @@ RELEASE are to the same lock variable, but only from the perspective of\n" - " another CPU not holding that lock. In short, a ACQUIRE followed by an\n" - " RELEASE may -not- be assumed to be a full memory barrier.\n" - " \n" - "-Similarly, the reverse case of a RELEASE followed by an ACQUIRE does not\n" - "-imply a full memory barrier. If it is necessary for a RELEASE-ACQUIRE\n" - "-pair to produce a full barrier, the ACQUIRE can be followed by an\n" - "-smp_mb__after_unlock_lock() invocation. This will produce a full barrier\n" - "-if either (a) the RELEASE and the ACQUIRE are executed by the same\n" - "-CPU or task, or (b) the RELEASE and ACQUIRE act on the same variable.\n" - "-The smp_mb__after_unlock_lock() primitive is free on many architectures.\n" - "-Without smp_mb__after_unlock_lock(), the CPU's execution of the critical\n" - "-sections corresponding to the RELEASE and the ACQUIRE can cross, so that:\n" - "-\n" - "-\t*A = a;\n" - "-\tRELEASE M\n" - "-\tACQUIRE N\n" - "-\t*B = b;\n" - "-\n" - "-could occur as:\n" - "-\n" - "-\tACQUIRE N, STORE *B, STORE *A, RELEASE M\n" - "-\n" - "-It might appear that this reordering could introduce a deadlock.\n" - "-However, this cannot happen because if such a deadlock threatened,\n" - "-the RELEASE would simply complete, thereby avoiding the deadlock.\n" - "-\n" - "-\tWhy does this work?\n" - "-\n" - "-\tOne key point is that we are only talking about the CPU doing\n" - "-\tthe reordering, not the compiler. If the compiler (or, for\n" - "-\tthat matter, the developer) switched the operations, deadlock\n" - "-\t-could- occur.\n" - "-\n" - "-\tBut suppose the CPU reordered the operations. In this case,\n" - "-\tthe unlock precedes the lock in the assembly code. The CPU\n" - "-\tsimply elected to try executing the later lock operation first.\n" - "-\tIf there is a deadlock, this lock operation will simply spin (or\n" - "-\ttry to sleep, but more on that later).\tThe CPU will eventually\n" - "-\texecute the unlock operation (which preceded the lock operation\n" - "-\tin the assembly code), which will unravel the potential deadlock,\n" - "-\tallowing the lock operation to succeed.\n" - "-\n" - "-\tBut what if the lock is a sleeplock? In that case, the code will\n" - "-\ttry to enter the scheduler, where it will eventually encounter\n" - "-\ta memory barrier, which will force the earlier unlock operation\n" - "-\tto complete, again unraveling the deadlock. There might be\n" - "-\ta sleep-unlock race, but the locking primitive needs to resolve\n" - "-\tsuch races properly in any case.\n" - "-\n" - "-With smp_mb__after_unlock_lock(), the two critical sections cannot overlap.\n" - "-For example, with the following code, the store to *A will always be\n" - "-seen by other CPUs before the store to *B:\n" - "-\n" - "-\t*A = a;\n" - "-\tRELEASE M\n" - "-\tACQUIRE N\n" - "-\tsmp_mb__after_unlock_lock();\n" - "-\t*B = b;\n" - "-\n" - "-The operations will always occur in one of the following orders:\n" - "-\n" - "-\tSTORE *A, RELEASE, ACQUIRE, smp_mb__after_unlock_lock(), STORE *B\n" - "-\tSTORE *A, ACQUIRE, RELEASE, smp_mb__after_unlock_lock(), STORE *B\n" - "-\tACQUIRE, STORE *A, RELEASE, smp_mb__after_unlock_lock(), STORE *B\n" - "-\n" - "-If the RELEASE and ACQUIRE were instead both operating on the same lock\n" - "-variable, only the first of these alternatives can occur. In addition,\n" - "-the more strongly ordered systems may rule out some of the above orders.\n" - "-But in any case, as noted earlier, the smp_mb__after_unlock_lock()\n" - "-ensures that the store to *A will always be seen as happening before\n" - "-the store to *B.\n" - "+However, the reverse case of a RELEASE followed by an ACQUIRE _does_\n" - "+imply a full memory barrier when these accesses are performed as a pair\n" - "+of UNLOCK and LOCK operations, irrespective of the lock variable.\n" - " \n" - " Locks and semaphores may not provide any guarantee of ordering on UP compiled\n" - " systems, and so cannot be counted on in such a situation to actually achieve\n" - "@@ -2087,7 +2022,6 @@ However, if the following occurs:\n" - " \tRELEASE M\t [1]\n" - " \tACCESS_ONCE(*D) = d;\t\tACCESS_ONCE(*E) = e;\n" - " \t\t\t\t\tACQUIRE M\t\t [2]\n" - "-\t\t\t\t\tsmp_mb__after_unlock_lock();\n" - " \t\t\t\t\tACCESS_ONCE(*F) = f;\n" - " \t\t\t\t\tACCESS_ONCE(*G) = g;\n" - " \t\t\t\t\tRELEASE M\t [2]\n" - "@@ -2105,11 +2039,6 @@ But assuming CPU 1 gets the lock first, CPU 3 won't see any of:\n" - " \t*F, *G or *H preceding ACQUIRE M [2]\n" - " \t*A, *B, *C, *E, *F or *G following RELEASE M [2]\n" - " \n" - "-Note that the smp_mb__after_unlock_lock() is critically important\n" - "-here: Without it CPU 3 might see some of the above orderings.\n" - "-Without smp_mb__after_unlock_lock(), the accesses are not guaranteed\n" - "-to be seen in order unless CPU 3 holds lock M.\n" - "-\n" - " \n" - " ACQUIRES VS I/O ACCESSES\n" - " ------------------------\n" - "diff --git a/arch/powerpc/include/asm/spinlock.h b/arch/powerpc/include/asm/spinlock.h\n" - "index 4dbe072eecbe..523673d7583c 100644\n" - "--- a/arch/powerpc/include/asm/spinlock.h\n" - "+++ b/arch/powerpc/include/asm/spinlock.h\n" - "@@ -28,8 +28,6 @@\n" - " #include <asm/synch.h>\n" - " #include <asm/ppc-opcode.h>\n" - " \n" - "-#define smp_mb__after_unlock_lock()\tsmp_mb() /* Full ordering for lock. */\n" - "-\n" - " #ifdef CONFIG_PPC64\n" - " /* use 0x800000yy when locked, where yy == CPU number */\n" - " #ifdef __BIG_ENDIAN__\n" - "diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h\n" - "index 262ba4ef9a8e..9e8ba39640ce 100644\n" - "--- a/include/linux/spinlock.h\n" - "+++ b/include/linux/spinlock.h\n" - "@@ -130,16 +130,6 @@ do {\t\t\t\t\t\t\t\t\\\n" - " #define smp_mb__before_spinlock()\tsmp_wmb()\n" - " #endif\n" - " \n" - "-/*\n" - "- * Place this after a lock-acquisition primitive to guarantee that\n" - "- * an UNLOCK+LOCK pair act as a full barrier. This guarantee applies\n" - "- * if the UNLOCK and LOCK are executed by the same CPU or if the\n" - "- * UNLOCK and LOCK operate on the same lock variable.\n" - "- */\n" - "-#ifndef smp_mb__after_unlock_lock\n" - "-#define smp_mb__after_unlock_lock()\tdo { } while (0)\n" - "-#endif\n" - "-\n" - " /**\n" - " * raw_spin_unlock_wait - wait until the spinlock gets unlocked\n" - " * @lock: the spinlock in question.\n" - "diff --git a/kernel/locking/mcs_spinlock.h b/kernel/locking/mcs_spinlock.h\n" - "index 4d60986fcbee..6d60c9f7dc87 100644\n" - "--- a/kernel/locking/mcs_spinlock.h\n" - "+++ b/kernel/locking/mcs_spinlock.h\n" - "@@ -42,15 +42,6 @@ do {\t\t\t\t\t\t\t\t\t\\\n" - " #endif\n" - " \n" - " /*\n" - "- * Note: the smp_load_acquire/smp_store_release pair is not\n" - "- * sufficient to form a full memory barrier across\n" - "- * cpus for many architectures (except x86) for mcs_unlock and mcs_lock.\n" - "- * For applications that need a full barrier across multiple cpus\n" - "- * with mcs_unlock and mcs_lock pair, smp_mb__after_unlock_lock() should be\n" - "- * used after mcs_lock.\n" - "- */\n" - "-\n" - "-/*\n" - " * In order to acquire the lock, the caller should declare a local node and\n" - " * pass a reference of the node to this function in addition to the lock.\n" - " * If the lock has already been acquired, then this will proceed to spin\n" - "diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c\n" - "index 7680fc275036..86595ead34ec 100644\n" - "--- a/kernel/rcu/tree.c\n" - "+++ b/kernel/rcu/tree.c\n" - "@@ -1322,10 +1322,8 @@ rcu_start_future_gp(struct rcu_node *rnp, struct rcu_data *rdp,\n" - " \t * hold it, acquire the root rcu_node structure's lock in order to\n" - " \t * start one (if needed).\n" - " \t */\n" - "-\tif (rnp != rnp_root) {\n" - "+\tif (rnp != rnp_root)\n" - " \t\traw_spin_lock(&rnp_root->lock);\n" - "-\t\tsmp_mb__after_unlock_lock();\n" - "-\t}\n" - " \n" - " \t/*\n" - " \t * Get a new grace-period number. If there really is no grace\n" - "@@ -1574,7 +1572,6 @@ static void note_gp_changes(struct rcu_state *rsp, struct rcu_data *rdp)\n" - " \t\tlocal_irq_restore(flags);\n" - " \t\treturn;\n" - " \t}\n" - "-\tsmp_mb__after_unlock_lock();\n" - " \tneedwake = __note_gp_changes(rsp, rnp, rdp);\n" - " \traw_spin_unlock_irqrestore(&rnp->lock, flags);\n" - " \tif (needwake)\n" - "@@ -1591,7 +1588,6 @@ static int rcu_gp_init(struct rcu_state *rsp)\n" - " \n" - " \trcu_bind_gp_kthread();\n" - " \traw_spin_lock_irq(&rnp->lock);\n" - "-\tsmp_mb__after_unlock_lock();\n" - " \tif (!ACCESS_ONCE(rsp->gp_flags)) {\n" - " \t\t/* Spurious wakeup, tell caller to go back to sleep. */\n" - " \t\traw_spin_unlock_irq(&rnp->lock);\n" - "@@ -1617,7 +1613,6 @@ static int rcu_gp_init(struct rcu_state *rsp)\n" - " \n" - " \t/* Exclude any concurrent CPU-hotplug operations. */\n" - " \tmutex_lock(&rsp->onoff_mutex);\n" - "-\tsmp_mb__after_unlock_lock(); /* ->gpnum increment before GP! */\n" - " \n" - " \t/*\n" - " \t * Set the quiescent-state-needed bits in all the rcu_node\n" - "@@ -1634,7 +1629,6 @@ static int rcu_gp_init(struct rcu_state *rsp)\n" - " \t */\n" - " \trcu_for_each_node_breadth_first(rsp, rnp) {\n" - " \t\traw_spin_lock_irq(&rnp->lock);\n" - "-\t\tsmp_mb__after_unlock_lock();\n" - " \t\trdp = this_cpu_ptr(rsp->rda);\n" - " \t\trcu_preempt_check_blocked_tasks(rnp);\n" - " \t\trnp->qsmask = rnp->qsmaskinit;\n" - "@@ -1684,7 +1678,6 @@ static int rcu_gp_fqs(struct rcu_state *rsp, int fqs_state_in)\n" - " \t/* Clear flag to prevent immediate re-entry. */\n" - " \tif (ACCESS_ONCE(rsp->gp_flags) & RCU_GP_FLAG_FQS) {\n" - " \t\traw_spin_lock_irq(&rnp->lock);\n" - "-\t\tsmp_mb__after_unlock_lock();\n" - " \t\tACCESS_ONCE(rsp->gp_flags) =\n" - " \t\t\tACCESS_ONCE(rsp->gp_flags) & ~RCU_GP_FLAG_FQS;\n" - " \t\traw_spin_unlock_irq(&rnp->lock);\n" - "@@ -1704,7 +1697,6 @@ static void rcu_gp_cleanup(struct rcu_state *rsp)\n" - " \tstruct rcu_node *rnp = rcu_get_root(rsp);\n" - " \n" - " \traw_spin_lock_irq(&rnp->lock);\n" - "-\tsmp_mb__after_unlock_lock();\n" - " \tgp_duration = jiffies - rsp->gp_start;\n" - " \tif (gp_duration > rsp->gp_max)\n" - " \t\trsp->gp_max = gp_duration;\n" - "@@ -1730,7 +1722,6 @@ static void rcu_gp_cleanup(struct rcu_state *rsp)\n" - " \t */\n" - " \trcu_for_each_node_breadth_first(rsp, rnp) {\n" - " \t\traw_spin_lock_irq(&rnp->lock);\n" - "-\t\tsmp_mb__after_unlock_lock();\n" - " \t\tACCESS_ONCE(rnp->completed) = rsp->gpnum;\n" - " \t\trdp = this_cpu_ptr(rsp->rda);\n" - " \t\tif (rnp == rdp->mynode)\n" - "@@ -1742,7 +1733,6 @@ static void rcu_gp_cleanup(struct rcu_state *rsp)\n" - " \t}\n" - " \trnp = rcu_get_root(rsp);\n" - " \traw_spin_lock_irq(&rnp->lock);\n" - "-\tsmp_mb__after_unlock_lock(); /* Order GP before ->completed update. */\n" - " \trcu_nocb_gp_set(rnp, nocb);\n" - " \n" - " \t/* Declare grace period done. */\n" - "@@ -1978,7 +1968,6 @@ rcu_report_qs_rnp(unsigned long mask, struct rcu_state *rsp,\n" - " \t\trnp_c = rnp;\n" - " \t\trnp = rnp->parent;\n" - " \t\traw_spin_lock_irqsave(&rnp->lock, flags);\n" - "-\t\tsmp_mb__after_unlock_lock();\n" - " \t\tWARN_ON_ONCE(rnp_c->qsmask);\n" - " \t}\n" - " \n" - "@@ -2009,7 +1998,6 @@ rcu_report_qs_rdp(int cpu, struct rcu_state *rsp, struct rcu_data *rdp)\n" - " \n" - " \trnp = rdp->mynode;\n" - " \traw_spin_lock_irqsave(&rnp->lock, flags);\n" - "-\tsmp_mb__after_unlock_lock();\n" - " \tif (rdp->passed_quiesce == 0 || rdp->gpnum != rnp->gpnum ||\n" - " \t rnp->completed == rnp->gpnum) {\n" - " \n" - "@@ -2224,7 +2212,6 @@ static void rcu_cleanup_dead_cpu(int cpu, struct rcu_state *rsp)\n" - " \tmask = rdp->grpmask;\t/* rnp->grplo is constant. */\n" - " \tdo {\n" - " \t\traw_spin_lock(&rnp->lock);\t/* irqs already disabled. */\n" - "-\t\tsmp_mb__after_unlock_lock();\n" - " \t\trnp->qsmaskinit &= ~mask;\n" - " \t\tif (rnp->qsmaskinit != 0) {\n" - " \t\t\tif (rnp != rdp->mynode)\n" - "@@ -2437,7 +2424,6 @@ static void force_qs_rnp(struct rcu_state *rsp,\n" - " \t\tcond_resched_rcu_qs();\n" - " \t\tmask = 0;\n" - " \t\traw_spin_lock_irqsave(&rnp->lock, flags);\n" - "-\t\tsmp_mb__after_unlock_lock();\n" - " \t\tif (!rcu_gp_in_progress(rsp)) {\n" - " \t\t\traw_spin_unlock_irqrestore(&rnp->lock, flags);\n" - " \t\t\treturn;\n" - "@@ -2467,7 +2453,6 @@ static void force_qs_rnp(struct rcu_state *rsp,\n" - " \trnp = rcu_get_root(rsp);\n" - " \tif (rnp->qsmask == 0) {\n" - " \t\traw_spin_lock_irqsave(&rnp->lock, flags);\n" - "-\t\tsmp_mb__after_unlock_lock();\n" - " \t\trcu_initiate_boost(rnp, flags); /* releases rnp->lock. */\n" - " \t}\n" - " }\n" - "@@ -2500,7 +2485,6 @@ static void force_quiescent_state(struct rcu_state *rsp)\n" - " \n" - " \t/* Reached the root of the rcu_node tree, acquire lock. */\n" - " \traw_spin_lock_irqsave(&rnp_old->lock, flags);\n" - "-\tsmp_mb__after_unlock_lock();\n" - " \traw_spin_unlock(&rnp_old->fqslock);\n" - " \tif (ACCESS_ONCE(rsp->gp_flags) & RCU_GP_FLAG_FQS) {\n" - " \t\trsp->n_force_qs_lh++;\n" - "@@ -2625,7 +2609,6 @@ static void __call_rcu_core(struct rcu_state *rsp, struct rcu_data *rdp,\n" - " \t\t\tstruct rcu_node *rnp_root = rcu_get_root(rsp);\n" - " \n" - " \t\t\traw_spin_lock(&rnp_root->lock);\n" - "-\t\t\tsmp_mb__after_unlock_lock();\n" - " \t\t\tneedwake = rcu_start_gp(rsp);\n" - " \t\t\traw_spin_unlock(&rnp_root->lock);\n" - " \t\t\tif (needwake)\n" - "diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h\n" - "index 3ec85cb5d544..a89523605545 100644\n" - "--- a/kernel/rcu/tree_plugin.h\n" - "+++ b/kernel/rcu/tree_plugin.h\n" - "@@ -180,7 +180,6 @@ static void rcu_preempt_note_context_switch(void)\n" - " \t\trdp = this_cpu_ptr(rcu_preempt_state.rda);\n" - " \t\trnp = rdp->mynode;\n" - " \t\traw_spin_lock_irqsave(&rnp->lock, flags);\n" - "-\t\tsmp_mb__after_unlock_lock();\n" - " \t\tt->rcu_read_unlock_special.b.blocked = true;\n" - " \t\tt->rcu_blocked_node = rnp;\n" - " \n" - "@@ -287,7 +286,6 @@ static void rcu_report_unblock_qs_rnp(struct rcu_node *rnp, unsigned long flags)\n" - " \tmask = rnp->grpmask;\n" - " \traw_spin_unlock(&rnp->lock);\t/* irqs remain disabled. */\n" - " \traw_spin_lock(&rnp_p->lock);\t/* irqs already disabled. */\n" - "-\tsmp_mb__after_unlock_lock();\n" - " \trcu_report_qs_rnp(mask, &rcu_preempt_state, rnp_p, flags);\n" - " }\n" - " \n" - "@@ -362,7 +360,6 @@ void rcu_read_unlock_special(struct task_struct *t)\n" - " \t\tfor (;;) {\n" - " \t\t\trnp = t->rcu_blocked_node;\n" - " \t\t\traw_spin_lock(&rnp->lock); /* irqs already disabled. */\n" - "-\t\t\tsmp_mb__after_unlock_lock();\n" - " \t\t\tif (rnp == t->rcu_blocked_node)\n" - " \t\t\t\tbreak;\n" - " \t\t\traw_spin_unlock(&rnp->lock); /* irqs remain disabled. */\n" - "@@ -576,7 +573,6 @@ static int rcu_preempt_offline_tasks(struct rcu_state *rsp,\n" - " \twhile (!list_empty(lp)) {\n" - " \t\tt = list_entry(lp->next, typeof(*t), rcu_node_entry);\n" - " \t\traw_spin_lock(&rnp_root->lock); /* irqs already disabled */\n" - "-\t\tsmp_mb__after_unlock_lock();\n" - " \t\tlist_del(&t->rcu_node_entry);\n" - " \t\tt->rcu_blocked_node = rnp_root;\n" - " \t\tlist_add(&t->rcu_node_entry, lp_root);\n" - "@@ -601,7 +597,6 @@ static int rcu_preempt_offline_tasks(struct rcu_state *rsp,\n" - " \t * in this case.\n" - " \t */\n" - " \traw_spin_lock(&rnp_root->lock); /* irqs already disabled */\n" - "-\tsmp_mb__after_unlock_lock();\n" - " \tif (rnp_root->boost_tasks != NULL &&\n" - " \t rnp_root->boost_tasks != rnp_root->gp_tasks &&\n" - " \t rnp_root->boost_tasks != rnp_root->exp_tasks)\n" - "@@ -732,7 +727,6 @@ static void rcu_report_exp_rnp(struct rcu_state *rsp, struct rcu_node *rnp,\n" - " \tunsigned long mask;\n" - " \n" - " \traw_spin_lock_irqsave(&rnp->lock, flags);\n" - "-\tsmp_mb__after_unlock_lock();\n" - " \tfor (;;) {\n" - " \t\tif (!sync_rcu_preempt_exp_done(rnp)) {\n" - " \t\t\traw_spin_unlock_irqrestore(&rnp->lock, flags);\n" - "@@ -750,7 +744,6 @@ static void rcu_report_exp_rnp(struct rcu_state *rsp, struct rcu_node *rnp,\n" - " \t\traw_spin_unlock(&rnp->lock); /* irqs remain disabled */\n" - " \t\trnp = rnp->parent;\n" - " \t\traw_spin_lock(&rnp->lock); /* irqs already disabled */\n" - "-\t\tsmp_mb__after_unlock_lock();\n" - " \t\trnp->expmask &= ~mask;\n" - " \t}\n" - " }\n" - "@@ -770,7 +763,6 @@ sync_rcu_preempt_exp_init(struct rcu_state *rsp, struct rcu_node *rnp)\n" - " \tint must_wait = 0;\n" - " \n" - " \traw_spin_lock_irqsave(&rnp->lock, flags);\n" - "-\tsmp_mb__after_unlock_lock();\n" - " \tif (list_empty(&rnp->blkd_tasks)) {\n" - " \t\traw_spin_unlock_irqrestore(&rnp->lock, flags);\n" - " \t} else {\n" - "@@ -850,7 +842,6 @@ void synchronize_rcu_expedited(void)\n" - " \t/* Initialize ->expmask for all non-leaf rcu_node structures. */\n" - " \trcu_for_each_nonleaf_node_breadth_first(rsp, rnp) {\n" - " \t\traw_spin_lock_irqsave(&rnp->lock, flags);\n" - "-\t\tsmp_mb__after_unlock_lock();\n" - " \t\trnp->expmask = rnp->qsmaskinit;\n" - " \t\traw_spin_unlock_irqrestore(&rnp->lock, flags);\n" - " \t}\n" - "@@ -1131,7 +1122,6 @@ static int rcu_boost(struct rcu_node *rnp)\n" - " \t\treturn 0; /* Nothing left to boost. */\n" - " \n" - " \traw_spin_lock_irqsave(&rnp->lock, flags);\n" - "-\tsmp_mb__after_unlock_lock();\n" - " \n" - " \t/*\n" - " \t * Recheck under the lock: all tasks in need of boosting\n" - "@@ -1323,7 +1313,6 @@ static int rcu_spawn_one_boost_kthread(struct rcu_state *rsp,\n" - " \tif (IS_ERR(t))\n" - " \t\treturn PTR_ERR(t);\n" - " \traw_spin_lock_irqsave(&rnp->lock, flags);\n" - "-\tsmp_mb__after_unlock_lock();\n" - " \trnp->boost_kthread_task = t;\n" - " \traw_spin_unlock_irqrestore(&rnp->lock, flags);\n" - " \tsp.sched_priority = kthread_prio;\n" - "@@ -1717,7 +1706,6 @@ static void rcu_prepare_for_idle(void)\n" - " \t\t\tcontinue;\n" - " \t\trnp = rdp->mynode;\n" - " \t\traw_spin_lock(&rnp->lock); /* irqs already disabled. */\n" - "-\t\tsmp_mb__after_unlock_lock();\n" - " \t\tneedwake = rcu_accelerate_cbs(rsp, rnp, rdp);\n" - " \t\traw_spin_unlock(&rnp->lock); /* irqs remain disabled. */\n" - " \t\tif (needwake)\n" - "@@ -2226,7 +2214,6 @@ static void rcu_nocb_wait_gp(struct rcu_data *rdp)\n" - " \tstruct rcu_node *rnp = rdp->mynode;\n" - " \n" - " \traw_spin_lock_irqsave(&rnp->lock, flags);\n" - "-\tsmp_mb__after_unlock_lock();\n" - " \tneedwake = rcu_start_future_gp(rnp, rdp, &c);\n" - " \traw_spin_unlock_irqrestore(&rnp->lock, flags);\n" - " \tif (needwake)\n" - "-- \n" - 2.1.4 + --->8 -2d76c681285aa00e7c8ffcdc4d4b674da51a3566c86150fd36502bdab68718e4 +282dc46d4ec27da6ed7b8254ecd75734319e6260a1e94c3a7c5867ab29cf378c
diff --git a/a/1.txt b/N2/1.txt index 3e715b4..e033564 100644 --- a/a/1.txt +++ b/N2/1.txt @@ -34,7 +34,7 @@ Will --->8 -From 23d1db44f20a12924d2addeb73231f10d90e9f05 Mon Sep 17 00:00:00 2001 +>From 23d1db44f20a12924d2addeb73231f10d90e9f05 Mon Sep 17 00:00:00 2001 From: Will Deacon <will.deacon@arm.com> Date: Fri, 23 Jan 2015 13:55:34 +0000 Subject: [PATCH] memory-barriers: remove smp_mb__after_unlock_lock() diff --git a/a/content_digest b/N2/content_digest index d54a6c3..b7add63 100644 --- a/a/content_digest +++ b/N2/content_digest @@ -49,7 +49,7 @@ "\n" "--->8\n" "\n" - "From 23d1db44f20a12924d2addeb73231f10d90e9f05 Mon Sep 17 00:00:00 2001\n" + ">From 23d1db44f20a12924d2addeb73231f10d90e9f05 Mon Sep 17 00:00:00 2001\n" "From: Will Deacon <will.deacon@arm.com>\n" "Date: Fri, 23 Jan 2015 13:55:34 +0000\n" "Subject: [PATCH] memory-barriers: remove smp_mb__after_unlock_lock()\n" @@ -488,4 +488,4 @@ "-- \n" 2.1.4 -2d76c681285aa00e7c8ffcdc4d4b674da51a3566c86150fd36502bdab68718e4 +e0a9d4cc01324ad9cc541498228d84eddacceafaddaaf44f3c4eeb9c0651d8c2
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.