seq: provide a comment explaining what seq is for and note 2 caveats

This commit is contained in:
Mateusz Guzik 2018-03-28 04:38:45 +00:00
parent 51f4f2ed3d
commit 21291aea03
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=331660

View File

@ -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 */