Thread safety¶
Ring buffers are effectively used in embedded systems with or without operating systems. Common problem most of implementations have is linked to multi-thread environment (when using OS) or reading/writing from/to interrupts. This is linked to common question What happens if I write to buffer while another thread is reading from it?
One of the main requirements (beside being lightweight) of LwRB was to allow read-while-write or write-while-read operations. This can be (and it is) achieved only when there is single write entry point and single read exit point.
This is most often used as pipe to write (for example) raw data to the buffer allowing another task to process the data from another thread.
Note
No race-condition is introduced when application uses LwRB with single write entry and single read exit point.
Thread safety gets broken when application does one of the following:
Uses multiple write entry points to the single LwRB instance
Uses multiple read exit points to the single LwRB instance
Uses multiple read/write exit/entry points to the same LwRB instance
Above use cases are examples when thread safety gets broken. Application must ensure exclusive access only to the part in dashed-red rectangle.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | /* Declare variables */
lwrb_t rb;
/* 2 mutexes, one for write operations,
one for read operations */
mutex_t m_w, m_r;
/* 4 threads below, 2 for write, 2 for read */
void
thread_write_1(void* arg) {
/* Use write mutex */
while (1) {
mutex_get(&m_w);
lwrb_write(&rb, ...);
mutex_give(&m_w);
}
}
void
thread_write_2(void* arg) {
/* Use write mutex */
while (1) {
mutex_get(&m_w);
lwrb_write(&rb, ...);
mutex_give(&m_w);
}
}
void
thread_read_1(void* arg) {
/* Use read mutex */
while (1) {
mutex_get(&m_r);
lwrb_read(&rb, ...);
mutex_give(&m_r);
}
}
void
thread_read_2(void* arg) {
/* Use read mutex */
while (1) {
mutex_get(&m_r);
lwrb_read(&rb, ...);
mutex_give(&m_r);
}
}
|
Read and write operations can be used simultaneously therefore it is perfectly valid if access is granted to read operation while write operation from one thread takes place.
Note
2
different mutexes are used for read and write due to the implementation,
allowing application to use buffer in read-while-write and write-while-read mode.
Mutexes are used to prevent write-while-write and read-while-read operations respectively
Tip
For multi-entry-point-single-exit-point use case, read mutex is not necessary. For single-entry-point-multi-exit-point use case, write mutex is not necessary.