2012-10-14 4 views
9

Ulrich Drepper's paper auf Thread-Local Storage umreißt das TLS ABI für verschiedene CPU-Architekturen, aber ich finde es als Grundlage unzureichend für TLS aus zwei Gründen Umsetzung:Was sind die wirklichen ELF TLS ABI Anforderungen für jeden CPU-Arch?

  1. Es läßt eine Reihe wichtiger Archs wie ARM , MIPS, etc. (mit einer Reihe von komplett irrelevanten wie Itanium)
  2. Noch wichtiger ist, es mischt viele Implementierungsdetails mit ABI, so dass es schwer zu sagen ist, welche Eigenschaften für die Interoperabilität benötigt werden und welche nur Aspekte seiner Umsetzung.

Als Beispiel die einzigen tatsächlichen ABI Anforderungen für i386 sind:

  • %gs:0 zeigt auf einen Zeiger auf sich selbst.
  • Das TLS-Segment der Hauptausführung muss (falls vorhanden) an einem festen (durch den Linker, negativ) Offset von dieser Adresse liegen.
  • Alle anderen TLS-Segmente für anfänglich geladene Bibliotheken müssen eine Laufzeitkonstante (dh für jeden Thread, aber nicht notwendigerweise die gleichen über verschiedene Programmläufe hinweg) Offsets relativ zu dieser Adresse haben (und der dynamische Linker muss füllen können) in Umzügen mit diesen Offsets).
  • ___tls_get_addr und __tls_get_addr Funktionen müssen mit der korrekten Semantik zum Nachschlagen beliebiger TLS-Segmente vorhanden sein.

Insbesondere die Existenz oder das Layout eines DTV ist nicht Teil des ABI, noch ist die Bestellung/Layout TLS Segmente außer dem Hauptprogramm.

Es scheint, dass jeder Bogen, der "TLS-Variante II" verwendet, ungefähr die obigen ABI-Anforderungen hat. Aber ich verstehe die Anforderungen der "TLS-Variante I" überhaupt nicht sehr gut, und aus den Quellen (in uClibc und glibc) scheint es, dass es sogar mehrere Varianten von "Variante I" geben kann.

Gibt es bessere Dokumente, die ich mir ansehen sollte, oder kann jemand, der mit der Funktionsweise von TLS vertraut ist, die ABI-Anforderungen für mich erklären?

+1

Es tut mir leid, wenn ich das offensichtliche frage, aber haben Sie die 'GCC' TLS Unterstützung überprüft? Zum Beispiel hat die Mailingliste 'gcc-patches' einen Thread, der am 1. Juni diesen Jahres beginnt und MIPS16-TLS-Unterstützung hinzufügt (http://marc.info/?l=gcc-patches&m=132586147826602). Die Compiler-Leute scheinen bezüglich dieser Art von Dingen viel formeller zu sein als die C-Bibliotheksentwickler; sie könnten eine bessere formelle Dokumentation haben. –

Antwort

3

Das Beste, was ich bisher sammeln kann, ist:

Für entweder TLS Variante __tls_get_addr oder andere Bogen spezifischer Funktionen müssen die richtige Semantik existieren und zum Nachschlagen jeden TLS-Objekts und die relativen zwischen zwei beliebigen Offset TLS-Segmente müssen eine Laufzeitkonstante sein (gleicher Offset für jeden Thread).

Für TLS-Variante II (i386, etc.), die "Thread-Zeiger-Register" (die möglicherweise kein Register, aber vielleicht ein Mechanismus wie %gs:0 oder sogar eine Falle in Kernelspace; aus Gründen der Einfachheit nennen wir es einfach ein Register) Punkte knapp hinter dem Ende des TLS-Segments für die Hauptdatei, wo "gerade nach dem Ende" umfasst Runden bis zum nächsten Vielfachen der Ausrichtung des TLS-Segments.

Bei der TLS-Variante I zeigt das "Thread Pointer Register" auf einen festen Offset von Anfang des TLS-Segments für die Hauptdatei. Dieser Offset variiert je nach Bogen.(Es wurde auf einigen hässlichen RISC Archs gewählt, um die Menge an TLS zu maximieren, die über vorzeichenbehaftete 16-Bit-Offsets zugänglich sind, was mir extrem unbrauchbar erscheint, da der Compiler keine Möglichkeit hat, zu wissen, ob der verlagerte Offset in 16 Bits passen wird Generiere immer den langsameren, größeren 32-Bit-Offset-Code unter Verwendung von load-upper/add-Befehlen.

Soweit ich sagen kann, ist nichts über TCBs, DTVs usw. Teil des ABI, in dem Sinne, dass Anwendungen nicht auf diese Strukturen zugreifen dürfen, noch ist der Standort eines anderen TLS-Segments als das Hauptteil ausführbarer Teil des ABI. In beiden Varianten I und II ist es sinnvoll, implementierungsinterne Informationen für den Thread in einem festen Abstand vom "Thread Pointer Register" zu speichern, und zwar auf eine sichere Art und Weise, das TLS-Segment nicht zu überlappen.

Verwandte Themen