2017-06-23 8 views
0

Étant donné le code suivantQuand la routine transmise à pthread_create démarre-t-elle?

#include <pthread.h> 

void *pt_routine(void *arg) 
{ 
    pthread_t *tid; 
    tid = (pthread_t *) arg; 
    /* do something with tid , say printf?*/ 
    /* 
    printf("The thread ID is %lu\n", *tid); 
    */ 
    return NULL; 
} 

int main(int argc, char **argv) 
{ 
    int rc; 
    pthread_t tid; 
    rc = pthread_create(&tid, NULL, pt_routine, &tid); 
    if (rc) 
    { 
     return 1; 
    } 
    printf("The new thread is %lu\n", tid); 
    pthread_join(tid, NULL); 
    return 0; 
} 

la routine peut avoir toujours le droit tid?

Bien sûr, je pourrais utiliser pthread pour récupérer l'auto-identification mais je me demande juste quand la routine fonctionne.

+0

"Quand la routine transmise à pthread_create démarre-t-elle?", Après l'appel de 'pthread_create()'? Votre question n'est pas claire. "Est-ce que la routine peut TOUJOURS obtenir le bon tid?" Que voulez-vous dire ? – Stargateur

+1

Vous passez '& tid' comme premier argument de' pthread_create' (l'endroit où 'pthread_create' devrait stocker l'ID du nouveau thread) et le quatrième argument de' pthread_create' (un argument à passer dans 'pt_routine') . Cela * sonne * comme si vous demandiez s'il est possible que 'pt_routine' s'exécute et déréférence son' arg' avant que 'pthread_create' ait stocké l'ID du thread à cette adresse. Est-ce exact? – Wyzard

Répondre

3

Eh bien, il y a en fait 2 questions:

  • thread qui exécutera la première
  • sera l'ID du sujet sera sauvé avant les mises en chantier de fil.

Cette réponse concerne Linux, car je n'ai pas d'autres plateformes disponibles. La réponse à la première question se trouve in the manuals:

À moins en temps réel politiques de planification sont en cours d'un emploi, après un appel à pthread_create(), il est indéterminée qui thread l'appelant ou le nouveau thread volonté Ensuite, exécutez.

Il est donc clair que dans votre cas, il est indéterminé quel thread sera réellement exécuté en premier. Maintenant, une autre question est comment est pthread_create mis en œuvre - si elle pourrait en quelque sorte créer un thread dormant, en stockant son identifiant d'abord, puis plus tard le démarrer?

Eh bien, Linux crée un nouveau thread en utilisant l'appel système clone:

clone(child_stack=0x7f7b35031ff0, 
     flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM 
      |CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, 
     parent_tidptr=0x7f7b350329d0, 
     tls=0x7f7b35032700, 
     child_tidptr=0x7f7b350329d0) = 24009 

Maintenant, il semble que l'ID de fil est stocké avec un pointeur de l'appel clone, mais il semble clair que child_tidptr n » t se référer à l'adresse detid, comme si je l'imprime, l'adresse est différente; c'est une variable interne dans la bibliothèque pthread; et tid serait mis à jour après l'appel système clone renvoie dans le thread parent.

Et en effet, pthread_self dit le texte suivant:

L'ID du thread retourné par pthread_self() est pas la même chose que l'ID du thread noyau renvoyé par un appel à gettid(2).

Cela confirme que les ids de fil du noyau sont distincts de pthread_t s

Ainsi, en plus de cela pas pris en charge par le POSIX spec, il n'y a aucune garantie sur la plate-forme Linux dans la pratique - la tid sera doit être défini dans le thread parent après clone renvoie, sinon le parent ne connaîtrait pas immédiatement l'ID de thread de l'enfant - mais cela signifie également que si l'enfant est le premier à exécuter après le retour, alors le l'ID de thread peut ne pas être défini pour le moment.

+0

Merci beaucoup! Très clair et utile! –

2

pt_thread() va commencer l'exécution à un moment arbitraire après pthread_create() est appelé - et comprend qu'il pourrait commencer à courir avant pthread_create() retourne au code d'appel. Et il n'y a aucune garantie que l'implémentation pthread_create() mettra à jour la variable tid avant que le thread démarre l'exécution.

Ainsi, rien dans votre code ne garantit que pt_routine() lira la valeur tid correctement. Vous devrez utiliser une sorte de synchronisation pour vous assurer que cela se produit correctement sans une course de données. Ou vous pourriez avoir le fil appelez pthread_self().

Voir la section « Utilisation de l'application » de the POSIX spec for pthread_create():

Il n'y a pas d'exigence sur la mise en œuvre que l'ID du fil créé sera disponible avant que le thread nouvellement créé commence à exécuter. Le thread appelant peut obtenir l'ID du fil créé par la valeur de retour de la fonction pthread_create(), et le fil nouvellement créé peut obtenir son ID par un appel à pthread_self

+0

Un autre [quote] (http://man7.org/linux/man-pages/man3/pthread_create.3.html) de la page de manuel linux: "Voir pthread_self (3) pour plus d'informations sur l'ID de thread retourné dans * thread Avec pthread_create(), sauf si des stratégies d'ordonnancement en temps réel sont utilisées, après un appel à pthread_create(), il est indéterminé quel thread (l'appelant ou le nouveau thread) va s'exécuter. " – Stargateur