Программирование транзакционной памяти AIX

Транзакционная память - это механизм синхронизации общей памяти, который позволяет нитям процесса выполнять операции сохранения, которые воспринимаются другими нитями процесса или приложениями как атомарные.

Обзор

Транзакционная память - это конструкция, которая позволяет выполнять критические разделы кода, основанных на блокировках, без получения блокировки. Первый процессор, реализующий программирование транзакционной памяти - это IBM® POWER 8.

Используйте механизм транзакционной памяти в следующих сценариях:
  • Оптимистическое выполнение приложений, основанных на блокировках. Транзакционная память поддерживает спекулятивное выполнение (выполнение "по предположению") критических разделов кода без получения блокировки. Этот метод предоставляет приложениям преимущества блокировки с высокой степенью детализации путем использования текущих блокировок, которые не настроены для производительности.
  • Программирование транзакций на языках высокого уровня. Программная модель транзакций - это развивающийся общеотраслевой стандарт, который предлагает повышение производительности относительно программ доступа к общей памяти на основе блокировки.
  • Использование контрольной точки/отката – Транзакционная память используется в качестве контрольной точки для восстановления архитектурного состояния. Этот метод позволяет выполнять спекулятивные оптимизации при компиляции во время динамической оптимизации кода или генерации и имитации контрольных точек.

Для использования механизма транзакционной памяти нить процесса помечает начало и конец последовательности обращений к памяти или транзакции с помощью команд tbegin. и tend. . Команда tbegin. инициирует выполнение транзакции, во время которого операции загрузки и сохранения выполняются как атомарные. Команда tend. завершает выполнение транзакции.

При преждевременной остановке транзакции выполняется откат обновлений памяти, сделанных после выполнения команды tbegin.. Соответственно, для содержимого подмножества регистров также выполняется откат в состояние, которое было до выполнения команды tbegin.. При преждевременной остановке транзакции запускается обработчик программных сбоев. Сбой может быть устойчивым или неустойчивым. Обработчик сбоев может повторить транзакцию или выбрать использование другой блокирующей логической структуры или другого логического пути, которые зависят от характера сбоя.

Операционная система AIX поддерживает использование транзакционной памяти, включая обработку управления состоянием транзакционной памяти между переключениями контекста и прерываниями.

Состояние контрольной точки

При инициации транзакции сохраняется набор регистров, представляющих состояние контрольной точки процессора. В случае сбоя транзакции восстанавливается состояние регистров, существовавшее перед запуском транзакции. Состояние контрольной точки процессора называется также предтранзакционным. Состояние контрольной точки включает перезаписываемые регистры задачного режима, за исключением регистров CR0, FXCC, EBBHR, EBBRR, BESCR, регистры системного монитора и SPR транзакционной памяти.

Прим.: К состоянию контрольной точки нельзя получить доступ непосредственно через состояние супервизора или состояние задачи.
После выполнения новой команды treclaim. состояние контрольной точки копируется в соответствующие регистры . Этот процесс позволяет привилегированному коду сохранять и изменять значения. После выполнения новой команды trechkpt. состояние контрольной точки копируется обратно в предполагаемые регистры из соответствующих пользовательских регистров .
К регистрам состояния машины процессора добавляются следующие SPR транзакционной памяти:
Имя Название Описание Привилегированный mtspr Привилегированный mfspr Размер (бит) SPR
FSCR Facility Status and Control Register (регистр состояния устройств и управления) Управляет доступными устройствами в состоянии задачи и указывает причину прерывания из-за недоступности устройства. да yes 64 153
TEXASR Transaction Exception And Summary Register (регистр исключительной ситуации транзакции и сводной информации) Содержит информацию об уровне транзакции и сводную информацию, которая используется обработчиками сбоев транзакций. Биты 0:31 содержат причину сбоя. no no 64 130
TFHAR Transaction Failure Handler Address Register (адресный регистр обработчика сбоев транзакций) Записывает EA обработчика программных сбоев. Для команды tbegin., которая инициировала транзакцию, для регистра TFHAR всегда задается NIA. no нет 64 128
TFIAR Transaction Failure Instruction Address Register (регистр адреса команды, вызвавшей сбой транзакции) Если это возможно, содержит точное значение EA команды, которая вызвала сбой. Точность регистра TFIAR указана в поле Exact (бит 37) регистра TEXASR. no нет 64 129
TEXASRU Transaction Exception And Summary Register (регистр исключительной ситуации транзакции и сводной информации, верхняя половина) Верхняя половина регистра TEXASR. нет no 32 131
Новый регистр TEXASR содержит информацию, относящуюся к состоянию транзакции и причине ее сбоя. Поля, включаемые в регистр TEXASR, описаны в следующей таблице:
Имя Поле Смысл значения Биты
TEXASR Код сбоя (примечание: бит 7 называется полем Устойчивый сбой) Коды сбоев транзакций 0:7
Запрещено 0b1 - команда типа доступа не разрешена 8
Переполнение при вложении 0b1 - превышен максимальный уровень транзакции. 9
Переполнение потребности 0b1 - превышен лимит отслеживания для обращений к транзакционной памяти. 10
Самопроизвольный конфликт 0b1 - в состоянии приостановки произошел самопроизвольный конфликт. 11
Нетранзакционный конфликт 0b1 - возник конфликт с доступом другого процессора в нетранзакционном режиме. 12
Конфликт транзакций 0b1 - Возник конфликт с другой транзакцией. 13
Конфликт при аннулировании преобразования 0b1 - произошел конфликт при аннулировании TLB. 14
Конкретная реализация 0b1 - зависящее от реализации условие привело к сбою транзакции. 15
Конфликт при вызове команды 0b1 - вызов команды нитью или другой нитью, выполнявшийся из блока, который ранее был записан в режиме транзакции. 16
Зарезервировано для будущих вариантов сбоев   17:30
Прекращение выполнения 0b1 – преждевременное прекращение выполнения было вызвано выполнением команды транзакционной памяти. 31
Приостановка 0b1 – В состоянии приостановки был зарегистрирован сбой. 32
Зарезервировано   33
Привилегия Во время регистрации сбоя нить находилась в привилегированном состоянии ([MSRHV||PR]). 34:35
Сводная информация о сбое (FS) 0b1 - сбой был обнаружен и записан. 36
Точность TFIAR

0b0 - поле TFIAR содержит приближенное значение.

0b1 - поле TFIAR содержит точное значение.

37
ROT

Значение равно 0b0 для отличной от ROT tbegin. .

При инициации транзакции ROT значение равно 0b1.

38
Зарезервировано   39:51
Уровень транзакции (TL) Уровень транзакции (уровень вложенности + 1) для активной транзакции имеет следующие значения:
  • 0, если самая последняя транзакция успешно выполнена.
  • Уровень транзакции, на котором не была выполнена самая последняя транзакция, если транзакция не была выполнена успешно.
Прим.: Значение 1 соответствует внешней транзакции. Значение, превышающее 1, соответствует вложенной транзакции.
52:63
Notes:
  • В случае регистрации сбоя транзакции задается в точности 1 бит из 8-31 битов регистра TEXASR. Единственный заданный бит указывает, что сбой вызван конкретной командой или событием.
  • Транзакция ROT (Rollback Only Transaction) - это последовательность команд, которые выполняются или не выполняются единым блоком. Эта конструкция позволяет с минимальными затратами выполнять большой объем команд "по предположению". В отличие от обычной транзакции, ROT не является полностью атомарной и не обладает свойствами синхронизации и сериализации, присущими обычной транзакции. Поэтому транзакции ROT не следует использовать для обработки общих данных.

Обработчик программных сбоев

В случае сбоя транзакции аппаратное обеспечение системы передает управление обработчику сбоев, связанному с самой внешней транзакцией. При сбое транзакции управление передается команде, которая следует за командой tbegin., а в CR0 задается или
0b101 || 0
, или
0b010 || 0
Следовательно, за командой tbegin. должна следовать команда передачи управления, основанная на бите 2 регистра CR0. Например, после выполнения команды tbegin. может следовать команда передачи управления beq, основанная на бите 2 регистра CR0. Управление должно передаваться разделу кода, который обрабатывает сбои транзакций. Если в начале транзакции успешно выполняется команда tbegin., то в регистре CR0 устанавливается или
0b000 || 0, или 0b010 || 0
Прим.: На причину сбоя указывают биты 0:31 TEXASR. Поле кода сбоя (FC) в битах 0-7 используется для следующих сценариев:
  • Привилегированный код в режиме супервизора или гипервизора вызывает сбой при использовании команды treclaim. .
  • Код в режиме задачи вызывает сбой при использовании формы tabort. .
Значение l в седьмом бите регистра TEXASR указывает, что сбой является устойчивым, и повторные попытки выполнить транзакцию будут неуспешными. Коды сбоев, зарезервированные операционной системой AIX, указывают причину сбоя, которая определена в файле /usr/include/sys/machine.h..

Пример транзакции

Следующий пример кода на ассемблере иллюстрирует простую транзакцию, которая записывает значение из GPR 5 по адресу в GPR 4, который считается общим для нескольких нитей выполнения. В случае невыполнения транзакции из-за устойчивого сбоя программа выполняется по альтернативному пути с меткой lock_based_update. Код для альтернативного пути не показан.
trans_entry:
  tbegin                             # Запустить транзакцию
  beq          failure_hdlr          # Обработать сбой транзакции
  stw          r5, 0(r4)             # Записать в память, указанную r4.
  tend.                              # Завершить транзакцию
  b            trans_exit
failure_hdlr:                        # Обработать сбои транзакции:
  mfspr        r4, TEXASRU           # Прочитать верхнюю половину TEXASR
  andis.       r5, r4, 0x0100        # Является ли сбой устойчивым?
  bne          lock_based_update     # Если сбой является устойчивым, получить 
                                     # блокировку, затем выполнить запись.
  b            trans_entry           # Если это самоустраняющийся отказ, повторить транзакцию.

lock_based_update:

trans_exit:

Динамическая проверка поддержки транзакционной памяти

Для того чтобы определить, поддерживает ли система категорию транзакционной памяти POWER ISA, в программе можно использовать функцию getsystemcfg для чтения системной переменной SC_TM_VER. В файле /usr/include/sys/systemcfg.h предоставляется макрос __power_tm(), предназначенный для определения функции транзакционной памяти внутри программы. Этот макрос полезен для программного обеспечения, которое условно использует функцию транзакционной памяти при ее наличии, а при ее отсутствии использует функционально эквивалентные пути кода на основе блокировки.

Структура расширенного контекста

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

Расширенный контекст выделяется и закрепляется для каждой нити транзакционного процесса при первом использовании ею транзакционной памяти. Если область расширенного контекста невозможно выделить и закрепить, то процесс получает сигнал SIGSEGV, который приводит к завершению процесса.

Информация о контексте системы включается в структуру sigcontext, которая предоставляется обработчикам сигналов. При возврате из обработчика сигнала активируется контекст системы, представленный в структуре sigcontext. Фактически структура sigcontext представляет собой подмножество структуры ucontext большего размера. Эти две структуры идентичные; различие состоит только в результате sizeof(struct sigcontext). Когда операционная система AIX компонует контекст сигналов, передаваемый обработчику сигналов, в стеке обработчика сигналов компонуется структура ucontext. Контекст системы, входящий в состав контекста сигналов, должен содержать все сведения о динамическом или статическом состоянии системы для случайно прерванного контекста. Структура ucontext содержит индикатор, указывающий, доступна ли информация о расширенном контексте.

Поле __extctx структуры ucontext - это адрес структуры расширенного контекста, которая определена в файле /usr/include/sys/context.h. Поле __extctx_magic структуры ucontext указывает, допустима ли информация о расширенном контексте, когда значение поля __extctx_magic равно __EXTCTX_MAGIC. Дополнительное состояние системы для нити, которая использует функцию транзакционной памяти, восстанавливается и сохраняется как элемент расширения контекста в структуре ucontext в рамках доставки и возврата сигнала.

Если приложение явным образом разрешает использование транзакционной памяти, то оно выбирает структуру ucontext увеличенного размера, в которой уже есть память для поля __extctx, которое включается компилятором путем неявного определения __EXTABI__. Расширенная структура ucontext может также выбираться с помощью явного определения __AIXEXTABI.

В состоянии выполнения транзакции и в состоянии приостановки транзакции не поддерживаются функции libc getcontext(), setcontext(), makecontext() и swapcontext(). Вызов функций getcontext(), setcontext(), makecontext() внутри транзакции приводит к устойчивому сбою транзакции типа TM_LIBC, который определен в файле /usr/include/sys/machine.h.

Вызов функции swapcontext() внутри транзакции приводит к следующему поведению:
  • Вызов функции swapcontext() в состоянии выполняющейся транзакции приводит к устойчивому сбою транзакции типа TM_LIBC.
  • Если функция swapcontext() вызывается в состоянии приостановки, то неудачное выполнение транзакции предопределено; подкачивается указанная структура ucontext, и возобновляется выполнение программы указанной структурой ucontext. Итоговое состояние и последующее поведение после возврата из функции swapcontext() не определено.

Если функции getcontext(), setcontext() и swapcontext() вызываются не в транзакционном состоянии, то они не извлекают в структуру ucontext и не восстанавливают из нее никакой расширенный контекст транзакционной памяти (структура указывается параметрами ucp или oucp). Если функции setcontext() или swapcontext() вызываются в присутствии расширенного контекста транзакционной памяти, то никакая ошибка не выдается.

Подробная информация о расширенном контексте содержится в заголовочном файле /usr/include/sys/context.h.

Доставка сигналов

Асинхронные сигналы, получаемые приложением в режиме выполнения транзакции, доставляются нетранзакционным способом. В состоянии, когда выполняется транзакция, доставка синхронных сигналов не разрешена, так как она приводит к устойчивому сбою транзакции типа TM_SYNC_SIGNAL, определенному в файле /usr/include/sys/machine.h.

Прерывания выравнивания и программные прерывания

В состоянии выполняющейся транзакции недопустимая операция или операция, требующая эмуляции, вызывает прерывания выравнивания или программные прерывания, что приводит к устойчивому сбою транзакции типа TM_ALIGN_INT или TM_INV_OP, который определен в файле /usr/include/sys/machine.h. В состоянии приостановленной транзакции прерывания выравнивания и программные прерывания обрабатываются обычным образом с использованием неспекулятивной семантики.

Системные вызовы

Предполагается, что транзакция не содержит системных вызовов. Системные вызовы в транзакции поддерживаются только в том случае, если транзакция приостановлена с помощью команды tsuspend. .

Если процесс или нить находятся в состоянии транзакции, и транзакция не приостановлена, то системный вызов в этом состоянии не выполняется ядром AIX и возникает устойчивый сбой транзакции. При возникновении этой ошибки поле FC регистра TEXASR содержит код сбоя TM_ILL_SC, который определен в файле /usr/sys/include/machine.h.

Предполагается, что сохраняются любые операции, выполняемые в транзакции, когда она явно приостанавливается разработчиком приложения. Любые операции, которые выполняются системным вызовом, сделанным в состоянии приостановки, не откатываются, даже если происходит сбой транзакции.

Операционная система AIX не поддерживает системные вызовы в транзакционном состоянии, поскольку не существует способа отката каких-либо операций, включая операции ввода-вывода, выполняемых AIX при системном вызове.

Функции setjmp() и longjmp()

В транзакционном состоянии и в состоянии приостановки не поддерживаются функции libc setjmp() и longjmp() из-за эффектов задания буфера перехода (jump buffer) и перехода обратно в буфер. Рассмотрим следующие сценарии
  1. Если функция setjmp() вызывается внутри транзакции, а соответствующая функция longjmp() - после завершения транзакции, то выполняется переход в спекулятивное состояние, которое теперь недопустимо.
  2. Если функция setjmp() вызывается перед транзакцией, соответствующая функция longjmp() переходит в это состояние до начала транзакции, независимо от результата выполнения транзакции: успешного завершения, сбоя или аварийного завершения.
  3. Если функция setjmp() вызывается внутри транзакции, а затем выполнение транзакции прекращается, то обновления, внесенные в буфер перехода функцией setjmp(), будут считаться не имевшими места.

Вызов функции setjmp() внутри транзакции приводит к устойчивому сбою транзакции типа TM_LIBC, или типа TM_ILL_SC, который определен в файле /usr/include/sys/machine.h.

Вызов функции longjmp() внутри транзакции приводит к следующему поведению:
  • Вызов функции longjmp() в состоянии выполняющейся транзакции приводит к устойчивому сбою транзакции типа TM_LIBC или типа TM_ILL_SC, который определен в файле /usr/include/sys/machine.h.
  • Если функция longjmp() вызывается в состоянии приостановки, то неудачное выполнение транзакции предопределено; указанный буфер восстанавливается и выполнение программы возвращается в соответствующую функцию setjmp(). Итоговое состояние и последующее поведение после возврата к setjmp() из функции longjmp() не определено.

Компиляторы

Компилятор операционной системы AIX, который поддерживает транзакционную память, должен соответствовать ABI AIX. Если включена транзакционная память, то компилятор C или C++ должен предопределить __EXTABI__. За более подробной информацией обратитесь к документации по компилятору.

Ассемблер

Компилятор ассемблера операционной системы AIX, расположенный в каталоге /usr/ccs/bin/as, поддерживает дополнительный набор инструкций, определенный для транзакционной памяти в POWER ISA и реализуемый процессором POWER8. Для того чтобы включить сборку команд транзакционной памяти, можно использовать режим сборки –m pwr8 или псевдооперацию .machine pwr8 внутри файла исходного кода. За дополнительной информацией обратитесь к справочнику по языку ассемблера.

Отладчик

Отладчик /usr/ccs/bin/dbx поддерживает отладку программ транзакционной памяти на машинном уровне. Эта поддержка включает возможность дизассемблирования новых команд транзакционной памяти и просмотра ее регистров специального назначения (SPR): TEXASR, TEXASRU, TFIAR и TFHAR.

Задание точки прерывания внутри транзакции приводит к безусловному прекращению выполнения транзакции при обнаружении точки прерывания. Таким образом, предлагаемый подход заключается в следующем: запуск отладчика для транзакции, которая не выполняется; задание точки прерывания в обработчике сбоев транзакции; просмотр регистров TEXASR и TFIAR в точке прерывания для определения причины и расположения сбоя.

В dbx для просмотра регистров TEXASR, TFIAR и TFHAR можно использовать команду print с параметром $texasr, $tfiar или $tfhar. Строку кода, связанную с адресом, найденным в регистрах TFIAR и TFHAR, можно просмотреть с помощью команды list, например:
(dbx) list at $tfiar
Для просмотра и интерпретации содержимого регистра TEXASR применяется команда dbx tm_status. Эта команда позволяет определить характер сбоя транзакции.

Для подключения отладчиков других фирм предусмотрена новая операция PTT_READ_TM ptrace для считывания состояния транзакционной памяти нити. За информацией обратитесь к документации по ptrace.

Поддержка трассировки

Трассировщик AIX был расширен и теперь включает набор событий трассировки операций транзакционной памяти, которые выполняются операционной системой AIX, в том числе приоритетное переключение процессов и другие операции, вызывающие сбой транзакции. Для просмотра событий трассировки, относящихся к транзакционной памяти, укажите в качестве входного параметра команды trace и trcrpt идентификатор события трассировки 675.

Файлы дампа

Операционная система AIX поддерживает включение состояния системы транзакционной памяти в файл дампа для использующих эту память процессов или нитей. Если процесс или нить используют или использовали транзакционную память, то в образ оперативной памяти включается состояние системы транзакционной памяти для такой нити.
Прим.: Состояние транзакционной памяти поддерживается только в текущих форматах файлов дампа для операционной системы AIX. Для чтения файла дампа с поддержкой транзакционной памяти и просмотра состояния системы транзакционной памяти применяется команда dbx.

Библиотека нитей AIX

Для приложений, которые используют нити M:N, транзакционная память не поддерживается. В среде, где несколько нитей совместно используют одну нить ядра, поведение транзакционных нитей может стать неопределенным. Применение транзакционной памяти приложением, которое использует нити M:N, может привести к устойчивому сбою транзакции с кодом сбоя TM_PTH_PREEMPTED, задаваемым в регистре TEXASR.