Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding glibc source code conventions

Tags:

c

pthreads

libc

I've been looking at some of the source code for glibc, in particular the nptl code, and I've found it a little bit hard to understand since it seems to have conventions that I'm not familiar with.

For example I was looking at a very small file pthread_equal.c and there are a few things that I had questions about:

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. The declaration on lines 22 and 23 looks like something I understand. It has a return type of int then the function name __pthread_equal and the parameter list (thread1, thread2). But what are the declarations on lines 24 pthread_t thread1; and 25 pthread_t thread2; for? It looks like these are being declared as global variables but I don't understand the purpose. I've seen this pattern in many files in the nptl directory and haven't been able to figure out why this is done.

  2. What is strong_alias? A quick Google search has examples of this being used but I did not find a link to any documentation.

  3. What is the reason for prefacing some names with two underscores __ and some with one underscore _. Most of the code I've seen uses the two underscores but I think I have seen some places where one underscore is used. For instance in 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);
    

Admittedly that code is prefaced with a comment that says "old cleanup interfaces" but either way I'm curious about the difference and why sometimes one underscore is used and sometimes two underscores are used.

Any information regarding these questions is appreciated.

like image 637
Gabriel Southern Avatar asked Mar 14 '12 02:03

Gabriel Southern


1 Answers

The function is written without requiring a C89 compliant compiler; it will work with older compilers too. That is a non-prototype function definition.

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 */
}

Note that the definitions of the arguments do not have to be in the same sequence as in the function line (I've had to convert code from this 'K&R' notation to prototype notation where they were out of order!). Also note that it used to be possible to simply write:

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

The implied type for argc was int since it wasn't specified as anything else. It is unlikely that the glib code takes advantage of that licence. Similarly, the return type of main() was int because no other type was given.

The strong_alias is related to hiding and exposing symbols in shared libraries. I've not used it, so I'm not sure of all the ramifications, but I believe it means that __pthread_equal() is another name for the pthread_equal() function.


One part of the reasoning behind the __pthread_equal() name is that names starting with an underscore followed by an upper-case letter or another underscore are 'reserved to the implementation' by the C Standard. Names such as 'pthread_equal()' are in the users' name space according to the C standard.

ISO/IEC 9899:1990 (the C99 standard) says:

7.1.3 Reserved identifiers

Each header declares or defines all identifiers listed in its associated subclause, and optionally declares or defines identifiers listed in its associated future library directions subclause and identifiers which are always reserved either for any use or for use as file scope identifiers.

— All identifiers that begin with an underscore and either an uppercase letter or another underscore are always reserved for any use.

— All identifiers that begin with an underscore are always reserved for use as identifiers with file scope in both the ordinary and tag name spaces.

— Each macro name in any of the following subclauses (including the future library directions) is reserved for use as specified if any of its associated headers is included; unless explicitly stated otherwise (see 7.1.4).

— All identifiers with external linkage in any of the following subclauses (including the future library directions) are always reserved for use as identifiers with external linkage.154)

— Each identifier with file scope listed in any of the following subclauses (including the future library directions) is reserved for use as a macro name and as an identifier with file scope in the same name space if any of its associated headers is included.

No other identifiers are reserved. If the program declares or defines an identifier in a context in which it is reserved (other than as allowed by 7.1.4), or defines a reserved identifier as a macro name, the behavior is undefined.

154) The list of reserved identifiers with external linkage includes errno, math_errhandling, setjmp, and va_end.

like image 76
Jonathan Leffler Avatar answered Oct 19 '22 04:10

Jonathan Leffler