I know the difference between pthread_self()
and syscall(SYS_gettid)
. pthread_create()
produces a POSIX thread ID which is represented by a struct pthread_t which is usually defined as an unsigned long int
. We can use pthread_self
to get the ID of the thread generated by pthread_create
.
With strace
, I know that pthread_create()
in libpthread.so.0 is implemented by calling clone
system call, which is also the system call used for fork()
. After creating a POSIX thread by calling pthread_create()
, a new POSXI thread (identified by thread ID returned by pthread_self()
) and a new linux thread(identified by thread ID returned by syscall(SYS_gettid)
) are produced. Does this mean POSIX thread ID have an one-to-one relation with linux thread ID? They just respectively represent the thread with pthread_t
and pid_t
?
Actually, sometimes I found that one linux thread ID maps to several POSIX thread IDs in the same process, which means that after producing a pair of POSIX thread ID and linux thread ID by calling pthread_create()
, the POSIX thread ID changes while linux thread ID stays the same. Is there any way to change the POSIX thread ID while keeping the linux thread ID unchanged? If there is, which pthread
function is it?
Thank you.
Here is the log by intercepting fork
and pthread_create
call. ltid
means linux thread ID, tid
means POSIX thread ID, pid
means process ID.
1 message: fork pid:12832 ltid:12832 tid:140300035462976 child pid:12848 ltid:12848 tid:140300035462976
2 message: fork pid:12848 ltid:12848 tid:140549640255296 child pid:12849 ltid:12849 tid:140549640255296
3 message: fork pid:12848 ltid:12848 tid:140549640255296 child pid:12850 ltid:12850 tid:140549640255296
4 message: fork pid:12848 ltid:12848 tid:140549640255296 child pid:12851 ltid:12851 tid:140549640255296
5 message: pthread_create pid:12848 ltid:12848 tid:139968995022656 child ltid:12865 tid:139968995018496
6 message: pthread_create pid:12848 ltid:12865 tid:139968995018496 child ltid:12865 tid:139968933345024
7 message: fork pid:12832 ltid:12832 tid:140300035462976 child pid:12885 ltid:12885 tid:140300035462976
8 message: fork pid:12885 ltid:12885 tid:139870512949056 child pid:12886 ltid:12886 tid:139870512949056
My explanation:
fork
producing (pid=12848, ltid=12848, tid=140...976)fork
producing (pid=12849, ltid=12849, tid=140...296)pthread_create
producing (ltid=12865, tid=139...496)The caller of 2
is the result of 1
according to linux thread ID(12848), but they have different POSIX thread IDs. The same goes for 1
and 5
.
Here is the interception code fragment.
void *intermedia(void * arg){
struct thread_param *temp;
void *(*start_routine) (void *);
temp=(struct thread_param *)arg;
char test[1024]="";
sprintf(test,"child ltid:%ld\ttid:%lu\n",syscall(SYS_gettid),pthread_self());
log_message(test)
return temp->start_routine(temp->args);
}
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg){
static void *handle = NULL;
static P_CREATE old_create=NULL;
if( !handle )
{
handle = dlopen("libpthread.so.0", RTLD_LAZY);
old_create = (P_CREATE)dlsym(handle, "pthread_create");
}
pthread_t tmp=pthread_self();
char test[1024]="";
sprintf(test,"pthread_create pid:%d\tptid:%ld\ttid:%lu\n",getpid(),syscall(SYS_gettid),tmp);
log_message(test);
struct thread_param *temp=malloc(sizeof(struct thread_param));
temp->args=arg;
temp->start_routine=start_routine;
int result=old_create(thread,attr,intermedia,(void *)temp);
return result;
}
pid_t fork(void){
static void *handle = NULL;
static FORK old_fork=NULL;
if( !handle )
{
handle = dlopen("libc.so.6", RTLD_LAZY);
old_fork = (FORK)dlsym(handle, "fork");
}
char test[1024]="";
sprintf(test,"fork pid:%d\tltid:%ld\ttid:%lu\t",getpid(),syscall(SYS_gettid),pthread_self());
pid_t ppid=getpid();
pthread_t ptid=pthread_self();
pid_t result=old_fork();
if(result==0){
sprintf(test,"%s\tchild pid:%d\tltid:%ld\ttid:%lu\n",test,getpid(),syscall(SYS_gettid),pthread_self());
log_message(test);
}
return result;
}
Does Posix thread ID have an one-to-one relation with linux thread ID
Yes.
But consider this an implementation detail. Other OSs might do this differently.
which is usually defined as
pthread_t
is opaque. As well do not make any assumptions on how it is implemented.
I found that one linux thread ID maps to several POSIX thread IDs
Really? I doubt this. At least not if all POSIX thread Ids in question were valid, that is the related thread either had not been joined yet or, if running detached, the thread had not ended yet.