реклама на сайте
подробности

 
 
> Атомарность операций
sysel
сообщение Oct 2 2009, 07:33
Сообщение #1


Знающий
****

Группа: Свой
Сообщений: 601
Регистрация: 3-07-07
Пользователь №: 28 852



Здравствуйте!

Прошу прощения за оффтоп(хотя ОС Windows CE), но проблема такова:

Пишу многопоточную программу под х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 приложения. Приложение запущено в пользовательском режиме (кольцо 3), cli и sti не советовать.

На всякий случай доп. информация (скорее всего не существенно):
Среда: Visual Studio 2005
ОС(целевая): Windows CE 6.0 R2
Процессор(целевой): AMD Geode LX800 (x86(набор инструкций P5), FPU, MMX, 3DNow!)
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
Oldring
сообщение Oct 7 2009, 10:32
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 3 041
Регистрация: 10-01-05
Из: Москва
Пользователь №: 1 874



Цитата(sysel @ Oct 2 2009, 11:33) *
Пишу многопоточную программу под х86 процессор (защищенный режим) на С++.
Есть глобальная переменная (назовём её Count) для взаимодействия двух потоков. (в обоих потоках присутствуют операции чтение, запись и чтение-модификация-запись (Count=Count+A)).


Под Виндами правильно пользоваться Interlocked функциями Win32 API, такими как InterlockedIncrement. Код будет гарантированно переносимыми на другие платформы.

Ассемблерная команда инкремента переменной в памяти будет атомарной с точки зрения ядра процессора, но не с точки зрения доступа по шине. Поэтому предлагаемое решение не будет работать на многоядерных процессорах. Правильное решение на x86 ассемблере - использовать команду с префиксом lock.


--------------------
Пишите в личку.
Go to the top of the page
 
+Quote Post
Xenia
сообщение Oct 7 2009, 10:56
Сообщение #3


Гуру
******

Группа: Модератор FTP
Сообщений: 4 479
Регистрация: 20-02-08
Из: Москва
Пользователь №: 35 237



Цитата(Oldring @ Oct 7 2009, 14:32) *
Правильное решение на x86 ассемблере - использовать команду с префиксом lock.


Что-то сомнительно. Префикс LOCK блокирует шину только на время выполнения данной инструкции, поэтому здесь это не поможет, поскольку "порча" происходит во время прерывания между соседними инструкциями. Кроме того, у меня противоречивые сведения о том, распространяются ли привилегии на префикс LOCK или нет.
Go to the top of the page
 
+Quote Post



Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 20th June 2025 - 19:37
Рейтинг@Mail.ru


Страница сгенерированна за 0.01373 секунд с 7
ELECTRONIX ©2004-2016