The reason you're getting the same TID for each thread is that you're calling syscall(SYS_gettid)
from the main thread each time, rather than from within the new thread you create. You need to call it from inside your thread function and then provide a way to pass the information back to the main thread if it's needed there.
As an example of one way to do it (some error checking omitted):
Create a struct to hold a mutex, condition, the TID, and a flag to indicate when the TID is valid.
struct s_threadId {
pthread_mutex_t mtx; /* mutex & condition to allow main thread to
wait for the new thread to set its TID */
pthread_cond_t cond; /* '' */
pid_t id; /* to hold new thread's TID */
int ready; /* to indicate when 'id' is valid, in case
the condition wait gets interrupted */
};
Then change your thread function to lock, set, and signal (and move it so that it's declaration is visible before spawnThreads()
):
void *foo(void *arg)
{
struct s_threadId *thId = arg;
/* Lock mutex... */
pthread_mutex_lock(&thId->mtx);
/* Get and save TID and ready flag.. */
thId->id = syscall(SYS_gettid);
thId->ready = 1;
/* ..and signal main thread that we're ready */
pthread_cond_signal(&thId->cond);
/* ..then unlock when we're done. */
pthread_mutex_unlock(&thId->mtx);
/* ... */
return NULL;
}
...and modify your spawnThreads
function to initialize/cleanup the struct members and get the TID once the thread sets it:
void spawnThreads(unsigned int n)
{
pthread_t thread; /* reused for each thread, since they run 1 at a time */
/* struct to pass back TID */
struct s_threadId threadId;
pthread_cond_init(&threadId.cond, NULL); /* init condition */
pthread_mutex_init(&threadId.mtx, NULL); /* init mutex */
int i;
for (i = 0; i < n; i++) {
/* lock mutex *before* creating the thread, to make the new thread
wait until we're ready before signaling us */
pthread_mutex_lock(&threadId.mtx);
/* clear ready flag before creating each thread */
threadId.ready = 0;
/* create threads and pass address of struct as argument */
if (pthread_create(&thread, NULL, foo, &threadId)) {
printf("pthread error!\n");
} else {
/* Wait on the condition until the ready flag is set */
while (!threadId.ready) {
pthread_cond_wait(&threadId.cond, &threadId.mtx);
}
/* Now we have the TID... */
printf("%d %d\n", i, threadId.id);
printf("I just created thread %d\n", i);
}
/* ..and unlock the mutex when done. */
pthread_mutex_unlock(&threadId.mtx);
pthread_join(thread, NULL);
}
/* When we're completely done with the struct we need to clean up the
mutex and condition variable */
pthread_mutex_destroy(&threadId.mtx);
pthread_cond_destroy(&threadId.cond);
}
In the above, the mutex and condition wait are needed to make sure that the main thread doesn't try to print the TID until the new thread has had a chance to set it. The main thread starts the new one and then waits, and the new thread signal when it's done storing the TID so the main thread can continue.