локальный поток и переключение контекста

У меня есть код на С++, использующий локальное хранилище потоков, каждый поток имеет вектор, в который он может помещать данные.

Я использую TLS для хранения идентификатора индекса для каждого потока, его можно использовать для поиска, в какой вектор вставлять данные. Затем он выполняет изрядное количество кода, который помещает данные в вектор.

Мне интересно, возможно ли, что ОС может перепланировать мой код для выполнения в другом потоке после того, как он получил указатель на локальный объект потока. (Пока что код выполняется нормально, и я этого не видел). Но если бы это было возможно, это наверняка бы сломало мою программу, поскольку теперь два потока могли бы иметь один и тот же объект.

Предполагая, что это правда, кажется, что это будет проблемой даже для любого кода, использующего TLS любой сложности, предназначен ли TLS только для простых объектов, где вы не берете адрес?

Спасибо!


person Froglegs    schedule 24.01.2013    source источник
comment
Какую библиотеку потоков вы используете? Вы сами создаете темы? Использовать кражу работы?   -  person Marc Glisse    schedule 24.01.2013
comment
Я использую Intel TBB, без явных потоков, только на основе задач   -  person Froglegs    schedule 24.01.2013
comment
Насколько я знаю, Intel TBB не переносит задачи между потоками, так что вы в безопасности. (нет такой вещи, как ОС, меняющая идентификатор потока за вашей спиной)   -  person Marc Glisse    schedule 24.01.2013


Ответы (2)


Локальное хранилище потоков — это просто хранилище для каждого потока. Каждый поток имеет свою собственную частную структуру данных. Этот поток, на каком бы процессоре он ни работал, является одним и тем же потоком. ОС не планирует работу ВНУТРИ потоков, она планирует, какие из потоков выполняются.

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

В процессорах x86 FS или GS обычно используются для данных «по потоку», поэтому ОС переключает регистр FS [или содержимое базового адреса регистра в случае 64-разрядных процессоров]. При чтении TLS компилятор будет использовать регистр сегмента FS или GS для префикса операций чтения/записи памяти, и, таким образом, вы всегда получаете «ваши личные данные», а не какие-то другие потоки.

Конечно, в ОС могут быть ошибки, но это то, на что будет полагаться довольно много вещей, поэтому, если что-то сломано, оно обнаружится довольно скоро (если только оно не очень тонкое, и вы должны стоять в нужном месте, с луна в правильной фазе, одежда правильного цвета, ветер в правильном направлении, дата делится на 3 и 7 и т. д. и т. д.).

person Mats Petersson    schedule 24.01.2013
comment
Ах, хорошо, так что TLS специфичен для потока, а не для аппаратного процессора, спасибо! - person Froglegs; 24.01.2013
comment
Ну, это зависит от процессора, на котором работает поток, но если поток перемещается, ОС перемещает настройки TLS вместе с потоком. - person Mats Petersson; 24.01.2013

TLS означает поток local, из вашего описания каждый поток получает доступ к общему вектору вектора через TLS (я не уверен), вы должны использовать какую-то блокировку. Есть примеры кодов?

person Jason L.    schedule 24.01.2013