Skip to content

Commit

Permalink
[PATCH] memory ordering in __kfifo primitives
Browse files Browse the repository at this point in the history
Both __kfifo_put() and __kfifo_get() have header comments stating that if
there is but one concurrent reader and one concurrent writer, locking is not
necessary.  This is almost the case, but a couple of memory barriers are
needed.  Another option would be to change the header comments to remove the
bit about locking not being needed, and to change the those callers who
currently don't use locking to add the required locking.  The attachment
analyzes this approach, but the patch below seems simpler.

Signed-off-by: Paul E. McKenney <paulmck@us.ibm.com>
Cc: Stelian Pop <stelian@popies.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
  • Loading branch information
Paul E. McKenney authored and Linus Torvalds committed Sep 29, 2006
1 parent 99de055 commit a45bce4
Showing 1 changed file with 28 additions and 0 deletions.
28 changes: 28 additions & 0 deletions kernel/kfifo.c
Original file line number Diff line number Diff line change
Expand Up @@ -122,13 +122,27 @@ unsigned int __kfifo_put(struct kfifo *fifo,

len = min(len, fifo->size - fifo->in + fifo->out);

/*
* Ensure that we sample the fifo->out index -before- we
* start putting bytes into the kfifo.
*/

smp_mb();

/* first put the data starting from fifo->in to buffer end */
l = min(len, fifo->size - (fifo->in & (fifo->size - 1)));
memcpy(fifo->buffer + (fifo->in & (fifo->size - 1)), buffer, l);

/* then put the rest (if any) at the beginning of the buffer */
memcpy(fifo->buffer, buffer + l, len - l);

/*
* Ensure that we add the bytes to the kfifo -before-
* we update the fifo->in index.
*/

smp_wmb();

fifo->in += len;

return len;
Expand All @@ -154,13 +168,27 @@ unsigned int __kfifo_get(struct kfifo *fifo,

len = min(len, fifo->in - fifo->out);

/*
* Ensure that we sample the fifo->in index -before- we
* start removing bytes from the kfifo.
*/

smp_rmb();

/* first get the data from fifo->out until the end of the buffer */
l = min(len, fifo->size - (fifo->out & (fifo->size - 1)));
memcpy(buffer, fifo->buffer + (fifo->out & (fifo->size - 1)), l);

/* then get the rest (if any) from the beginning of the buffer */
memcpy(buffer + l, fifo->buffer, len - l);

/*
* Ensure that we remove the bytes from the kfifo -before-
* we update the fifo->out index.
*/

smp_mb();

fifo->out += len;

return len;
Expand Down

0 comments on commit a45bce4

Please sign in to comment.