как реализованы мутексы на многоядерных платформах? на одноядерных вроде понятно (там гонок нет - выполняется только одна задча) на многоядерных я понимаю выполняется сназу несколько задач и если они одновременно проверят один мутекс то ... будет что-то не то вроде объясните пожалуйста любопытному как это устроено.
Мьютекс устроен вот так вот. Это переменная с функцией блокировки по чтению. Блокировка устроенна в виде цикла. Код (Text): procedure SpinMutexDoLock(const Mutex:PMutex); assembler; asm @spin_loop: MOV edx,1 lock XCHG DWord PTR [mutex],edx OR edx,edx JZ @lock_success wait JMP @spin_loop @lock_success: end; lock - означает, что процессор выставляет сигнал захвата шины. Пока выставлен сигнал захвата шины другие ядра не могут ни читать не писать с шины. Каждое ядро имеет свой приоритет захвата шины. Приоритеты реализованы при помощи 4 портовых арбитров. Поэтому в один момент шину может захватить только одно ядро. Ядро захватившее шину первым вычитывает значение переменной если там 0 то его пропускают выполнять код дальше. После того как первый снял сигнал с шины следующее по приоритету ядро получает возможность считать данные, но там уже лежит 1 которую записал предыдущий поток. И соответственно, отстающее ядро попадёт в spin-цикл.
Защититься от гонок можно по разному: разделить доступ по времени, либо сделать двойную проверку для выявления конфликтов, либо разделить общие данные путем клонирования. Просто циклическая блокировка самый простой и понятный примитив. Многоядерные это более общий случай. Так что, для одноядерных, код будет и подавно работать. Другое дело что код не оптимален и вместо цикла можно отдать исполнение следующему по плану потоку/процессу. Метод с Lock просто проще объяснить. А так xchg для x86 это атомарная операция, это значит что прёфикс Lock ей не нужен. При разбиении XCHG на макрокоманды, онные помечаются тегом атомарности. Который запрещает внеочередное исполнение команд. Вернее запрещает переставлять микрокоманды чтения от разных макрокоманд. Для одноядерных этого достаточно. Для многоядерных выполняется ещё проверка на кохерентность кэшей. И если конфликт не обнаружен, то код выполняется далее, а если конфликт обнаружен, то там уже и захват шины по средствам сигнала Lock.
вы за clflush prefetch или как она там, забыл вроде на w начинается, короче от слова "и райтбак мемори" это какраз делает NtFlushInstructionCache