9

スレッド ローカル ストレージに関するUlrich Drepper の論文では、いくつかの異なる CPU アーキテクチャの TLS ABI の概要が説明されていますが、次の 2 つの理由から、TLS を実装するための基礎としては不十分であることがわかりました。

  1. ARM、MIPS などの多くの重要なアーキテクチャが省略されています (一方で、Itanium のような完全に無関係なものが多数含まれています)。
  2. さらに重要なことは、多くの実装の詳細が ABI と混在しているため、相互運用性に必要なプロパティと、彼の実装の単なる側面を区別するのが難しいことです。

例として、i386 の実際の ABI 要件は次のとおりです。

  • %gs:0自分自身へのポインタを指します。
  • メイン実行可能ファイルの TLS セグメントがある場合は、このアドレスからの固定 (リンカーによる負の) オフセットに配置する必要があります。
  • 最初にロードされたライブラリの他のすべての TLS セグメントには、このアドレスに関連する実行時定数 (つまり、各スレッドで同じですが、異なるプログラム実行間で必ずしも同じであるとは限りません) のオフセットが必要です (また、動的リンカーは、再配置をこれらのオフセット)。
  • ___tls_get_addr__tls_get_addr関数は、任意の TLS セグメントを検索するための正しいセマンティクスで存在する必要があります。

特に、DTV の存在またはレイアウトは ABI の一部ではなく、メイン プログラム以外の TLS セグメントの順序付け/レイアウトでもありません。

「TLSバリアントII」を使用するアーキテクチャには、おおよそ上記のABI要件があるようです。しかし、「TLSバリアントI」の要件をまったくよく理解していません。ソース(uClibcおよびglibcの)を読むと、「バリアントI」にはいくつかのバリアントが存在する可能性があるようです。

私が見るべきより良いドキュメントはありますか、またはTLSの仕組みに詳しい人がABI要件を説明してくれますか?

4

1 に答える 1

3

私がこれまでに集めることができる最高のものは次のとおりです。

TLSバリアント、__tls_get_addrまたは他のアーチ固有の関数のいずれかが存在し、TLSオブジェクトを検索するための正しいセマンティクスを持っている必要があり、任意の2つのTLSセグメント間の相対オフセットはランタイム定数(各スレッドで同じオフセット)である必要があります。

TLSバリアントII(i386など)の場合、「スレッドポインタレジスタ」(実際にはレジスタではないかもしれませんが、カーネルスペースのようなメカニズムまたはトラップのようなメカニズムです%gs:0。簡単にするために、レジスタと呼びましょう)はメイン実行可能ファイルのTLSセグメントの終わりを過ぎた場合、「終わりを過ぎたところ」には、TLSセグメントのアラインメントの次の倍数への切り上げが含まれます。

TLSバリアントIの場合、「スレッドポインタレジスタ」は、メインの実行可能ファイルのTLSセグメントの先頭からの固定オフセットを指します。このオフセットはアーチによって異なります。(一部の醜いRISCアーチでは、署名された16ビットオフセットを介してアクセスできるTLSの量を最大化するために選択されています。これは、コンパイラが再配置されたオフセットが16ビットに収まるかどうかを知る方法がないため、非常に役に立たないと思います。 load-upper / add命令を使用して、常に低速で大きな32ビットオフセットコードを生成します)。

私の知る限り、TCB、DTVなどについては、アプリケーションがこれらの構造にアクセスすることを許可されていないという意味で、ABIの一部ではありません。また、メインの実行可能ファイルの一部以外のTLSセグメントの場所もありません。 ABI。バリアントIとIIの両方で、「スレッドポインタレジスタ」からの固定オフセットにスレッドの実装内部情報を格納することは理にかなっています。どちらの方法でも、TLSセグメントの重複を安全に回避できます。

于 2012-10-15T01:03:50.377 に答える