OSDev
http://osdev.ru/

Мьютексы и семофоры
http://osdev.ru/viewtopic.php?f=7&t=1124
Страница 1 из 1

Автор:  pavia [ 26 окт 2015, 08:33 ]
Заголовок сообщения:  Мьютексы и семофоры

Кто нибудь их уже делал мьютексы и семофоры для IA32 и x86-64? Поделитесь кодом. Ясно что там всё просто и понятно, но посмотреть как другие делают охота.

Автор:  pavia [ 31 окт 2015, 17:15 ]
Заголовок сообщения:  Re: Мьютексы и семофоры

Все указатели выравнены на границе 4 байт.
Нужен тут прёфикс Lock?
Я думаю что нет. Операция записи атомарная. Но на ксенонах возможно переупорядычивание записи.

Код:
procedure MutexInit(const Mutex:PMutex;const Value:TMutex):Boolean;
assembler;
asm
  MOV eax, Value
  MOV DWord PTR [Mutex], eax  // Нужен тут прёфикс Lock?
end;

procedure MutexTryDoLock(const Mutex:PMutex):Boolean;
assembler;
asm
  MOV   eax, 1
  lock  XCHG [mutex],eax
  OR   eax, eax
  SETZ  eax
end;

procedure MutexDoLock(const Mutex:PMutex);
assembler;
asm
  MOV  eax,1
  MOV  DWord PTR [mutex],eax // Нужен тут прёфикс Lock?
end;

procedure MutexDoUnLock(const Mutex:PMutex);
assembler;
asm
  MOV  eax,0
  MOV  DWord PTR [mutex],eax // Нужен тут прёфикс Lock?
end;

procedure SpinMutexDoLock(const Mutex:PMutex);
assembler;
asm
spin_loop:
  MOV   eax,1
  lock  XCHG  DWord PTR [mutex],eax
  OR   eax,eax
  JZ   @lock_success
  ;; wait
  JMP   @spin_loop
lock_success:
end;


Поправил имена функциям, теперь где надо стоят глаголы.

Автор:  pavia [ 31 окт 2015, 23:46 ]
Заголовок сообщения:  Re: Мьютексы и семофоры

Следующий вопрос. Делаю код для реализации критической секции. Хочу сделать через патч.
Это нужно для того что-бы отказаться от глобальных переменных с мьютексом. В место этого будет динамически список. В нём будут храниться мьютексы каждой критической секции.

Идея такова при первом вызове CriticalSectionBegin создаётся структура описывающая критическую секцию. У каждой секции она будет своя. Затем CriticalSectionBegin заменяется на CriticalSectionBeginImp с указателем на эту структуру. В этой структуре храниться мьютекс. Т.е получается что у кадой критической секции свой мьютекс. И при следующих вызовах код будет сразу попадать на вызов крутящегося мьютекса.

Но возник вопрос как атомарно произвести патч? Ведь код вызова не выровнен. А значит он может попасть на границу кэш-линейки. Достаточно в этом случае прёфикса lock?
Или надо заморозить потоки?

Автор:  SII [ 01 ноя 2015, 07:21 ]
Заголовок сообщения:  Re: Мьютексы и семофоры

lock не нужен при гарантированно атомарной операции (только чтение или только запись правильно выровненных данных). Кроме того, lock не нужен перед xchg (у Вас он там стоит): согласно описанию, xchg является единственной инструкцией (ещё со времён 8086), которая сама выставляет соответствующий сигнал независимо от наличия префикса. Будет ли lock нормально работать при невыровненном доступе -- без понятия, смотрите документацию.

С критическими секциями, как по мне, идея неудачная. Существенно усложняется реализация и т.п., а каков выигрыш? Кстати, о реализации. Соответствующий код уже может быть выбран процессором и находиться на декодировании, и его модификация в этой ситуации не приведёт к отмене уже выполненной выборки. Соответственно, существует ненулевая вероятность, что старый код будет выполнен формально уже после того, как он заменён на новый -- следовательно, надо останавливать потоки и т.п.

Автор:  pavia [ 01 ноя 2015, 11:30 ]
Заголовок сообщения:  Re: Мьютексы и семофоры

Цитата:
согласно описанию, xchg является единственной инструкцией (ещё со времён 8086), которая сама выставляет соответствующий сигнал независимо от наличия префикса.

Я знаю только со времён 486 в 286 и 386 такого не было.
Я много читал как это работает и понял одно. Толи у интела ошибки по тексту толи они сами не понимают где работает, а где нет.

Цитата:
С критическими секциями, как по мне, идея неудачная. Существенно усложняется реализация и т.п., а каков выигрыш?
Сахар чисто синтаксический. Понятно что достаточно сделать глобальную переменную. Но я не ищу легких путей.
Всегда найдётся пользователь который справку не прочтёт и будет делать в локальной памяти. Так что это ещё защита "от дурака".

В Си в OpenMP это всё решается текстовым препроцессором. Но это оставлю на будущее.

Цитата:
Кстати, о реализации. Соответствующий код уже может быть выбран процессором и находиться на декодировании, и его модификация в этой ситуации не приведёт к отмене уже выполненной выборки. Соответственно, существует ненулевая вероятность, что старый код будет выполнен формально уже после того, как он заменён на новый -- следовательно, надо останавливать потоки и т.п.

Да вы правы. Поэтому добавлен следующий код.

Код:
 SpinMutexDoLock(CriticlSectionsList.Lock);
  // Не успели пропатчить, а ядра уже скопились в выше стоящем мьюткса
  // Проверяем зарегистрирована ли критическая секция или ещё нет.
  if SeachAddr(CriticlSection, Addr) then
     begin
       Exit; // Переход в предыдущую функцию где  идёт обработка критической секции
     end else
   // Регистрируем критическую секцию и патчим код.

Автор:  pavia [ 01 ноя 2015, 11:39 ]
Заголовок сообщения:  Re: Мьютексы и семофоры

Цитата:
lock не нужен при гарантированно атомарной операции (только чтение или только запись правильно выровненных данных).

Я решил что есть ещё 3 случай. Есть такая вещь как смена порядка операций.
Всё бы было хорошо если не одна строчка на ксенонах запись может менять порядок! Как и когда в манах ничего не сказано. В остальных процессорах такой проблемы нет. Можно было сделать без lock, но я решил подстраховаться и поставить lock.

Автор:  Yoda [ 02 ноя 2015, 13:32 ]
Заголовок сообщения:  Re: Мьютексы и семофоры

Невыровненные адреса действительно могут привести к неатомарной операции даже в случае только чтения или только записи. Так, документация Intel утверждает, что в зависимости от конкретной реализации процессора, инструкции, данные которых пересекают границы параграфа, могут вызвать неатомарную процедуру чтения двух блоков памяти (см. описание LDDQU).
Префикс LOCK может предшествовать только следующим инструкциям: ADD, ADC, AND, BTC, BTR, BTS, CMPXCHG, CMPXCH8B, DEC, INC, NEG, NOT, OR, SBB, SUB, XOR, XADD и XCHG и только в случае, если один из операндов находится в памяти. В остальных случаях будет вызвано исключение.
Инструкция XCHG всегда выставляет сигнал LOCK на шину, независимо от того, есть у неё префикс или нет, и так работает на всех процессорах линейки x86, начиная с самых первых - 8086. Казалось бы, другие операции, для которых атомарность критически важна для сохранения корректности результата, тоже должны были бы быть атомарными, но в данном случае это дань традиции и академической науке, что именно эта (и только эта) операция сделана внутренне атомарной. Большинство статей посвящено реализации атомарности, основываясь именно на операции обмена и сравнения. Также большое количество других процессоров (включая некоторые RISC-процессоры) атомарно реализует именно эту инструкцию.
Касательно эффективности. Если вы не планируете запускать ваш код на процессорах 80386 или меньше, то в ряде случаев лучше пользоваться инструкцией CMPXCHG (появилась с 486), которая одновременно выполняет сравнение и условный обмен данными. Для реализации блокировки также очень удобны битовые функции - BTC, BTR и BTS, которые также осуществляют два действия за раз и доступны начиная с 386 процессора (т.е. в данном случае даже сомнений в доступности инструкций быть не должно, если вы пишете ОС для защищённого режима).
Никакая смена порядка операций не может поменять семантику. Если процессор выполнил блокирующую операцию раньше других, это означает, что ни одна отложенная инструкция не зависит по данным от этой инструкции и не может вызвать исключение (а также, при возникновении внешнего прерывания сначала будут завершены отложенные инструкции).

Страница 1 из 1 Часовой пояс: UTC + 3 часа
Powered by phpBB® Forum Software © phpBB Group
http://www.phpbb.com/