Ситуация такая: Есть динамичесая библиотека несколько функций которой работают с одной и той же облатью памяти. Необходимо синхронизировать чтение/запись в эту область разными функциями. Делаю следующие: в каждой функции проверяю некий флаг, если ноль, писать в буфер можно, если нет, ждем своей очереди. Выглядит это примерно так: mov eax, Flag_syn wait: cmp [eax], 0 ;{1} jnz wait ;{2} mov [eax], 1 ;{3} ............ mov [eax], 0 ret Работает невсегда. Очевидно несколько функций могут одновременно выполнить строки 1-3, либо одна функция не успевает установить флаг (строка 3), а вторая в это время проверяет его значение. Как все это делается правильно?, либо где есть доки. Будут ли отличия для Win9x и Win NT
Тебе нужно юзать примитивы синхронизации, которые предоставляет операционная система. Прежде чем выполнять какие-либо операции над твоей областью памяти, ты должен захватить объект синхронизации (возможно критическую секцию). Смотри функции EnterCriticalSection()/LeaveCriticalSection(). Если же область памяти небольшая - размером с ULONG, (например твой флаг), то можно для его модификации и проверки юзать InterlockedXXX() функции.
Я думаю тебе надо юзать именно то что предоставляет система! Этому мнению способоствует прочитанное в Э.Танненбауме "Современные операционные системы", после этого у тебя появится полное понимание что может произойти, если ты поступишь по другому. Ищи в ней про процессы, к примеру страницы около "спящего брадобея"
A_Must_Loll А че у тебя функции в разных потоках? Или ты либу по нескольку раз грузиш? Да функции вызываютя из разных потоков. Не нашел какой функцией проверить состояния флага не меняя его. Еще вопрос по InterlockedExchange - такая фраза The function prevents more than one thread from using the same variable simultaneously. Поглядел в kernel там ниже следующие: mov ecx, dword ptr [esp+4] mov eax, dword ptr [esp+8] xchg dword ptr [ecx], eax ret 8 Понятно, что функция работает но как она синхронизирует потоки (система Win98 2-e изд.).
Boola, у тебя видимо однопроцессорный HAL, поэтому никакой синхнонизации в InterlockedExchange() нет. В многопроцессорном варианте используется префикс LOCK.
Boola Не парься с флагом, синхронизацию так никто не делает. Используй критическую секцию. Код (Text): .data CRITICAL_SECTION CritSection ... .code ... push offset CritSection call EnterCriticalSection work_with_shared_memory: ... end_work_with_memory: push offset CritSection call LeaveCriticalSection Только не забудь, что перед первым использованием нужно вызвать InitializeCriticalSection. И, как сказал NoName, почитай Рихтера - многие вопросы отпадут.
Описание CRITICAL_SECTION, как и всего прочего смотрится здесь: http://msdn.microsoft.com/ Прототип также должен быть в windows.inc.
с крит. секцией красиво, но проще с interlocked фнукциями. это был мой opinion. А касательно win98, там ядро однопоточное если не ошибаюсь. Т.е. вызовы из разных приложений обрабатываются последовательно а не параллельно. Когда я последний раз его (98) дебажил. я заметил, что почти каждая функция юзерспейса (ведущая в ядро) начинается с вызова FlushInstructionsCache. Как я подозреваю - это сводится к сбросу конвейера\кеша, а так же где-то рядом находится некоторая крит. секция (глобальная на все процессы) , контроллирующая и гарантирующая что, в один момент времени только один процесс сможет находиться в ядре.
с крит. секцией красиво, но проще с interlocked фнукциями. Interlocked - это для одного ULONG'а, а у человека буфер с данными.