4

非常に軽量な pthread 置換ライブラリを実装しています。__thread を完全に無効にしたい理由はいくつかあります。

  1. 記憶の無駄です。__thread で変数を宣言するコンテキストとは関係のないスレッドを 1000 作成している場合でも 、プログラムは1000* そのデータ バイトのサイズを割り当て、それを使用することはありません。大量同時実行モデルと互換性のあるメモリではありません。わずか 8K のスタックで非常に軽量なファイバーが必要な場合、わずか 4K の TLS ブロックは、各スレッドで使用されるメモリの 50% のオーバーヘッドになります。一部のシナリオでは、TLS オーバーヘッドが膨大になります。
  2. TLS は複雑な標準であり、それをサポートするための時間やリソースがありません。それは高価です。個人的には、標準の設計が不十分だと思います。スレッド ライブラリが TLS 割り当てが行われる場所を制御し、必要な関連するオフセットとアドレスを挿入できるように、リンカによって提供される必要がある標準関数を定義しておく必要があります。また、標準の ELF 実装は pthread に感染しており、pthread サイズの構造体がオフセットを計算することを期待しているため、他の何かに適応するのは非常に困難です。
  3. それはただの悪いパターンです。グローバルを使用し、静的関数/副作用を伴う関数を作成することをお勧めします。分析しやすい正しいプログラムを作成している場合、これは私たちが入りたい領域ではありません。
  4. シーンの背後でスレッドの状態を追跡する魔法 (割り当てやキャンセルの追跡など) のために「スレッド コンテキスト」が本当に必要な場合は、そもそもそのコンテキストを理解するために TLS が使用する魔法を公開しないのはなぜですか? 個人的には、%fsレジスタを直接使用するだけです。これは明らかな理由でライブラリでは不可能ですが、なぜ最初からスレッド対応にする必要があるのでしょうか? 引数リストの最初の場所で必要なコンテキスト関連のデータを取得できるように、正しく設計しないのはなぜですか?

私の質問は簡単です: __thread サポートを無効にして、clang を誤って使用した場合にエラーを発生させる最も簡単な方法は何ですか? たまたま TLS を必要とする動的ライブラリをロードすると、エラーが発生する可能性がありますか?

4

1 に答える 1

3

最も簡単な方法は、このようなものを無条件に CFLAGS に追加することだと思います(システムグローバルにしたい場合は、おそらくclangのgccスペックファイルに相当するものから):

-D__thread='^-^'

ここで、右辺は、C プログラムの任意の時点で構文的に無効 (制約違反) になる可能性があります。

TLS を使用したライブラリの読み込みを防止するには、リンカーや動的リンカーにパッチを適用してそれらを拒否する必要があります。について話しているだけの場合dlopen、プログラムは最初にファイルを読み取り、TLS 再配置の ELF ヘッダーを解析してから、ライブラリがあればそれを (に渡さずにdlopen) 拒否することができます。LD_PRELOADこれはラッパーでも可能かもしれません。

特に現在の実装では、TLS は一般的に使用を避けるべきものであることに同意しますが、コストを測定したかどうかお尋ねしてもよろしいですか? それを使用するように設計されたシステムでは、それを完全に消し去ることはかなり難しいと思います。どの libc を使用していますか? それが glibc なら、glibc には最近、内部で使用する TLS がたくさんあると確信しています...もちろん、独自のスレッド実装を作成している場合は、標準ライブラリの残りの部分との多くのやり取りが必要になります。 、おそらくあなたはすでにパッチを当てています...?


ちなみに (恥知らずなプラグインが続きます)、musl libcには非常に軽量なスレッド実装があり、現在 TLS はありません。別の libc と統合するのは簡単ではないと思います (また、独自の libc を作成している場合は、glibc、特に TLS のサポートを期待する glibc の動的リンカーとの統合が難しいことに気付くでしょう)。ライブラリ全体をそのまま使用できる場合は、特定のプロジェクトのニーズを満たすか、借用できる有用なコードがある可能性があります (ライセンスは MIT です)。

于 2012-09-22T12:05:10.930 に答える