getcontext(3) получить или установить пользовательский контекст

Other Alias

setcontext

ОБЗОР

#include <ucontext.h>

int getcontext(ucontext_t *ucp);
int setcontext(const ucontext_t *ucp);

ОПИСАНИЕ

В окружении, подобном SysV, существует два типа данных —mcontext_t и ucontext_t, которые определены в файле <ucontext.h> и четыре функции — getcontext(), setcontext(), makecontext(3) и swapcontext(3), которые позволяют контексту пользовательского уровня переключаться между несколькими нитями внутри одного процесса.

Тип mcontext_t является машинно-зависимым и примитивным типом данных. Тип ucontext_t является структурой, которая по крайней мере имеет следующие поля:

typedef struct ucontext {
    struct ucontext *uc_link;
    sigset_t         uc_sigmask;
    stack_t          uc_stack;
    mcontext_t       uc_mcontext;
    ...
} ucontext_t;
где sigset_t и stack_t определены в файле <signal.h>. В этой структуре uc_link указывает на контекст, к которому будет осуществлён переход, когда завершается текущий контекст (в случае, если текущий контекст был создан с помощью makecontext(3)), в uc_sigmask задаётся список сигналов, которые блокируются в этом контексте (см. sigprocmask(2)), uc_stack --- это стек, который используется этим контекстом (см. sigaltstack(2)), а uc_mcontext является машинно-зависимым представлением сохранённого контекста, который содержит регистры вызываемой нити.

Функция getcontext() инициализирует вышеописанную структуру, указывая через ucp на текущий активный контекст.

Функция setcontext() восстанавливает пользовательский контекст, на который указывает ucp. При успешном вызове управление не возвращается обратно. Контекст должен быть получен с помощью вызова getcontext() или makecontext(3) или передан как третий аргумент обработчика сигнала.

Если контекст был получен через вызов getcontext(), то выполнение программы продолжается как если бы этот вызов завершился простым возвратом.

Если контекст был получен через вызов makecontext(3), выполнение программы продолжается с помощью вызова функции func, которая задаётся как второй аргумент вызова makecontext(3). Когда происходит возврат из функции func, выполнение продолжается с поля uc_link структуры ucp, которая задаётся как первый аргумент вызова makecontext(3). Если это поле равно NULL, осуществляется выход из нити.

Если контекст был получен с помощью вызова обработчика сигнала, то старый текст стандарта говорит, что "выполнение программы продолжается с инструкции программы, которая следует за инструкцией, прерванной сигналом". Однако, этот текст был удалён в SUSv2 с вердиктом "результат не определён".

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ

В случае успеха getcontext() возвращает 0, а setcontext() не возвращает ничего. В случае ошибки, возвращается -1 и значение errno устанавливается соответствующим образом.

ОШИБКИ

Не определены.

АТРИБУТЫ

Описание терминов данного раздела смотрите в attributes(7).
ИнтерфейсАтрибутЗначение
getcontext(), setcontext() безвредность в нитяхбезвредно (MT-Safe race:ucp)

СООТВЕТСТВИЕ СТАНДАРТАМ

SUSv2, POSIX.1-2001. В POSIX.1-2008 удалено определение getcontext() со ссылкой на проблемы с переносимостью и рекомендацией переписать приложение с использование нитей POSIX.

ЗАМЕЧАНИЯ

В ранних версиях этого механизма использовался механизм setjmp(3)/longjmp(3). Так как в нём нет обработки контекста сигнала, было решено использовать следующий вариант пары sigsetjmp(3)/siglongjmp(3). Текущий механизм даёт много больше контроля. С другой стороны, не существует лёгкого способа определить какое из двух значений возвращает при первом запуске вызов getcontext() или вызов setcontext(). Пользователь должен придумать собственный способ и через регистровую переменную это сделать нельзя, так как значения регистров восстанавливаются.

Если возникнет сигнал, текущий пользовательский контекст сохраняется и для обработчика сигнала ядром создаётся новый контекст. Не выходите из этого обработчика, используя longjmp(3) --- неизвестно, что может случиться с контекстами. Вместо этого используйте вызовы siglongjmp(3) или setcontext().