set_thread_area(2)

НАИМЕНОВАНИЕ
get_thread_area, set_thread_area - управляют информацией области локального хранилища нити

БИБЛИОТЕКА
Стандартная библиотека языка C (libc, -lc)

ОБЗОР
#include <sys/syscall.h>     /* определения констант SYS_* */
#include <unistd.h>

#if defined __i386__ || defined __x86_64__
# include <asm/ldt.h>        /* определения struct user_desc */

int syscall(SYS_get_thread_area, struct user_desc *u_info);
int syscall(SYS_set_thread_area, struct user_desc *u_info);

#elif defined __m68k__

int syscall(SYS_get_thread_area);
int syscall(SYS_set_thread_area, unsigned long tp);

#elif defined __mips__ || defined __csky__

int syscall(SYS_set_thread_area, unsigned long addr);

#endif

Примечание: glibc не предоставляет обёрточных функций для этих системных вызовов, что делает необходимым использование syscall(2).

ОПИСАНИЕ
These calls provide architecture-specific support for a thread-local storage implementation. At the moment, set_thread_area() is available on m68k, MIPS, C-SKY, and x86 (both 32-bit and 64-bit variants); get_thread_area() is available on m68k and x86.

On m68k, MIPS and C-SKY, set_thread_area() allows storing an arbitrary pointer (provided in the tp argument on m68k and in the addr argument on MIPS and C-SKY) in the kernel data structure associated with the calling thread; this pointer can later be retrieved using get_thread_area() (see also NOTES for information regarding obtaining the thread pointer on MIPS).

На x86 в Linux под локальное хранилище нити отдано три элемента глобальной таблицы дескрипторов (GDT). Подробней о GDT читайте в Intel Software Developer's Manual или AMD Architecture Programming Manual.

Этим системным вызовам передаётся указатель на структуру вида:

    struct user_desc {
        unsigned int  entry_number;
        unsigned int  base_addr;
        unsigned int  limit;
        unsigned int  seg_32bit:1;
        unsigned int  contents:2;
        unsigned int  read_exec_only:1;
        unsigned int  limit_in_pages:1;
        unsigned int  seg_not_present:1;
        unsigned int  useable:1;
    #ifdef __x86_64__
        unsigned int  lm:1;
    #endif
    };

Вызов get_thread_area() читает элемент GDT, указанный в u_info->entry_number и заполняет оставшиеся поля в u_info.

Вызов set_thread_area() изменяет элемент TLS в GDT.

Элемент массива TLS, устанавливаемый set_thread_area(), соответствует значению u_info->entry_number, которое передал пользователь. Если это значение находится в допустимых пределах, то set_thread_area() записывает дескриптор TLS, на который указывает u_info, в массив TLS нити.

Когда set_thread_area() передаётся entry_number со значением -1, то ищется свободный элемент TLS. Если set_thread_area() находит свободный элемент TLS, то значение u_info->entry_number устанавливается после возврата для показа того, какой же элемент был изменён.

Структура user_desc считается «пустой», если read_exec_only и seg_not_present равны 1, а все остальные поля равны 0. Если «пустой» дескриптор передаётся в set_thread_area(), то соответствующий элемент TLS будет очищен. Дополнительную информацию смотрите в разделе ДЕФЕКТЫ.

Начиная с Linux 3.19, set_thread_area() нельзя использовать для записи отсутствующих сегментов, 16-битных сегментов или сегментов кода, но допускается очистка таких сегментов.

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
On x86, these system calls return 0 on success, and -1 on failure, with errno set to indicate the error.

On C-SKY, MIPS and m68k, set_thread_area() always returns 0. On m68k, get_thread_area() returns the thread area pointer value (previously set via set_thread_area()).

ОШИБКИ

EFAULT
    u_info является некорректным указателем.

EINVAL
    u_info->entry_number вне допустимых границ.

ENOSYS
    Вызов get_thread_area() или set_thread_area() был вызван как 64-битный системный вызов.

ESRCH
    (set_thread_area()) Невозможно найти свободный элемент TLS.

СТАНДАРТЫ
Linux.

ИСТОРИЯ

set_thread_area()
    Linux 2.5.29.

get_thread_area()
    Linux 2.5.32.

ПРИМЕЧАНИЯ
These system calls are generally intended for use only by threading libraries.

На x86 вызов arch_prctl(2) может влиять на set_thread_area(). Подробней смотрите в arch_prctl(2). Обычно это не вызывает проблем, так как arch_prctl(2) обычно используется только в 64-битных программах.

На MIPS текущее значение указателя области нити можно получить с помощью инструкции:

    rdhwr dest, $29

Эта инструкция ловится и обрабатывается ядром.

ОШИБКИ
В 64-битных ядрах до Linux 3.19, если был установлен один из битов заполнения в user_desc, то это приводило к тому, что дескриптор не считался пустым (смотрите modify_ldt(2)). В результате, единственным надёжным способом очистить элемент TLS было задействование memset(3) для обнуления всей структуры user_desc, включая биты заполнения, и затем установка битов read_exec_only и seg_not_present. В Linux 3.19, структура user_desc, полностью состоящая из нулей кроме entry_number, также будет считаться запросом на очистку элемента TLS, что отличается от работы старых ядер.

До Linux 3.19, сегментные регистры DS и ES не должны ссылаться на элементы TLS.

СМОТРИТЕ ТАКЖЕ
arch_prctl(2), modify_ldt(2), ptrace(2) (PTRACE_GET_THREAD_AREA and PTRACE_SET_THREAD_AREA)

ПЕРЕВОД
Русский перевод этой страницы руководства разработал(и) Alexander Golubev <fatzer2@gmail.com>, Azamat Hackimov <azamat.hackimov@gmail.com>, Hotellook, Nikita <zxcvbnm3230@mail.ru>, Spiros Georgaras <sng@hellug.gr>, Vladislav <ivladislavefimov@gmail.com>, Yuri Kozlov <yuray@komyakino.ru> и Иван Павлов <pavia00@gmail.com>

Этот перевод является свободной программной документацией; он распространяется на условиях общедоступной лицензии GNU (GNU General Public License - GPL, https://www.gnu.org/licenses/gpl-3.0.html версии 3 или более поздней) в отношении авторского права, но БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ.

Если вы обнаружите какие-либо ошибки в переводе этой страницы руководства, пожалуйста, сообщите об этом разработчику(ам) по его(их) адресу(ам) электронной почты или по адресу списка рассылки русских переводчиков (<debian-l10n-russian@lists.debian.org>).