Атомарность операций
Добавлено: 02 окт 2009, 11:22
Здравствуйте!
Пишу многопоточную программу под х86 процессор (защищенный режим) на С++.
Есть глобальная переменная (назовём её Count) для взаимодействия двух потоков. (в обоих потоках присутствуют операции чтение, запись и чтение-модификация-запись (Count=Count+A)).
По логике программы операции чтение и запись не могут привести к нарушению работы, а вот чтение-модификация-запись - может.
Возникла идея реализовать операцию Count=Count+A в виде ассемблерной вставки, где операция выполняется инструкцией Add:
__asm{
push eax
mov eax,A
add Count,eax
pop eax
};
, т.к. код, генерируемый компилятором по умолчанию сводился к:
mov eax,Count
mov ebx,A
add eax,ebx ; опасная строка 1
mov Count,eax ; опасная строка 2
Все эти заморочки вызваны тем, что в любом месте моя программа может быть прервана планировщиком ОС. Т.е. если планировщик вклиниться между опасными командами 1 и 2, запустит на выполнение второй поток, который выполнит опасные команды 1 и 2, и опять запустит на выполнение первый поток, который выполнит опасную команду 2, возникнет ситуация "пепец".
Теперь внимание вопрос: если операция Count=Count+A в ассемблерном коде представлена одной процессорной командой Add, гарантирует ли это отсутствие ситуации "пепец" ?
Иными словами, можно ли ассемблерную инструкцию считать атомарной (выполняемой как единое целое) ?
Иными словами: планировщик современных ОС вклинивается между инструкциями x86 или между инструкциями внутреннего RISC-ядра процессора?
На всякий случай добавлю: пользоваться объектами синхронизации ОС (критические секции, Interlocked...) не вышло - очень замедляет работу моего RealTime приложения. Приложение запущено в пользовательском режиме (кольцо 4), cli и sti не советовать.
На всякий случай доп. информация (скорее всего не существенно):
Среда: Visual Studio 2005
ОС(целевая): Windows CE 6.0 R2
Процессор(целевой): AMD Geode LX800 (x86(набор инструкций P5), FPU, MMX, 3DNow!)
Пишу многопоточную программу под х86 процессор (защищенный режим) на С++.
Есть глобальная переменная (назовём её Count) для взаимодействия двух потоков. (в обоих потоках присутствуют операции чтение, запись и чтение-модификация-запись (Count=Count+A)).
По логике программы операции чтение и запись не могут привести к нарушению работы, а вот чтение-модификация-запись - может.
Возникла идея реализовать операцию Count=Count+A в виде ассемблерной вставки, где операция выполняется инструкцией Add:
__asm{
push eax
mov eax,A
add Count,eax
pop eax
};
, т.к. код, генерируемый компилятором по умолчанию сводился к:
mov eax,Count
mov ebx,A
add eax,ebx ; опасная строка 1
mov Count,eax ; опасная строка 2
Все эти заморочки вызваны тем, что в любом месте моя программа может быть прервана планировщиком ОС. Т.е. если планировщик вклиниться между опасными командами 1 и 2, запустит на выполнение второй поток, который выполнит опасные команды 1 и 2, и опять запустит на выполнение первый поток, который выполнит опасную команду 2, возникнет ситуация "пепец".
Теперь внимание вопрос: если операция Count=Count+A в ассемблерном коде представлена одной процессорной командой Add, гарантирует ли это отсутствие ситуации "пепец" ?
Иными словами, можно ли ассемблерную инструкцию считать атомарной (выполняемой как единое целое) ?
Иными словами: планировщик современных ОС вклинивается между инструкциями x86 или между инструкциями внутреннего RISC-ядра процессора?
На всякий случай добавлю: пользоваться объектами синхронизации ОС (критические секции, Interlocked...) не вышло - очень замедляет работу моего RealTime приложения. Приложение запущено в пользовательском режиме (кольцо 4), cli и sti не советовать.
На всякий случай доп. информация (скорее всего не существенно):
Среда: Visual Studio 2005
ОС(целевая): Windows CE 6.0 R2
Процессор(целевой): AMD Geode LX800 (x86(набор инструкций P5), FPU, MMX, 3DNow!)