мутекс

Тема в разделе "WASM.OS.DEVEL", создана пользователем VaVa, 21 сен 2018.

  1. VaVa

    VaVa Member

    Публикаций:
    0
    Регистрация:
    21 авг 2018
    Сообщения:
    34
    как реализованы мутексы на многоядерных платформах?
    на одноядерных вроде понятно (там гонок нет - выполняется только одна задча)
    на многоядерных я понимаю выполняется сназу несколько задач и если они одновременно проверят один мутекс то ... будет что-то не то вроде
    объясните пожалуйста любопытному как это устроено.
     
  2. Pavia

    Pavia Well-Known Member

    Публикаций:
    0
    Регистрация:
    17 июн 2003
    Сообщения:
    2.409
    Адрес:
    Fryazino
    Мьютекс устроен вот так вот. Это переменная с функцией блокировки по чтению. Блокировка устроенна в виде цикла.

    Код (Text):
    1.  
    2. procedure SpinMutexDoLock(const Mutex:PMutex);
    3. assembler;
    4. asm
    5. @spin_loop:
    6.   MOV   edx,1
    7.   lock  XCHG  DWord PTR [mutex],edx
    8.   OR    edx,edx
    9.   JZ    @lock_success
    10.   wait
    11.   JMP   @spin_loop
    12. @lock_success:
    13. end;
    14.  
    lock - означает, что процессор выставляет сигнал захвата шины. Пока выставлен сигнал захвата шины другие ядра не могут ни читать не писать с шины.
    Каждое ядро имеет свой приоритет захвата шины. Приоритеты реализованы при помощи 4 портовых арбитров. Поэтому в один момент шину может захватить только одно ядро. Ядро захватившее шину первым вычитывает значение переменной если там 0 то его пропускают выполнять код дальше. После того как первый снял сигнал с шины следующее по приоритету ядро получает возможность считать данные, но там уже лежит 1 которую записал предыдущий поток. И соответственно, отстающее ядро попадёт в spin-цикл.
     
    VaVa и TermoSINteZ нравится это.
  3. VaVa

    VaVa Member

    Публикаций:
    0
    Регистрация:
    21 авг 2018
    Сообщения:
    34
    спасибо!
    а для одноядерных тоже применяют метод с lock или по другому?
     
  4. Pavia

    Pavia Well-Known Member

    Публикаций:
    0
    Регистрация:
    17 июн 2003
    Сообщения:
    2.409
    Адрес:
    Fryazino
    Защититься от гонок можно по разному: разделить доступ по времени, либо сделать двойную проверку для выявления конфликтов, либо разделить общие данные путем клонирования. Просто циклическая блокировка самый простой и понятный примитив.
    Многоядерные это более общий случай. Так что, для одноядерных, код будет и подавно работать. Другое дело что код не оптимален и вместо цикла можно отдать исполнение следующему по плану потоку/процессу.


    Метод с Lock просто проще объяснить.
    А так xchg для x86 это атомарная операция, это значит что прёфикс Lock ей не нужен. При разбиении XCHG на макрокоманды, онные помечаются тегом атомарности. Который запрещает внеочередное исполнение команд. Вернее запрещает переставлять микрокоманды чтения от разных макрокоманд. Для одноядерных этого достаточно. Для многоядерных выполняется ещё проверка на кохерентность кэшей. И если конфликт не обнаружен, то код выполняется далее, а если конфликт обнаружен, то там уже и захват шины по средствам сигнала Lock.
     
  5. sn0w

    sn0w Active Member

    Публикаций:
    0
    Регистрация:
    27 фев 2010
    Сообщения:
    956
    вы за clflush prefetch или как она там, забыл вроде на w начинается, короче от слова "и райтбак мемори" это какраз делает NtFlushInstructionCache