-1

The structure of pthread is as follows. It is taken from https://stuff.mit.edu/afs/sipb/project/pthreads/include/pthread.h

    struct pthread {
    struct machdep_pthread  machdep_data;
    enum pthread_state      state;
    pthread_attr_t          attr;

    /* Signal interface */
    sigset_t                sigmask;
    sigset_t                sigpending;

    /* Time until timeout */
    struct timespec         wakeup_time;

    /* Cleanup handlers Link List */
    struct pthread_cleanup  *cleanup;

    /* Join queue for waiting threads */
    struct pthread_queue    join_queue;

    /* Queue thread is waiting on, (mutexes, cond. etc.) */
    struct pthread_queue    *queue;

    /*
     * Thread implementations are just multiple queue type implemenations,
     * Below are the various link lists currently necessary
     * It is possible for a thread to be on multiple, or even all the
     * queues at once, much care must be taken during queue manipulation.
     *
     * The pthread structure must be locked before you can even look at
     * the link lists.
     */ 

    struct pthread          *pll;       /* ALL threads, in any state */
    /* struct pthread       *rll;        Current run queue, before resced */
    struct pthread          *sll;       /* For sleeping threads */
    struct pthread          *next;      /* Standard for mutexes, etc ... */
    /* struct pthread           *fd_next;    For kernel fd operations */

    int                     fd;         /* Used when thread waiting on fd */

    semaphore               lock;

    /* Data that doesn't need to be locked */
    void                    *ret;
    int                     error;
    const void              **specific_data;
};

    typedef struct pthread *        pthread_t;

Now let's see the following code to print the ID of the thread:

#include <stdio.h> 
#include <stdlib.h> 
#include <pthread.h> 
void* calls(void* ptr) 
{ 
    // using pthread_self() get current thread id 
    printf("In function \nthread id = %ld\n", pthread_self()); 
    pthread_exit(NULL); 
    return NULL; 
} 

int main() 
{ 
    pthread_t thread; // declare thread 
    pthread_create(&thread, NULL, calls, NULL); 
    printf("In main \nthread id = %ld\n", thread);  
    pthread_join(thread, NULL);  
    return 0; 
} 

Output in my system is:

In main 
thread id = 140289852200704
In function 
thread id = 140289852200704

From pthread.h file (above), pthread is a structure, thread in the code is a pointer to the structure pthread (since pthread_t is typdef struct pthread*). Why does printing this pointer gives us the thread ID?

Krishna Kanth Yenumula
  • 2,533
  • 2
  • 14
  • 26
  • You may want to have at look at this: https://stackoverflow.com/questions/33285562/why-and-in-what-sense-is-pthread-t-an-opaque-type – Matteo Pacini May 23 '20 at 00:34
  • 1
    Why not? Using the base address of a descriptor struct is a very common means of passing around pseudo-opaque tokens for complex objects. – Martin James May 23 '20 at 04:28
  • @Martin James Can you please explain more?? Please provide a link. – Krishna Kanth Yenumula May 23 '20 at 04:50
  • A thread ID is *not* a number. You can write code to pass a thread ID as a number and some number will be printed. But that number is in no way the thread ID. A thread ID is a value of a `pthread_t` type. They cannot be printed. They can't even be directly [compared](https://pubs.opengroup.org/onlinepubs/009695399/functions/pthread_equal.html). – David Schwartz May 23 '20 at 05:25
  • @KrishnaKanthYenumula link? Just think about it - you have a complex subsystem of data/code/threads/whatever that users need access to, a filesystem, a server, a threadpool, whatever. Nearly always, there will be a root struct/object that contains management data, function/method pointers/references etc, a root that was dynamically allocated when the system was created and so has a unique base address. That is your token, and other system elements need only that token to access the services of the subsystem. – Martin James May 23 '20 at 08:11

1 Answers1

2

From pthread.h file (above), pthread is a structure, thread in the code is a pointer to the structure pthread (since pthread_t is typdef struct pthread*).

To be clear: in that implementation, pthread_t is a pointer-to-structure type. I imagine that's very common for pthreads implementations, but do be careful to avoid mistaking the details of a particular implementation for a general characteristic of the specifications or of all implementations. For example, it could just as well be an integer index in some other implementation, among various other possibilities.

Why does printing this pointer gives us the thread ID?

Because it is the thread ID. And because you're lucky that the undefined behavior arising from printing it with a %d formatting directive manifested the same way in both places.

You probably have done yourself a disservice by looking under the covers at the definition of your implementation's pthread_t. You don't need to know those details to use pthreads, and in fact they do not help you in the slightest. The type is meant to be treated as opaque.

All you really need to understand to answer the question is that the value written into variable thread by pthread_create() is the created thread's ID, and the value returned by pthread_self() is the calling thread's thread ID. Naturally, each mechanism for obtaining a thread ID yields the same ID for the same thread.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157