2016-04-20 2 views
3

Так что я читаю atomic.h из исходного кода Linux от here (нашел его на Google Я не уверен, если это нормально.), И я просто не могу обернуть свой ум вокруг этого:Как атомный_dec_if_положительный атомный?

как это атомное?

static inline int atomic_dec_if_positive(atomic_t *v) 
{ 
    int c, old, dec; 
    c = atomic_read(v); 
    for (;;) { 
    dec = c - 1; 
    if (unlikely(dec < 0)) 
     break; 
    old = atomic_cmpxchg((v), c, dec); 
    if (likely(old == c)) 
     break; 
    c = old; 
    } 
    return dec; 
} 
+0

Можете ли вы объяснить сценарий, в котором вы думаете, что он ведет себя неатомно? –

ответ

3

Он использует функцию atomic_read() и atomic_cmpxchg(), которые, безусловно, где-то будут реализованы на языке ассемблера с использованием атомарности особенности набора команд микропроцессора.

Это первый считывает значение и делает, что он является положительным, сохраняет значение чтения в c, уменьшенное значение в dec и вызовы atomic_cmpxchg() которые будут атомарно сделать следующее: «написать dec в *v только если значение в *v является равным c, и вернуть старое значение в *v ". Таким образом, вы убедитесь, что значение в *v не было изменено между двумя атомарными вызовами. Если это не удается и возвращаемое значение отличается от ожидаемого содержимого *v, оно повторяет весь процесс.

+0

Я не знаю, как я этого не видел раньше :). Самая важная часть: «писать' dec' в '* v', только если значение в' * v' равно 'c' ', а' c' - значение, которое было красным в начале функции. – carobnodrvo

2

Следующая строка

c = atomic_read(v); 

означает, в данный момент мы знаем, что значение переменной atomic_v == с. We декремент c, чтобы дать нам наше требуемое значение.

dec = c - 1; 

Очевидно, что если число не является положительным и 0 не является положительным, мы не можем декремент это.

if (unlikely(dec < 0)) 
     break; 

Теперь мы пытаемся изменить наш известный старый результат с ожидаемым результатом

old = atomic_cmpxchg((v), c, dec); 

Это определяется как

int atomic_cmpxchg(atomic_t *v, int old, int new); 

Если мы запишем его следующим образом, и предположим, что в целом функция атомарна. У нас есть

int atomic_cmpxchg(atomic_t *v, int old, int new) { 
    &v->counter = &v->counter == old ? new : old; 
    return old; 
} 

Примечания, я лечение v как целое число, на x86 это структура. На этом этапе мы знаем, что в точке выполнения атомной операции мы получаем старое значение . Наше ожидаемое старое значение - c, так что если это так, то у нас успешно уменьшено значение, верните результат.

if (likely(old == c)) 
     break; 

Если нам не нужно сбросить наш expectataion т.е. нашей начальной точки, мы декремента новое значение c не старый один у нас был, когда в последний раз вошел в for(;;) петлю

c = old; 

Важной частью вот что это в цикле, этот цикл будет продолжаться до тех пор, пока ему не удастся уменьшить значение или значение не положительно.

Смежные вопросы