mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-04-18 20:29:04 +08:00
ARM: 7643/1: sched: correct update_sched_clock()
If we want load epoch_cyc and epoch_ns atomically,
we should update epoch_cyc_copy first of all.
This notify reader that updating is in progress.
If we update epoch_cyc first like as current implementation,
there is subtle error case.
Look at the below example.
<Initial Condition>
cyc = 9
ns = 900
cyc_copy = 9
== CASE 1 ==
<CPU A = reader> <CPU B = updater>
write cyc = 10
read cyc = 10
read ns = 900
write ns = 1000
write cyc_copy = 10
read cyc_copy = 10
output = (10, 900)
== CASE 2 ==
<CPU A = reader> <CPU B = updater>
read cyc = 9
write cyc = 10
write ns = 1000
read ns = 1000
read cyc_copy = 9
write cyc_copy = 10
output = (9, 1000)
If atomic read is ensured, output should be (9, 900) or (10, 1000).
But, output in example case are not.
So, change updating sequence in order to correct this problem.
Cc: <stable@vger.kernel.org>
Signed-off-by: Joonsoo Kim <iamjoonsoo.kim@lge.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
This commit is contained in:
committed by
Russell King
parent
836dc9e3fb
commit
7c4e9ced42
@@ -93,11 +93,11 @@ static void notrace update_sched_clock(void)
|
||||
* detectable in cyc_to_fixed_sched_clock().
|
||||
*/
|
||||
raw_local_irq_save(flags);
|
||||
cd.epoch_cyc = cyc;
|
||||
cd.epoch_cyc_copy = cyc;
|
||||
smp_wmb();
|
||||
cd.epoch_ns = ns;
|
||||
smp_wmb();
|
||||
cd.epoch_cyc_copy = cyc;
|
||||
cd.epoch_cyc = cyc;
|
||||
raw_local_irq_restore(flags);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user