set_thread_area - назначение элемента GDT для области локального хранилища
set_thread_area(2)
назначение элемента GDT для области локального хранилища
ОБЗОР
#include <linux/unistd.h>
#include <asm/ldt.h>
int get_thread_area(struct user_desc *u_info);
int set_thread_area(struct user_desc *u_info);
Замечание: В glibc нет обёрточных функций для этих системных вызовов;
смотрите
ЗАМЕЧАНИЯ.
ОПИСАНИЕ
В Linux под локальное хранилище нити отдано три элемента глобальной таблицы
дескрипторов (GDT). Подробней о GDT читайте в Intel Software Developer's
Manual или AMD Architecture Programming Manual.
Этим системным вызовам передаётся указатель на структуру вида:
struct user_desc {
unsigned int entry_number;
unsigned long 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;
};
Вызов 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-битных сегментов или сегментов кода, но
допускается очистка таких сегментов.
ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
Данные системные вызовы возвращают 0 при успешном выполнении и 1 при ошибке,
записывая в
errno соответствующее значение.
ОШИБКИ
EFAULT
u_info является некорректным указателем.
EINVAL
u_info->entry_number вне допустимых границ.
ENOSYS
Вызов get_thread_area(2) или set_thread_area(2) был вызван как
64-битный системный вызов.
ESRCH
(set_thread_area()) Невозможно найти свободный элемент TLS.
ВЕРСИИ
Вызов
set_thread_area() появился в версии 2.5.29. Вызов
get_thread_area() появился в Linux 2.5.32.
СООТВЕТСТВИЕ СТАНДАРТАМ
set_thread_area() есть только в Linux, и он не должен использоваться в
переносимых программах.
ЗАМЕЧАНИЯ
В glibc нет обёрточных функций для этих системных вызовов, так как они
предназначены только для использования в библиотеках нитей. Если вам
всё-таки нужно их вызвать, используйте
syscall(2).
Вызов arch_prctl(2) может влиять на set_thread_area(2). Подробней
смотрите в arch_prctl(2). Обычно это не вызывает проблем, так как
arch_prctl(2) обычно используется только в 64-битных программах.
ДЕФЕКТЫ
В 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.