2009-02-17 4 views
33

Ich habe eine pthread_t, und ich möchte seine CPU-Affinität ändern. Das Problem ist, dass ich glibc 2.3.2 verwende, das pthread_setaffinity_np() nicht hat. Das ist jedoch in Ordnung, denn pthread_setaffinity_np() ist selbst ein Wrapper von sched_setaffinity(), der durch Übergeben einer Thread-ID anstelle einer Prozess-ID aufgerufen werden kann, um die Affinität für einen beliebigen Thread festzulegen.Wie bekomme ich eine Thread-ID von einem beliebigen pthread_t?

ABER ... Die Thread-ID, mit der sched_setaffinity arbeiten kann, ist eine Betriebssystem-Thread-ID, die Sie vom Systemruf gettid() erhalten können. Dies unterscheidet sich vom opaken Typ pthread_t, und gettid() gibt nur die Thread-ID des aktuellen Threads zurück. Ich muss in der Lage sein, die CPU-Affinität eines beliebigen Threads festzulegen.

Leider kann ich nicht auf die privaten Teile des pthread zugreifen, was mir erlauben würde, die Thread-ID zu stehlen, indem ich ein pthread_t in ein struct pthread * umwandelt. Umso besser, schätze ich, da man sich auf private Implementierungen verlassen muss, um nach weiteren Problemen zu fragen: mehr.

Ich habe auch auf der pthread_getunique_np Funktion gelesen, aber dies gibt eine "eindeutige Integral-Kennung" - die ich glaube nicht, ist in irgendeiner Form oder Form entspricht einer OS-Thread-ID.

Daher die Frage: Wie bekomme ich eine Thread-ID aus einem beliebigen pthread_t?

Antwort

31

Da pthread s nicht mit Linux-Threads (oder überhaupt Kernel-Threads) implementiert werden müssen und einige Implementierungen vollständig auf Benutzerebene oder gemischt sind, bietet die Schnittstelle keine Funktionen für den Zugriff auf diese Implementierungsdetails, da diese nicht portierbar wären (selbst unter Implementierungen von pthread unter Linux). Thread-Bibliotheken, die diese verwenden, könnten dies als Erweiterung bereitstellen, aber das scheint es nicht zu geben.

Neben dem Zugriff auf interne Datenstrukturen der Threading-Bibliothek (die Sie verständlicherweise nicht wollen, obwohl Ihr Code mit Ihren Annahmen über Prozessoraffinität und Linux-Thread-IDs sowieso nicht portabel ist), können Sie möglicherweise eine wenn Sie den Code bei der Erstellung Trick, zu steuern, die schafft die Fäden:

geben pthread_create() einen Eintrag Funktion, die gettid() (die durch die Art und Weise ruft Sie wahrscheinlich zu tun haben die syscall Makro direkt verwenden, da es nicht immer exportiert von libc), speichert das Ergebnis irgendwo und ruft dann die ursprüngliche Eintragsfunktion auf. Wenn Sie mehrere Threads mit derselben Eintragsfunktion haben, können Sie einen inkrementierten Zeiger in ein Array im -Argument an pthread_create übergeben, das dann an die Eintragsfunktion übergeben wird, die Sie zum Speichern der Thread-ID erstellt haben. Speichern Sie den Rückgabewert pthread_t von pthread_create in der gleichen Reihenfolge, und dann können Sie die Linux-Thread-IDs aller erstellten Threads mit ihrem pthread_t-Wert nachschlagen.

Ob dieser Trick es wert ist, hängt davon ab, wie wichtig es ist, in Ihrem Fall die CPU-Affinität einzustellen, statt auf interne Strukturen der Thread-Bibliothek zuzugreifen oder abhängig von einer Thread-Bibliothek, die pthread_setaffinity_np bereitstellt.

1

Ich würde eine einfache Abhilfe mit einem gemeinsamen int-Array vorschlagen, wo Sie die Thread-ID aus den Threads schreiben könnten, um später darauf zuzugreifen.

Hoffe, dass hilft.

+1

Es ist keine mmap erforderlich, Threads teilen sich trotzdem den gleichen Speicher. – raimue

+0

Guter Punkt :) gosh das ist so offensichtlich ...;) –

2
pthread_t pthread_self() 

dieser Strom pthread_t zurückkehren, die Thread-ID ist, können Sie wandeln es "unsigned int" zu geben,

+2

Eigentlich 'unsigned long int'. – JumpAlways

+0

'pthread_t me();' => undefinierter Verweis auf 'me()'. – Eric

12

Eigentlich pthread_self kehrt pthread_t und kein Integer-Thread-ID Sie mit, die folgenden Helfer arbeiten können Funktion wird Ihnen das auf portable Weise über verschiedene POSIX-Systeme hinweg ermöglichen.

uint64_t gettid() { 
    pthread_t ptid = pthread_self(); 
    uint64_t threadId = 0; 
    memcpy(&threadId, &ptid, std::min(sizeof(threadId), sizeof(ptid))); 
    return threadId; 
} 
+0

'pthread_t tid = pthread_self();' funktioniert auf dem Haupt-Thread, aber nicht auf einem anderen? Ich habe meine exe crash aufrufen von "__start_routine" nach dem Aufruf von 'pthread_create'. – Eric

0

In glibc 2,24 die pthread_t zurückgegeben ist nur der Zeiger auf einem opaken struct pthread. Sie können die Definition in nptl/descr.h nachschlagen.