Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I'm not familiar with the Linux ring buffer specifically. It is presumably a multiple producer single or multiple consumer circular buffer, though.

Single producer single consumer circular buffers can be made pretty easily without locks. The producer writes to the buffer then atomically increments the head pointer. The consumer reads the buffer and then atomically increments the tail pointer.

Multiple producers get tricky without locking because they need to coordinate with each other enough to not write over the same part of the buffer. This can still be done via atomically incrementing a head pointer, though. The trick is that the increment has to happen before writing to the buffer rather than after. The buffer therefore needs to have a marker in it to indicate that it's ready to be read. A producer allocates the buffer with the atomic increment, writes it's data at it's leasure, then marks it ready to be read. The consumer looks at both the head pointer and the markers to tell how much data can be read.

Multiple consumers can be implemented by simply maintaining a tail pointer for each consumer. In order to be truly lock free, though, producers can't be blocked by slow consumers. Instead, producers simply write as fast as they want, and consumers do their best to keep up. A consumer can detect when it falls too far behind if you use counters rather than pointers or indexes; rather than wrapping around on increment, you wrap around on access to the circular buffer. That way, you can tell when you've fallen behind when your counter is more than the buffer size behind the head counter. You can either use 64 bit counters and never worry about roll over, or you can use a smaller data type for the counter and then size your buffer to be a power of two so that integer rollover doesn't cause a discontinuity.



Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: