Локальные переменные потока и сегмент fs

Я читаю из локальной переменной потока в моем коде вроде этого,

// tid_local is declared as __thread int tid_local;
long tid = tid_local

Оглядываясь на дизассемблированный код, я увидел что-то вроде этого, которое, как я подозреваю, является инструкцией, которая присваивает tid, читая tid_local.

movslq %fs:0xfffffffffffffffc,%rbx

Теперь мой вопрос в том, действительно ли это может быть инструкция, которая делает это, то есть чтение из локальной переменной потока, и если gcc всегда использует сегмент fs для хранения локальных переменных потока. Как это должно работать?

Ответ 1

Да, это вполне может быть правильной инструкцией. Из руководства gcc :

-mtls-direct-seg-refs

-mno-tls-direct-seg-refs

Управляет доступом к переменным TLS с смещениями из регистров сегмента TLS (% gs для 32-разрядных,% fs для 64-разрядных) или должен быть добавлен указатель на основе потока. Независимо от того, является ли это законным, зависит от операционной системы и отображает ли он сегмент для охвата всей области TLS.

edit Вот отличная ссылка, предложенная @janneb в комментариях: http://www.akkadia.org/drepper/tls.pdf

Ответ 2

Способ, которым различные потоки могут иметь разные сегменты fs, реализуется путем настройки локальных таблиц дескриптора (LDT) для каждого потока. Когда происходит переключение потоков, процессор автоматически загружает любые дескрипторы сегмента "нить-локальные" из соответствующей LDT. Вы можете проверить это, посмотрев на значение FS. Если бит 3 равен 1, то он использует LDT.

Ex. FS = 1B (который, как правило, является обычным селектором "CS" для Win NT) - это локальный поток.

Вы работаете так:

Селектор в двоичном формате

0000 0000 0001 1011

или

Индекс = 0000 0000 0001 [12 бит] (вторая запись в DT)

Таблица дескрипторов = 1 [1 бит] (1 == local, 0 == global)

RPL = 011 [3 бит] (запрошенный уровень привилегий = 3)

  • Alan