From 21291aea033308c1fddeaae655a9060cd1ec745b Mon Sep 17 00:00:00 2001 From: Mateusz Guzik Date: Wed, 28 Mar 2018 04:38:45 +0000 Subject: [PATCH] seq: provide a comment explaining what seq is for and note 2 caveats --- sys/sys/seq.h | 56 +++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 41 insertions(+), 15 deletions(-) diff --git a/sys/sys/seq.h b/sys/sys/seq.h index 5783fbe33d1..b5e07156cb8 100644 --- a/sys/sys/seq.h +++ b/sys/sys/seq.h @@ -41,26 +41,52 @@ typedef uint32_t seq_t; #ifdef _KERNEL /* - * Typical usage: + * seq allows readers and writers to work with a consistent snapshot. Modifying + * operations must be enclosed within a transaction delineated by + * seq_write_beg/seq_write_end. The trick works by having the writer increment + * the sequence number twice, at the beginning and end of the transaction. + * The reader detects that the sequence number has not changed between its start + * and end, and that the sequence number is even, to validate consistency. + * + * Some fencing (both hard fencing and compiler barriers) may be needed, + * depending on the cpu. Modern AMD cpus provide strong enough guarantees to not + * require any fencing by the reader or writer. + * + * Example usage: * * writers: - * lock_exclusive(&obj->lock); - * seq_write_begin(&obj->seq); - * ..... - * seq_write_end(&obj->seq); - * unlock_exclusive(&obj->unlock); + * lock_exclusive(&obj->lock); + * seq_write_begin(&obj->seq); + * obj->var1 = ...; + * obj->var2 = ...; + * seq_write_end(&obj->seq); + * unlock_exclusive(&obj->lock); * * readers: - * obj_t lobj; - * seq_t seq; + * int var1, var2; + * seq_t seq; * - * for (;;) { - * seq = seq_read(&gobj->seq); - * lobj = gobj; - * if (seq_consistent(&gobj->seq, seq)) - * break; - * } - * foo(lobj); + * for (;;) { + * seq = seq_read(&obj->seq); + * var1 = obj->var1; + * var2 = obj->var2; + * if (seq_consistent(&obj->seq, seq)) + * break; + * } + * ..... + * + * Writers may not block or sleep in any way. + * + * There are 2 minor caveats in this implementation: + * + * 1. There is no guarantee of progress. That is, a large number of writers can + * interfere with the execution of the readers and cause the code to live-lock + * in a loop trying to acquire a consistent snapshot. + * + * 2. If the reader loops long enough, the counter may overflow and eventually + * wrap back to its initial value, fooling the reader into accepting the + * snapshot. Given that this needs 4 billion transactional writes across a + * single contended reader, it is unlikely to ever happen. */ /* A hack to get MPASS macro */