2009-02-17 5 views
33

J'ai un pthread_t, et je voudrais changer son affinité CPU. Le problème est que j'utilise la glibc 2.3.2, qui n'a pas pthread_setaffinity_np(). Cela est correct, car pthread_setaffinity_np() est lui-même un wrapper de sched_setaffinity(), qui peut être appelé en passant un ID de thread au lieu d'un ID de processus pour définir l'affinité pour un thread arbitraire.Comment puis-je obtenir un ID de thread à partir d'un pthread_t arbitraire?

BUT ... L'ID de thread avec lequel sched_setaffinity peut fonctionner est un ID de thread OS, le type que vous pouvez obtenir à partir de l'appel système gettid(). Ceci est différent du type opaque pthread_t, et gettid() ne retournera que l'identificateur de thread du thread en cours . J'ai besoin de pouvoir définir l'affinité CPU d'un thread arbitraire.

Malheureusement, je ne peux pas accéder aux parties privées de pthread, ce qui me permettrait de voler l'identifiant de thread en lançant un pthread_t à struct pthread *. Tant mieux, je suppose, puisque s'appuyer sur des implémentations privées demande même plus de problèmes. J'ai également lu sur la fonction pthread_getunique_np, mais cela renvoie un "identifiant unique unique" - qui, je ne crois pas est en aucune façon forme ou forme équivalente à un ID de thread OS.

Par conséquent, la question: Comment puis-je obtenir un ID de thread à partir d'un pthread_t arbitraire?

Répondre

31

Puisque pthread s n'ont pas besoin d'être implémentés avec des threads Linux (ou des threads du noyau, d'ailleurs), et que certaines implémentations sont entièrement au niveau utilisateur ou mixtes, l'interface pthread ne fournit pas de fonctions pour y accéder détails de mise en œuvre, car ceux-ci ne seraient pas portables (même à travers les implémentations de pthread sur Linux). Les bibliothèques de threads qui utilisent celles-ci pourraient fournir cela comme une extension, mais cela ne semble pas être le cas. Outre l'accès aux structures de données internes de la bibliothèque de threads (ce que vous ne voulez pas, bien que vos suppositions sur l'affinité du processeur et les identificateurs de threads Linux, votre code ne sera pas portable), vous pourrez peut-être jouer un trick au moment de la création, si vous contrôlez le code qui crée les fils:

Donne pthread_create() une fonction d'entrée qui appelle gettid() (qui, par la façon dont vous êtes susceptible d'avoir à faire à l'aide du syscall macro directement car il est pas toujours exporté par libc), stocke le résultat quelque part, puis appelle la fonction d'entrée d'origine. Si vous avez plusieurs threads avec la même fonction d'entrée, vous pouvez passer un pointeur incrémenté dans un tableau dans l'argument arg à pthread_create, qui sera ensuite transmis à la fonction d'entrée que vous avez créée pour stocker l'ID de thread. Enregistrez la valeur de retour pthread_t. Dans le même ordre, vous pouvez rechercher les ID de threads Linux de tous les threads que vous avez créés, en fonction de leur valeur pthread_t. La valeur de cette astuce dépend de l'importance de la configuration de l'affinité de la CPU dans votre cas, et non de l'accès aux structures internes de la bibliothèque de threads ou d'une bibliothèque de threads fournissant pthread_setaffinity_np.

1

Je suggère une solution de contournement simple avec un tableau int partagé où vous pouvez écrire l'ID de thread à partir des threads pour y accéder plus tard.

Espérons que ça aide.

+1

Il n'y a pas besoin de mmap, les threads partagent quand même la même mémoire. – raimue

+0

Bon point :) ça alors c'est si évident ...;) –

2
pthread_t pthread_self() 

ce retour pthread_t actuel, qui est id fil, vous pouvez le convertir en type « unsigned int »,

+2

En fait 'unsigned long int'. – JumpAlways

+0

'pthread_t me();' => référence non définie à 'me()'. – Eric

12

En fait pthread_self retours pthread_t et non un identifiant de fil entier vous pouvez travailler avec, l'aide suivante La fonction vous permettra de l'utiliser de manière portable sur différents systèmes POSIX.

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();' fonctionne sur le thread principal, mais pas sur un autre? J'ai mon crash exe appelant cela de '__start_routine' après avoir appelé' pthread_create'. – Eric

0

Dans glibc 2.24 le retour pthread_t est juste le pointeur sur un struct pthread opaque. Vous pouvez rechercher la définition dans nptl/descr.h.

Questions connexes