Я написал простую совместную многопоточную библиотеку. В настоящее время я всегда сохраняю и восстанавливаю состояние fpu с помощью fxsave
/ fxrstor
при переключении в новый контекст. Но необходимо ли это в соглашении о вызовах cdecl?
В качестве простого примера:
float thread_using_fpu(float x)
{
float y = x / 2; // do some fpu operation
yield(); // context switch, possibly altering fpu state.
y = y / 2; // another fpu operation
return y;
}
Может ли компилятор сделать какие-либо предположения о состоянии FPU после вызова yield()
?
Согласно БИНАРНЫЙ ИНТЕРФЕЙС ПРИЛОЖЕНИЯ SYSTEM V Приложение для архитектуры Intel386TM, стр. 3-12:
% st (0): если функция не возвращает значение с плавающей точкой, то это
регистр должен быть пустым. Этот регистр должен быть пустым до
вход в функцию.% st (1) -% st (7):
Регистры с плавающей запятой не имеют определенной роли в
стандартная последовательность вызова. Эти регистры должны быть пустыми перед входом
и при выходе из функции.
Таким образом, вам не нужно переключать их контекст.
Другая, более новая версия говорит это:
Процессор должен находиться в режиме x87 при входе в функцию. Поэтому каждая функция, которая использует регистры MMX, должна выдавать
Инструкция emms или femms после использования регистров MMX, перед возвратом
или вызов другой функции. […] Управляющие биты регистра MXCSR сохраняются вызываемым абонентом (сохраняется при вызовах), а биты состояния сохраняются вызывающим абонентом (не сохраняются).
Регистр слова состояния x87 сохраняется вызывающим абонентом, тогда как элемент управления x87
слово сохранено.
[…] Все регистры x87 сохраняются вызывающими, поэтому вызывающие абоненты, использующие регистры MMX, могут использовать инструкцию более быстрого femms.
Таким образом, вам может понадобиться сохранить контрольное слово.
Нет. Вы не должны делать никаких сбережений государства. Если один поток находится в середине вычисления с плавающей запятой, где, например, установлен денормализованный флаг, и этот поток прерывается, то при возобновлении O / S или ядро установит флаги, точно так же, как восстановит другие регистры. Точно так же вам не нужно беспокоиться об этом в yield ().
Изменить: Если вы делаете свое собственное переключение контекста, возможно, вам нужно будет сохранить контрольные флаги точности и округления, если вам нужно установить для них значения не по умолчанию. В противном случае снова ты в порядке.