linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Re: [PATCH 4/4] timekeeping: Use printk_deferred when holding timekeeping seqlock
@ 2014-05-06 21:33 George Spelvin
  2014-05-12 16:21 ` [rough draft PATCH] avoid stalls on the " George Spelvin
  2014-05-12 17:49 ` [PATCH 4/4] timekeeping: Use printk_deferred when holding " John Stultz
  0 siblings, 2 replies; 14+ messages in thread
From: George Spelvin @ 2014-05-06 21:33 UTC (permalink / raw)
  To: john.stultz; +Cc: linux, linux-kernel

One misfeature in the timekeeping seqlock code I noticed is that
read_seqcount_begin returns "unsigned int", not "unsigned long".

Casting to a larger type is harmless, but inefficient.

> This is due to printk() triggering console sem wakeup, which can
> cause scheduling code to trigger hrtimers which may try to read
> the time.

An alternative solution, which avoids the need for this entire patch
series, is to make ktime_get completely nonblocking.

To do that, use a seqlock variant wherein you mintain an array of "struct
timekeeper" structures so that reading is always non-blocking if there
is no writer progress.  (I.e. livelock is remotely possible, but deadlock
is not.)

In the basic version, there are two.  (You can add more to further
reduce the chance of livelock.)  The currently stable one is indicated
by (timekeeper_seq->sequence & 2).  Writers update the appropriate
one ping-pong.  The low two bits indicate four phases:

0: Both timekeepers stable, [0] preferred for reading
1: Timekeeper[1] is being written; read timekeeper[0] only
2: Both timekeepers stable, [1] preferred for reading
3: Timekeeper[0] is being written; read timekeeper[1] only

The actual writer locking code is exactly the current write_seqcount_begin
and write_seqcount_end code.

A reader needs to retry only if end_seq > (start_seq & ~1u) + 2.
Accounting for wraparound, the read sequence is:

unsigned raw_read_FOO_begin(seqcount_t const *s)
{
	unsigned ret = ACCESS_ONCE(s->sequence);
	smp_rmb();
	return ret;
}

unsigned raw_read_FOO_retry(seqcount_t const *s, unsigned start)
{
	smp_rmb();
	start &= ~1u;
	return unlikely(s->seqence - start > 2);
}


A reader does:

        unsigned seq;

        do {
		struct timekeeper const *tk;
                seq = read_FOO_begin(&timekeeper_seq);
 		tk = timekeeper + (seq >> 1 & 1);
		frobnicate(tk);
        } while (read_FOO_retry(&timekeeper_seq, seq));

I haven't yet thought of a good name (to replace FOO) for this.
"seqnonblock"?


If you have more frequent updates, there's another variant that does
away with lsbit of the sequence number, so the writer only increments it
once, after update.  This reduces coherency traffic.  It does, however,
cause more readers to retry unless you go to an array of 4 structures.

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2014-05-13 16:18 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-05-06 21:33 [PATCH 4/4] timekeeping: Use printk_deferred when holding timekeeping seqlock George Spelvin
2014-05-12 16:21 ` [rough draft PATCH] avoid stalls on the " George Spelvin
2014-05-12 18:23   ` John Stultz
2014-05-12 17:49 ` [PATCH 4/4] timekeeping: Use printk_deferred when holding " John Stultz
2014-05-13  2:44   ` George Spelvin
2014-05-13  3:39     ` John Stultz
2014-05-13  5:13       ` George Spelvin
2014-05-13 12:07         ` Mathieu Desnoyers
2014-05-13 13:29           ` George Spelvin
2014-05-13 13:39             ` Mathieu Desnoyers
2014-05-13 16:18               ` George Spelvin
2014-05-13  2:45   ` [PATCH 1/2] timekeeping: Use unsigned int for seqlock sequence George Spelvin
2014-05-13 11:49     ` Mathieu Desnoyers
2014-05-13  2:48   ` [PATCH 2/2] timekeeping: Mark struct timekeeper * passed to notifiers as const George Spelvin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).