2017-02-09 7 views
1

thread_local data ist ein Wert, der von der C++ - Laufzeit initialisiert wird, wobei die Daten aus den Abschnitten ".tdata/.tbss" (unter der Annahme von ELF abi) verwendet werden. Es scheint daher machbar, ein weiteres Paar von Abschnitten hinzuzufügen, die ".tinit"/". Tfini" genannt werden. Dieser Abschnitt könnte Code enthalten, der immer dann ausgeführt wird, wenn untergeordnete Threads gestartet und beendet werden und nachdem der lokale Thread-Speicher eingerichtet wurde (analog zu ".init"/".fini" -Abschnitten, die am Haupt-Thread-Start/Ende ausgeführt werden). Die Konstruktoren und Destruktoren für lokale Objekte, die nicht trivial sind, können dann von den Linkern in diese gruppiert werden.Initialisierung von nicht-trivialen thread_local-Variablen: Warum nur auf Anfrage?

Die Funktionalität von angenommenen ".tfini" Abschnitt wird derzeit von dynamischen Maschinen von "__cxa_thread_atexit" und Freunden (bei beträchtlichen Aufwand) behandelt. Jedoch wird von der Laufzeitumgebung keine dedizierte Instrumentierung für den "automatischen" Thread-Initialisierungscode bereitgestellt: Für alle nicht-trivialen lokalen Thread-Objekte muss der Compiler Schutzvariablen ausgeben, die bei jedem Zugriff überprüft werden.

Die Frage ist also: Wurde der oben skizzierte Ansatz von den Thread-Local-Data-Feature-Architekten ausgewertet? Welche Nachteile wurden festgestellt (abgesehen von Änderungen in der Semantik der Thread-Ausführung, die eindeutig nicht in Stein gemeißelt sind)?

+0

Nur neugierig, war die Antwort hilfreich? – yugr

+0

Nein, war es nicht. – oakad

+0

Ich schlage vor, du stellst dann klärende Fragen. – yugr

Antwort

0

Also, wie Sie hingewiesen haben, ELF Thread lokale Variablen (d. H. Mit __thread markiert) müssen mit konstanten Ausdrücken initialisiert werden. Dies liegt an einer Designentscheidung über die Implementierung.

Insight 1: Die meisten Threads greifen nicht auf alle Thread-lokalen Daten zu, die in der Anwendung verfügbar sind. Stellen Sie sich eine Berechnungsbibliothek vor, die mehrere Threads startet, um die Ausführung zu beschleunigen - diese Threads greifen höchstwahrscheinlich auf den internen Thread dieser Bibliothek zu - Locals, nicht Thread-Locals aus anderen Bibliotheken. Deshalb weist Glibc lokalen Thread-Speicher auf Anfrage zu, d. Code greift zuerst über __tls_get_addr (einige TLS-Blöcke werden beim Start zugeordnet, aber das ist mehr eine Optimierung als Voraussetzung).

Insight 2: ermöglicht beliebige Konstrukteuren bei TLS Zuweisung (dh innerhalb __tls_get_addr) zu arbeiten wäre eine riesige Quelle Deadlocks Rennen als __tls_get_addr kann an beliebiger Stelle im Code aufgerufen werden (sobald der erste Hinweis auf TLS-Variable ist gemacht).

Ich glaube, das ist, was Designer dazu veranlasste, dynamische Initialisierung von TLS-Variablen insgesamt zu verbieten.

+0

Haben Sie eine Referenz für "verbieten dynamische Initialisierung insgesamt"? Dynamische Thread-Initialisierungsabschnitte wurden vor einigen Jahren vom C++ - Komitee diskutiert; Ich bin interessiert, den Link zu dem Ergebnis dieser Diskussion zu sehen. Außerdem ist Ihr "Einblick 1" meistens falsch, wenn es sich um echte Apps handelt (erwägen Sie Logging- und Metrik-Bibliotheken, Random-State/Crypto-Provider und ausgefallene gleichzeitige Datenstrukturen). – oakad

+0

@oakad Eigentlich dachte ich, wir diskutieren nur GCC TLS. Constant Initializers Anforderung wird in [ihren Dokumenten] (https://gcc.gnu.org/onlinedocs/gcc-3.3/gcc/Thread-Local.html) erwähnt. Beachten Sie, dass GNU TLS C++ TLS vor ca. 7 Jahren vorausgeht. – yugr

Verwandte Themen