As asked
Implement a lock-free single-producer single-consumer ring buffer in C for passing bytes between a UART ISR (producer) and a main-loop consumer on a single-core Cortex-M. It must not use mutexes or disable interrupts.
Sample answer outline
The candidate should use separate head and tail indices with volatile qualifiers and ensure that the producer only writes head after writing data, and the consumer only writes tail after reading data. The key is that on a single-core system with a single producer and consumer, no locking is needed as long as head and tail each have a single writer. They should use a power-of-two buffer size and modulo-via-mask, and be careful that size checks use copies of the volatile indices to avoid re-reading a changing value mid-check.
Reference implementation (c)
#define BUF_SIZE 256 // must be power of two
typedef struct {
uint8_t data[BUF_SIZE];
volatile uint32_t head; // written only by producer (ISR)
volatile uint32_t tail; // written only by consumer (main)
} RingBuf;
void rb_push(RingBuf *rb, uint8_t byte);
int rb_pop(RingBuf *rb, uint8_t *byte); // returns 1 if data available
uint32_t rb_used(const RingBuf *rb);Expect these follow-ups
- Why do you need volatile on head and tail here even though this is single-core?
- How does this approach break on a multi-core system, and what is the fix?