Здравствуйте, barney, Вы писали:
N>>1. Что за компилятор?
B>Apple LLVM version 9.1.0
Я удивляюсь стилю ассемблера, GCC и Clang используют стиль GCC. Но тут явно что-то другое, ближе к традициям MS. OK, ясно.
N>>CF=0 как раз если было 0, то есть спинлок захвачен. Нафига в этом случае возвращаться на loop? Ты делаешь всё наоборот — если захватил, идёшь на круг
N>>Тут лучше ложится jc outer (и вообще, outer и loop совместить)
B>ммм... моя логика такая:
B>если мьютекс еще не захвачен ( == 0) то вызов 'bts [rbx], eax' в керри положит старое значени 0, и атомарно в память 1
B>(но, до этого момента, другой поток УЖЕ мог прочитать 0 в таком же outer цикле, и перейти на inner этап)
B>теперь проц дает гарантию что lock bts атомарно положит там 1 хотя бы в одном из потоков!
B>т.е у кого то carry будет == 0 а у кого == 1
B>вот у того, кого 0 — тот захватил первым
Именно. И если CF=0, то надо не идти на цикл, а считать действие lock завершённым. Поэтому jc должно идти на цикл, а противоположность (прямой ход исполнения или jnc) — выходить из цикла.
Но дальше второе — чтобы не задрочить кэш, шины и всю систему постоянными попытками записи, если bts или аналог сорвались, снова идут на циклическое чтение, в ожидании, пока не появится 0.