Comprendre les conventions du code source de glibc

J’ai consulté une partie du code source de glibc, en particulier le code nptl, et je l’ai trouvé un peu difficile à comprendre car il semble avoir des conventions que je ne connais pas bien.

Par exemple, je cherchais un très petit fichier pthread_equal.c et il y avait quelques points sur lesquels j’avais des questions:

22 int 23 __pthread_equal (thread1, thread2) 24 pthread_t thread1; 25 pthread_t thread2; 26 { 27 return thread1 == thread2; 28 } 29 strong_alias (__pthread_equal, pthread_equal) 
  1. La déclaration aux lignes 22 et 23 ressemble à quelque chose que je comprends. Il a un type de retour de int __pthread_equal nom de la fonction __pthread_equal et de la liste de parameters (thread1, thread2) . Mais quelles sont les déclarations sur les lignes 24 pthread_t thread1; et 25 pthread_t thread2; pour? On dirait que celles-ci sont déclarées en tant que variables globales mais je ne comprends pas l’objective. J’ai vu ce modèle dans de nombreux fichiers du répertoire nptl et je n’ai pas réussi à comprendre pourquoi cela est fait.

  2. Qu’est-ce que strong_alias ? Une recherche rapide sur Google contient des exemples d’utilisation, mais je n’ai trouvé de lien vers aucune documentation.

  3. Quelle est la raison de préfacer certains noms avec deux __ soulignement __ et certains avec un trait de soulignement _ . La plupart du code que j’ai vu utilise les deux traits de soulignement, mais je pense avoir déjà vu des endroits où un trait de soulignement est utilisé. Par exemple dans pthreadP.h

     556 /* Old cleanup interfaces, still used in libc.so. */ 557 extern void _pthread_cleanup_push (struct _pthread_cleanup_buffer *buffer, 558 void (*routine) (void *), void *arg); 559 extern void _pthread_cleanup_pop (struct _pthread_cleanup_buffer *buffer, 560 int execute); 561 extern void _pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *buffer, 562 void (*routine) (void *), void *arg); 563 extern void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *buffer, 564 int execute); 

Certes, ce code est préfacé par un commentaire qui dit “anciennes interfaces de nettoyage”, mais de toute façon, je suis curieux de savoir la différence et pourquoi parfois un soulignement est utilisé et parfois deux soulignements sont utilisés.

Toute information concernant ces questions est appréciée.

La fonction est écrite sans nécessiter un compilateur conforme à C89; cela fonctionnera aussi avec les anciens compilateurs. C’est une définition de fonction non prototype.

 int /* Return type */ function(arg1, arg2) /* Function name and argument names (but no types) */ int arg1; /* Type of arg1 */ char *arg2; /* Type of arg2 */ { /* Body of function */ } 

Notez que les définitions des arguments ne doivent pas forcément être dans la même séquence que dans la ligne de fonction (j’ai dû convertir le code de cette notation ‘K & R’ en notation prototype où elles étaient hors d’usage!). Notez également qu’il était possible d’écrire simplement:

 main(argc, argv) char **argv; { ... } 

Le type implicite pour argc était int puisqu’il n’était pas spécifié comme quoi que ce soit d’autre. Il est peu probable que le code glib tire parti de cette licence. De même, le type de retour de main() était int car aucun autre type n’a été donné.

strong_alias est lié à la dissimulation et à l’exposition de symboles dans des bibliothèques partagées. Je ne l’ai pas utilisé, donc je ne suis pas sûr de toutes les ramifications, mais je pense que cela signifie que __pthread_equal() est un autre nom de la fonction pthread_equal() .


Une partie du raisonnement derrière le nom __pthread_equal() est que les noms commençant par un trait de soulignement suivi d’une lettre majuscule ou d’un autre trait de soulignement sont «réservés à la mise en œuvre» par la norme C. Des noms tels que ‘pthread_equal ()’ sont dans l’espace de noms des utilisateurs selon le standard C.

ISO / IEC 9899: 1990 (la norme C99) dit:

7.1.3 Identifiants réservés

Chaque en-tête déclare ou définit tous les identificateurs répertoriés dans sa sous-clause associée et éventuellement identifie ou définit les identificateurs répertoriés dans sa sous-clause d’instructions de bibliothèque future associée et les identificateurs qui sont toujours réservés pour toute utilisation ou pour être utilisés comme identificateurs de scope de fichier.

– Tous les identificateurs commençant par un trait de soulignement et une lettre majuscule ou un autre trait de soulignement sont toujours réservés pour toute utilisation.

– Tous les identificateurs commençant par un trait de soulignement sont toujours réservés à une utilisation en tant qu’identificateurs avec une étendue de fichier dans les espaces de nom de balise et ordinaire.

– Chaque nom de macro dans l’un des sous-paragraphes suivants (y compris les instructions futures de la bibliothèque) est réservé pour être utilisé comme spécifié si l’un des en-têtes associés est inclus. sauf indication explicite contraire (voir 7.1.4).

– Tous les identifiants avec une liaison externe dans l’un des sous-paragraphes suivants (y compris les instructions futures de la bibliothèque) sont toujours réservés à une utilisation en tant qu’identificateurs avec une liaison externe. 154)

– Chaque identifiant avec une étendue de fichier répertoriée dans l’un des sous-paragraphes suivants (y compris les instructions futures de la bibliothèque) est réservé à l’utilisation en tant que nom de macro et en tant qu’identifiant avec une étendue de fichier dans le même espace de nom si l’un des en-têtes associés est inclus.

Aucun autre identifiant n’est réservé. Si le programme déclare ou définit un identifiant dans un contexte dans lequel il est réservé (autre que celui autorisé par 7.1.4), ou définit un identifiant réservé en tant que nom de macro, le comportement est indéfini.

154) La liste des identificateurs réservés avec une liaison externe comprend errno , math_errhandling , setjmp et va_end .

  1. Écriture ancienne.
  2. Pour garantir le type de __pthread_equal , pthread_equal identique.
  3. Distinguer les noms de variables et distinguer les zones principales des utilisateurs.