Это немного сложно ( этот документ объясняет это очень подробно), но в принципе ни то, ни другое. Вместо этого компилятор помещает специальный раздел .tdata в исполняемый файл, который содержит все локальные переменные потока. Во время выполнения создается новый раздел данных для каждого потока с копией данных в разделе (только для чтения) .tdata, а когда потоки переключаются во время выполнения, этот раздел также переключается автоматически.
Конечным результатом является то, что переменные __thread так же быстры, как и обычные переменные, и они также не занимают дополнительного стекового пространства.