I'm trying to implement pthread_self() in C but I'm confused on what exactly it does. I'm aware that it returns the thread ID but is that ID a memory location because it returns a pthread_t which I'm not sure how to interpret. Additionally, how would I go about retrieving the id of the thread, do I just create a new thread and return it?
pthread_self() returns the ID of the thread. Please check man pages for pthread_self and pthread_create.
man 3 pthread_self
man 3 pthread_create
For pthread_create(), the first argument is of type pthread_t. It is assigned the ID of the newly created thread. This ID is used to identify the thread for other pthread functions. The abstract type of pthread_t is implementation dependent.
Before returning, a successful call to pthread_create() stores the ID of the new thread in the buffer pointed to by thread; this identifier is used to refer to the thread in subsequent calls to other pthread functions.
pthread_self returns the same ID, what pthread_create stores in the first argument "thread"
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
pthread_t pthread_self(void);
In my system pthread_t type is "unsigned long int"
/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h:typedef unsigned long int pthread_t;
In the following example, the value returned by pthread_self() and th1 are same.
// main function:
pthread_t th1;
if(rc1 = pthread_create(&th1, NULL, &functionC1, NULL))
{
printf("Thread creation failed, return code %d, errno %d", rc1, errno);
}
printf("Printing thread id %lu\n", th1);
// Thread function:
void *functionC1(void *)
{
printf("In thread function Printing thread id %lu\n", pthread_self());
}
Output:
Printing thread id 140429554910976
In thread function Printing thread id 140429554910976
Please check blog Tech Easy for more information on threads.
Related
When creating an pthread, pthread_create() is used. First parameter of this function is thread_id.
I tried to access this value pthread_self() but this gives something very big and not the numbers I gave while creating.
Is there a way to access this value?
for(int i = 0; i < necessaryThreadCount; i++){
pthread_create(&threadIDs[i], NULL, theFunction, (void*)&requiredStructre[i]);
}
my question is, how can i access the value of given threadID inside theFunction?
Solution:
I just added another variable to the struct I pass as parameter.
First parameter is pointer to thread_id which you need to declare first.
ID will get assigned after you create thread using pthread_create(). refer the below:
int main()
{
pthread_t thread; // declare thread
pthread_create(&thread, NULL, func, NULL);
printf("the thread id = %d\n", thread);
}
thread_id is for the new thread that is created. if you execute pthread_self() in the current thread it returns a different value from the newly created thread.
Hope the below example may help you to understand thread id creation:
[NOTE: not a good idea to have global pthread_t declared]
Example:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
pthread_t ctid;
void* thread_function(void* arg)
{
printf("Inside the thread\n");
printf("ctid: %ld, self: %ld", ctid, pthread_self());
// exit the current thread
pthread_exit(NULL);
}
void createthread()
{
pthread_create(&ctid, NULL, &thread_function, NULL);
printf("This line may be printed"
" before thread terminates\n");
// Waiting for the created thread to terminate
pthread_join(ctid, NULL);
pthread_exit(NULL);
}
// Driver code
int main()
{
createthread();
return 0;
}
The signature of pthread_create(3) is:
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
What are the requirements on the storage duration of the pthread_t *thread argument? The man page for pthread_create says:
Before returning, a successful call to pthread_create() stores the ID of the new thread in the buffer pointed to by thread;
But it's not clear if it means that it stores the value there so that the caller can examine it, or if it uses that buffer to store the value (implying that the buffer needs to stay usable for the whole lifetime of the child thread).
Similarly, pthread_self says it returns
the same value that is returned in *thread in the pthread_create(3) call that created this thread.
but it's not clear if it means that it returns the value stored in *thread or a value equal to what was returned in *thread.
Concretely, I'm wondering if it's legal to have something like:
void make_thread(void) {
pthread_t tid;
return pthread_create(&tid, NULL, some_fn, NULL);
}
or if tid needs to be malloc'd. When I put tid on the stack, I get a bunch of errors in valgrind related to _Unwind_ForcedUnwind, which makes me suspect that *thread needs to remain valid for the lifetime of the child thread.
The thread ID is returned for your own use. You don't need to store it if you're going to detach the thread or the thread is going to detach itself.
void make_thread(void) {
pthread_t tid;
return pthread_create(&tid, NULL, some_fn, NULL);
}
This is kind of odd. You can't join the thread, because you didn't keep its ID. And you didn't detach it. I suppose this could be fine if the thread detaches itself, but that's an odd way to do things.
I've been reading and learning about POSIX threads, and tried to write some simple codes to understand it better.
#include <stdio.h> /* standard I/O routines */
#include <pthread.h> /* pthread functions and data structures */
/* function to be executed by the new thread */
void* PrintHello(void* data)
{
pthread_t tid = (pthread_t)data;
printf("Hello from new thread %d - got %d\n", pthread_self(), tid);
pthread_exit(NULL); /* terminate the thread */
}
int main(int argc, char* argv[])
{
int rc; /* return value */
pthread_t thread_id;
int tid;
thread_id = pthread_self();
printf("FLAG = %d ", thread_id);
/* create a new thread that will execute 'PrintHello' */
rc = pthread_create(&thread_id, NULL, PrintHello, (void*)thread_id);
if(rc) /* could not create thread */
{
printf("\n ERROR: return code from pthread_create is %u \n", rc);
exit(1);
}
printf("\n Created new thread (%d) ... \n", thread_id);
pthread_exit(NULL); /* terminate the thread */
}
For this code I get the following output:
FLAG = 363480832
Created new thread (355198720) ...
Hello from new thread 355198720 - got 363480832
What is bothering me is why thread_id which is 363480832, becomes 355198720, same as thread_id of a function that was called from main (PrintHello()). I assumed that thread id doesn't change throughout the program execution. Or is it something inside the function that changes it?
If you're doing anything with a pthread_t other than passing it to a function that takes one, you're doing something wrong. Only the pthreads API knows how to use a pthread_t correctly. They can have any internal structure that's convenient for the implementation.
Being a C language construct, pthread_t behaves more like char *. The necessary language constructs to make it behave like std::string don't exist. So you have to treat it like char *.
A char * contains a string somehow, but you have to understand its implementation to get that value out. Consider:
char *j = "hello";
char *k = strdup (j);
if (j == k)
printf ("This won't happen\n");
printf ("%d\n", j);
printf ("%d\n", k); // these won't be equal
You can't compare char *'s with == to see if they refer to the same string. And if you print out j and k, you'll get different values.
Similarly, a pthread_t refers to one particular thread somehow. But you have to understand how to get the value out. Two pthread_ts can have different apparent values but still refer to the same thread just as two char *s can have different apparent values but still refer to the same string.
Just as you compare two char *'s with strcmp if you want to tell if they refer to the same string value, you compare two pthread_ts with pthread_equal to tell if they refer to the same thread.
So this line of code makes no sense:
printf("FLAG = %d ", thread_id);
A pthread_t is not an integer and you can't print it with a %d format specifier. POSIX has no printable thread IDs. If you want one, you need to code one (perhaps using pthread_getspecific).
In C, arguments are passed by value. In particular, the argument (void *)thread_id is an expression that's evaluated before calling pthread_create, so the fact that pthread_create writes to thread_id as a result of &thread_id being passed as the first argument is irrelevant. If you were instead passing &thread_id rather than (void *)thread_id as the argument to the new thread start function, and dereferencing it there, then you may see the effects you want; however, it's not clear to me that pthread_create's writing of the new thread id via its first argument is required to take place before the new thread starts, so there is probably a data race if you do it that way.
Further, note that David's answer is also correct. It's invalid to print thread ids this way since they are formally an opaque type.
In this line:
rc = pthread_create(&thread_id, NULL, PrintHello, (void*)thread_id);
as the manual says, pthread_create() shall store the ID of the created thread in the location referenced by thread_id. In this example, it would be modified to 355198720, which is the tid of new thread PrintHello().
Besides, it may be better to change the argument for PrintHello to:
rc = pthread_create(&thread_id, NULL, PrintHello, (void*)&thread_id);
and in PrintHello(), it would be:
void* PrintHello(void* data)
{
pthread_t tid = (pthread_t)(*data);
...
}
In a Linux C program, how do I print the thread id of a thread created by the pthread library? For example like how we can get pid of a process by getpid().
What? The person asked for Linux specific, and the equivalent of getpid(). Not BSD or Apple. The answer is gettid() and returns an integral type. You will have to call it using syscall(), like this:
#include <sys/types.h>
#include <unistd.h>
#include <sys/syscall.h>
....
pid_t x = syscall(__NR_gettid);
While this may not be portable to non-linux systems, the threadid is directly comparable and very fast to acquire. It can be printed (such as for LOGs) like a normal integer.
pthread_self() function will give the thread id of current thread.
pthread_t pthread_self(void);
The pthread_self() function returns the Pthread handle of the calling thread. The pthread_self() function does NOT return the integral thread of the calling thread. You must use pthread_getthreadid_np() to return an integral identifier for the thread.
NOTE:
pthread_id_np_t tid;
tid = pthread_getthreadid_np();
is significantly faster than these calls, but provides the same behavior.
pthread_id_np_t tid;
pthread_t self;
self = pthread_self();
pthread_getunique_np(&self, &tid);
As noted in other answers, pthreads does not define a platform-independent way to retrieve an integral thread ID.
On Linux systems, you can get thread ID thus:
#include <sys/types.h>
pid_t tid = gettid();
On many BSD-based platforms, this answer https://stackoverflow.com/a/21206357/316487 gives a non-portable way.
However, if the reason you think you need a thread ID is to know whether you're running on the same or different thread to another thread you control, you might find some utility in this approach
static pthread_t threadA;
// On thread A...
threadA = pthread_self();
// On thread B...
pthread_t threadB = pthread_self();
if (pthread_equal(threadA, threadB)) printf("Thread B is same as thread A.\n");
else printf("Thread B is NOT same as thread A.\n");
If you just need to know if you're on the main thread, there are additional ways, documented in answers to this question how can I tell if pthread_self is the main (first) thread in the process?.
pid_t tid = syscall(SYS_gettid);
Linux provides such system call to allow you get id of a thread.
You can use pthread_self()
The parent gets to know the thread id after the pthread_create() is executed sucessfully, but while executing the thread if we want to access the thread id we have to use the function pthread_self().
This single line gives you pid , each threadid and spid.
printf("before calling pthread_create getpid: %d getpthread_self: %lu tid:%lu\n",getpid(), pthread_self(), syscall(SYS_gettid));
I think not only is the question not clear but most people also are not cognizant of the difference. Examine the following saying,
POSIX thread IDs are not the same as the thread IDs returned by the
Linux specific gettid() system call. POSIX thread IDs are assigned
and maintained by the threading implementation. The thread ID returned
by gettid() is a number (similar to a process ID) that is assigned by
the kernel. Although each POSIX thread has a unique kernel thread ID
in the Linux NPTL threading implementation, an application generally
doesn’t need to know about the kernel IDs (and won’t be portable if it
depends on knowing them).
Excerpted from: The Linux Programming Interface: A Linux and UNIX System Programming Handbook, Michael Kerrisk
IMHO, there is only one portable way that pass a structure in which define a variable holding numbers in an ascending manner e.g. 1,2,3... to per thread. By doing this, threads' id can be kept track. Nonetheless, int pthread_equal(tid1, tid2) function should be used.
if (pthread_equal(tid1, tid2)) printf("Thread 2 is same as thread 1.\n");
else printf("Thread 2 is NOT same as thread 1.\n");
pthread_getthreadid_np wasn't on my Mac os x. pthread_t is an opaque type. Don't beat your head over it. Just assign it to void* and call it good. If you need to printf use %p.
There is also another way of getting thread id. While creating threads with
int pthread_create(pthread_t * thread, const pthread_attr_t * attr, void * (*start_routine)(void *), void *arg);
function call; the first parameter pthread_t * thread is actually a thread id (that is an unsigned long int defined in bits/pthreadtypes.h). Also, the last argument void *arg is the argument that is passed to void * (*start_routine) function to be threaded.
You can create a structure to pass multiple arguments and send a pointer to a structure.
typedef struct thread_info {
pthread_t thread;
//...
} thread_info;
//...
tinfo = malloc(sizeof(thread_info) * NUMBER_OF_THREADS);
//...
pthread_create (&tinfo[i].thread, NULL, handler, (void*)&tinfo[i]);
//...
void *handler(void *targs) {
thread_info *tinfo = targs;
// here you get the thread id with tinfo->thread
}
For different OS there is different answer. I find a helper here.
You can try this:
#include <unistd.h>
#include <sys/syscall.h>
int get_thread_id() {
#if defined(__linux__)
return syscall(SYS_gettid);
#elif defined(__FreeBSD__)
long tid;
thr_self(&tid);
return (int)tid;
#elif defined(__NetBSD__)
return _lwp_self();
#elif defined(__OpenBSD__)
return getthrid();
#else
return getpid();
#endif
}
Platform-independent way (starting from c++11) is:
#include <thread>
std::this_thread::get_id();
You can also write in this manner and it does the same. For eg:
for(int i=0;i < total; i++)
{
pthread_join(pth[i],NULL);
cout << "SUM of thread id " << pth[i] << " is " << args[i].sum << endl;
}
This program sets up an array of pthread_t and calculate sum on each. So it is printing the sum of each thread with thread id.
This is what I am wondering:
If I create a thread with pthread_create() and then call pthread_self() from that thread, will that value match the pthread_t value that I pass to pthread_create in the main thread?
//pthread_t variable
pthread_t producer_thread = (pthread_t*)malloc(sizeof(pthread_t));;
//create the thread
pthread_create(producer_thread, NULL, producer, NULL);
printf("Pthread_t variable after creating thread says %d\n", producer_thread);
....
//function passed to thread
void producer(void *p){
printf("Pthread self says: %d\n", pthread_self());
}
Return type of pthread_self is pthread_t which is basically a pointer not of integer type.
So, it is printing its address(typecasted to int), not pthread_t structure.
You can use pthread_equal function to check if these pthread_t are same or not. Means, in another thread, use
printf("%d\n", pthread_equal(mythreadId, pthread_self()));
It should print a non-zero number indicating that they correspond to the same thread.
If they are not same, then it is a problem.
Print mythreadId in the thread what is spawns. It must match with main's pthread_t. If they are different, then there is a problem.