aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-01-15 20:31:55 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2014-01-15 20:31:55 -0500
commit9b6c4ea95ff87464e012f70b119601de9e94deac (patch)
tree5dc1d4c9ea990bdf01a9f3c42965f9bc5bf0d47d
parent93a11c8f5cc642571071a1609a83998db1373077 (diff)
parent7a06c41cbec33c6dbe7eec575c61986122617408 (diff)
Merge branch 'core-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull locking fixes from Ingo Molnar: "Two fixes from lockdep coverage of seqlocks, which fix deadlocks on lockdep-enabled ARM systems" * 'core-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: sched_clock: Disable seqlock lockdep usage in sched_clock() seqlock: Use raw_ prefix instead of _no_lockdep
-rw-r--r--arch/x86/vdso/vclock_gettime.c8
-rw-r--r--include/linux/seqlock.h27
-rw-r--r--kernel/time/sched_clock.c6
3 files changed, 26 insertions, 15 deletions
diff --git a/arch/x86/vdso/vclock_gettime.c b/arch/x86/vdso/vclock_gettime.c
index 2ada505067cc..eb5d7a56f8d4 100644
--- a/arch/x86/vdso/vclock_gettime.c
+++ b/arch/x86/vdso/vclock_gettime.c
@@ -178,7 +178,7 @@ notrace static int __always_inline do_realtime(struct timespec *ts)
178 178
179 ts->tv_nsec = 0; 179 ts->tv_nsec = 0;
180 do { 180 do {
181 seq = read_seqcount_begin_no_lockdep(&gtod->seq); 181 seq = raw_read_seqcount_begin(&gtod->seq);
182 mode = gtod->clock.vclock_mode; 182 mode = gtod->clock.vclock_mode;
183 ts->tv_sec = gtod->wall_time_sec; 183 ts->tv_sec = gtod->wall_time_sec;
184 ns = gtod->wall_time_snsec; 184 ns = gtod->wall_time_snsec;
@@ -198,7 +198,7 @@ notrace static int do_monotonic(struct timespec *ts)
198 198
199 ts->tv_nsec = 0; 199 ts->tv_nsec = 0;
200 do { 200 do {
201 seq = read_seqcount_begin_no_lockdep(&gtod->seq); 201 seq = raw_read_seqcount_begin(&gtod->seq);
202 mode = gtod->clock.vclock_mode; 202 mode = gtod->clock.vclock_mode;
203 ts->tv_sec = gtod->monotonic_time_sec; 203 ts->tv_sec = gtod->monotonic_time_sec;
204 ns = gtod->monotonic_time_snsec; 204 ns = gtod->monotonic_time_snsec;
@@ -214,7 +214,7 @@ notrace static int do_realtime_coarse(struct timespec *ts)
214{ 214{
215 unsigned long seq; 215 unsigned long seq;
216 do { 216 do {
217 seq = read_seqcount_begin_no_lockdep(&gtod->seq); 217 seq = raw_read_seqcount_begin(&gtod->seq);
218 ts->tv_sec = gtod->wall_time_coarse.tv_sec; 218 ts->tv_sec = gtod->wall_time_coarse.tv_sec;
219 ts->tv_nsec = gtod->wall_time_coarse.tv_nsec; 219 ts->tv_nsec = gtod->wall_time_coarse.tv_nsec;
220 } while (unlikely(read_seqcount_retry(&gtod->seq, seq))); 220 } while (unlikely(read_seqcount_retry(&gtod->seq, seq)));
@@ -225,7 +225,7 @@ notrace static int do_monotonic_coarse(struct timespec *ts)
225{ 225{
226 unsigned long seq; 226 unsigned long seq;
227 do { 227 do {
228 seq = read_seqcount_begin_no_lockdep(&gtod->seq); 228 seq = raw_read_seqcount_begin(&gtod->seq);
229 ts->tv_sec = gtod->monotonic_time_coarse.tv_sec; 229 ts->tv_sec = gtod->monotonic_time_coarse.tv_sec;
230 ts->tv_nsec = gtod->monotonic_time_coarse.tv_nsec; 230 ts->tv_nsec = gtod->monotonic_time_coarse.tv_nsec;
231 } while (unlikely(read_seqcount_retry(&gtod->seq, seq))); 231 } while (unlikely(read_seqcount_retry(&gtod->seq, seq)));
diff --git a/include/linux/seqlock.h b/include/linux/seqlock.h
index cf87a24c0f92..535f158977b9 100644
--- a/include/linux/seqlock.h
+++ b/include/linux/seqlock.h
@@ -117,15 +117,15 @@ repeat:
117} 117}
118 118
119/** 119/**
120 * read_seqcount_begin_no_lockdep - start seq-read critical section w/o lockdep 120 * raw_read_seqcount_begin - start seq-read critical section w/o lockdep
121 * @s: pointer to seqcount_t 121 * @s: pointer to seqcount_t
122 * Returns: count to be passed to read_seqcount_retry 122 * Returns: count to be passed to read_seqcount_retry
123 * 123 *
124 * read_seqcount_begin_no_lockdep opens a read critical section of the given 124 * raw_read_seqcount_begin opens a read critical section of the given
125 * seqcount, but without any lockdep checking. Validity of the critical 125 * seqcount, but without any lockdep checking. Validity of the critical
126 * section is tested by checking read_seqcount_retry function. 126 * section is tested by checking read_seqcount_retry function.
127 */ 127 */
128static inline unsigned read_seqcount_begin_no_lockdep(const seqcount_t *s) 128static inline unsigned raw_read_seqcount_begin(const seqcount_t *s)
129{ 129{
130 unsigned ret = __read_seqcount_begin(s); 130 unsigned ret = __read_seqcount_begin(s);
131 smp_rmb(); 131 smp_rmb();
@@ -144,7 +144,7 @@ static inline unsigned read_seqcount_begin_no_lockdep(const seqcount_t *s)
144static inline unsigned read_seqcount_begin(const seqcount_t *s) 144static inline unsigned read_seqcount_begin(const seqcount_t *s)
145{ 145{
146 seqcount_lockdep_reader_access(s); 146 seqcount_lockdep_reader_access(s);
147 return read_seqcount_begin_no_lockdep(s); 147 return raw_read_seqcount_begin(s);
148} 148}
149 149
150/** 150/**
@@ -206,14 +206,26 @@ static inline int read_seqcount_retry(const seqcount_t *s, unsigned start)
206} 206}
207 207
208 208
209
210static inline void raw_write_seqcount_begin(seqcount_t *s)
211{
212 s->sequence++;
213 smp_wmb();
214}
215
216static inline void raw_write_seqcount_end(seqcount_t *s)
217{
218 smp_wmb();
219 s->sequence++;
220}
221
209/* 222/*
210 * Sequence counter only version assumes that callers are using their 223 * Sequence counter only version assumes that callers are using their
211 * own mutexing. 224 * own mutexing.
212 */ 225 */
213static inline void write_seqcount_begin_nested(seqcount_t *s, int subclass) 226static inline void write_seqcount_begin_nested(seqcount_t *s, int subclass)
214{ 227{
215 s->sequence++; 228 raw_write_seqcount_begin(s);
216 smp_wmb();
217 seqcount_acquire(&s->dep_map, subclass, 0, _RET_IP_); 229 seqcount_acquire(&s->dep_map, subclass, 0, _RET_IP_);
218} 230}
219 231
@@ -225,8 +237,7 @@ static inline void write_seqcount_begin(seqcount_t *s)
225static inline void write_seqcount_end(seqcount_t *s) 237static inline void write_seqcount_end(seqcount_t *s)
226{ 238{
227 seqcount_release(&s->dep_map, 1, _RET_IP_); 239 seqcount_release(&s->dep_map, 1, _RET_IP_);
228 smp_wmb(); 240 raw_write_seqcount_end(s);
229 s->sequence++;
230} 241}
231 242
232/** 243/**
diff --git a/kernel/time/sched_clock.c b/kernel/time/sched_clock.c
index 68b799375981..0abb36464281 100644
--- a/kernel/time/sched_clock.c
+++ b/kernel/time/sched_clock.c
@@ -74,7 +74,7 @@ unsigned long long notrace sched_clock(void)
74 return cd.epoch_ns; 74 return cd.epoch_ns;
75 75
76 do { 76 do {
77 seq = read_seqcount_begin(&cd.seq); 77 seq = raw_read_seqcount_begin(&cd.seq);
78 epoch_cyc = cd.epoch_cyc; 78 epoch_cyc = cd.epoch_cyc;
79 epoch_ns = cd.epoch_ns; 79 epoch_ns = cd.epoch_ns;
80 } while (read_seqcount_retry(&cd.seq, seq)); 80 } while (read_seqcount_retry(&cd.seq, seq));
@@ -99,10 +99,10 @@ static void notrace update_sched_clock(void)
99 cd.mult, cd.shift); 99 cd.mult, cd.shift);
100 100
101 raw_local_irq_save(flags); 101 raw_local_irq_save(flags);
102 write_seqcount_begin(&cd.seq); 102 raw_write_seqcount_begin(&cd.seq);
103 cd.epoch_ns = ns; 103 cd.epoch_ns = ns;
104 cd.epoch_cyc = cyc; 104 cd.epoch_cyc = cyc;
105 write_seqcount_end(&cd.seq); 105 raw_write_seqcount_end(&cd.seq);
106 raw_local_irq_restore(flags); 106 raw_local_irq_restore(flags);
107} 107}
108 108