Мне трудно понять, как работает shortp_incr_bp()
.Как он может атомарно увеличиваться без необходимости спин-блокировки или семафора?(Я не очень понимаю предоставленные комментарии.) Что может произойти, если barrier()
там не было?Как оптимизация вызывает неправильные значения?Каким образом эта оптимизация может пойти не так?
/*
* Input is managed through a simple circular buffer which, among other things,
* is allowed to overrun if the reader isn't fast enough. That makes life simple
* on the "read" interrupt side, where we don't want to block.
*/
static unsigned long shortp_in_buffer = 0;
static unsigned long volatile shortp_in_head;
static volatile unsigned long shortp_in_tail;
/*
* Atomically increment an index into "shortp_in_buffer"
*
* This function has been carefully written to wrap a pointer into the circular
* buffer without ever exposing an incorrect value. The "barrier" call is there
* to block compiler optimizations across the other two lines of the function.
* Without the barrier, the compiler might decide to optimize out the "new"
* variable and assign directly to "*index". That optimization could expose an
* incorrect value of the index for a brief period in the case where it wraps.
* By taking care to prevent in inconsistent value from ever being visible to
* other threads, we can manipulate the circular buffer pointers safely without
* locks.
*/
static inline void shortp_incr_bp(volatile unsigned long *index, int delta)
{
unsigned long new = *index + delta;
barrier(); /* Don't optimize these two together */
*index = (new >= (shortp_in_buffer + PAGE_SIZE)) ? shortp_in_buffer : new;
}