Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9b6c4ea9 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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
parents 93a11c8f 7a06c41c
Loading
Loading
Loading
Loading
+4 −4
Original line number Original line Diff line number Diff line
@@ -178,7 +178,7 @@ notrace static int __always_inline do_realtime(struct timespec *ts)


	ts->tv_nsec = 0;
	ts->tv_nsec = 0;
	do {
	do {
		seq = read_seqcount_begin_no_lockdep(&gtod->seq);
		seq = raw_read_seqcount_begin(&gtod->seq);
		mode = gtod->clock.vclock_mode;
		mode = gtod->clock.vclock_mode;
		ts->tv_sec = gtod->wall_time_sec;
		ts->tv_sec = gtod->wall_time_sec;
		ns = gtod->wall_time_snsec;
		ns = gtod->wall_time_snsec;
@@ -198,7 +198,7 @@ notrace static int do_monotonic(struct timespec *ts)


	ts->tv_nsec = 0;
	ts->tv_nsec = 0;
	do {
	do {
		seq = read_seqcount_begin_no_lockdep(&gtod->seq);
		seq = raw_read_seqcount_begin(&gtod->seq);
		mode = gtod->clock.vclock_mode;
		mode = gtod->clock.vclock_mode;
		ts->tv_sec = gtod->monotonic_time_sec;
		ts->tv_sec = gtod->monotonic_time_sec;
		ns = gtod->monotonic_time_snsec;
		ns = gtod->monotonic_time_snsec;
@@ -214,7 +214,7 @@ notrace static int do_realtime_coarse(struct timespec *ts)
{
{
	unsigned long seq;
	unsigned long seq;
	do {
	do {
		seq = read_seqcount_begin_no_lockdep(&gtod->seq);
		seq = raw_read_seqcount_begin(&gtod->seq);
		ts->tv_sec = gtod->wall_time_coarse.tv_sec;
		ts->tv_sec = gtod->wall_time_coarse.tv_sec;
		ts->tv_nsec = gtod->wall_time_coarse.tv_nsec;
		ts->tv_nsec = gtod->wall_time_coarse.tv_nsec;
	} while (unlikely(read_seqcount_retry(&gtod->seq, seq)));
	} while (unlikely(read_seqcount_retry(&gtod->seq, seq)));
@@ -225,7 +225,7 @@ notrace static int do_monotonic_coarse(struct timespec *ts)
{
{
	unsigned long seq;
	unsigned long seq;
	do {
	do {
		seq = read_seqcount_begin_no_lockdep(&gtod->seq);
		seq = raw_read_seqcount_begin(&gtod->seq);
		ts->tv_sec = gtod->monotonic_time_coarse.tv_sec;
		ts->tv_sec = gtod->monotonic_time_coarse.tv_sec;
		ts->tv_nsec = gtod->monotonic_time_coarse.tv_nsec;
		ts->tv_nsec = gtod->monotonic_time_coarse.tv_nsec;
	} while (unlikely(read_seqcount_retry(&gtod->seq, seq)));
	} while (unlikely(read_seqcount_retry(&gtod->seq, seq)));
+19 −8
Original line number Original line Diff line number Diff line
@@ -117,15 +117,15 @@ static inline unsigned __read_seqcount_begin(const seqcount_t *s)
}
}


/**
/**
 * read_seqcount_begin_no_lockdep - start seq-read critical section w/o lockdep
 * raw_read_seqcount_begin - start seq-read critical section w/o lockdep
 * @s: pointer to seqcount_t
 * @s: pointer to seqcount_t
 * Returns: count to be passed to read_seqcount_retry
 * Returns: count to be passed to read_seqcount_retry
 *
 *
 * read_seqcount_begin_no_lockdep opens a read critical section of the given
 * raw_read_seqcount_begin opens a read critical section of the given
 * seqcount, but without any lockdep checking. Validity of the critical
 * seqcount, but without any lockdep checking. Validity of the critical
 * section is tested by checking read_seqcount_retry function.
 * section is tested by checking read_seqcount_retry function.
 */
 */
static inline unsigned read_seqcount_begin_no_lockdep(const seqcount_t *s)
static inline unsigned raw_read_seqcount_begin(const seqcount_t *s)
{
{
	unsigned ret = __read_seqcount_begin(s);
	unsigned ret = __read_seqcount_begin(s);
	smp_rmb();
	smp_rmb();
@@ -144,7 +144,7 @@ static inline unsigned read_seqcount_begin_no_lockdep(const seqcount_t *s)
static inline unsigned read_seqcount_begin(const seqcount_t *s)
static inline unsigned read_seqcount_begin(const seqcount_t *s)
{
{
	seqcount_lockdep_reader_access(s);
	seqcount_lockdep_reader_access(s);
	return read_seqcount_begin_no_lockdep(s);
	return raw_read_seqcount_begin(s);
}
}


/**
/**
@@ -206,14 +206,26 @@ static inline int read_seqcount_retry(const seqcount_t *s, unsigned start)
}
}





static inline void raw_write_seqcount_begin(seqcount_t *s)
{
	s->sequence++;
	smp_wmb();
}

static inline void raw_write_seqcount_end(seqcount_t *s)
{
	smp_wmb();
	s->sequence++;
}

/*
/*
 * Sequence counter only version assumes that callers are using their
 * Sequence counter only version assumes that callers are using their
 * own mutexing.
 * own mutexing.
 */
 */
static inline void write_seqcount_begin_nested(seqcount_t *s, int subclass)
static inline void write_seqcount_begin_nested(seqcount_t *s, int subclass)
{
{
	s->sequence++;
	raw_write_seqcount_begin(s);
	smp_wmb();
	seqcount_acquire(&s->dep_map, subclass, 0, _RET_IP_);
	seqcount_acquire(&s->dep_map, subclass, 0, _RET_IP_);
}
}


@@ -225,8 +237,7 @@ static inline void write_seqcount_begin(seqcount_t *s)
static inline void write_seqcount_end(seqcount_t *s)
static inline void write_seqcount_end(seqcount_t *s)
{
{
	seqcount_release(&s->dep_map, 1, _RET_IP_);
	seqcount_release(&s->dep_map, 1, _RET_IP_);
	smp_wmb();
	raw_write_seqcount_end(s);
	s->sequence++;
}
}


/**
/**
+3 −3
Original line number Original line Diff line number Diff line
@@ -74,7 +74,7 @@ unsigned long long notrace sched_clock(void)
		return cd.epoch_ns;
		return cd.epoch_ns;


	do {
	do {
		seq = read_seqcount_begin(&cd.seq);
		seq = raw_read_seqcount_begin(&cd.seq);
		epoch_cyc = cd.epoch_cyc;
		epoch_cyc = cd.epoch_cyc;
		epoch_ns = cd.epoch_ns;
		epoch_ns = cd.epoch_ns;
	} while (read_seqcount_retry(&cd.seq, seq));
	} while (read_seqcount_retry(&cd.seq, seq));
@@ -99,10 +99,10 @@ static void notrace update_sched_clock(void)
			  cd.mult, cd.shift);
			  cd.mult, cd.shift);


	raw_local_irq_save(flags);
	raw_local_irq_save(flags);
	write_seqcount_begin(&cd.seq);
	raw_write_seqcount_begin(&cd.seq);
	cd.epoch_ns = ns;
	cd.epoch_ns = ns;
	cd.epoch_cyc = cyc;
	cd.epoch_cyc = cyc;
	write_seqcount_end(&cd.seq);
	raw_write_seqcount_end(&cd.seq);
	raw_local_irq_restore(flags);
	raw_local_irq_restore(flags);
}
}