[RFC][Patch] Fix gdb failure to access tls data for parent thread

Vinay Sridhar
2009-01-09T08:47:51Z

Hello,

While using gdb to access tls data for a parent thread of a multi-threaded program, we get the following error :

"Cannot find thread-local storage for LWP 11884, executable file /home/test/test
TLS not supported on this target"

This can be recreated as follows :

$ cat test.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <omp.h>

__thread int thread;

void initTlsData() {
printf("Initialising %d\n",thread);
}
int main(int argc, char *argv[]) {
#pragma omp parallel
{
thread = omp_get_thread_num();
initTlsData();
}
return(0);
}

0. export "OMP_NUM_THREADS=5" // 5 for example
1. gdb ./test
2. break initTlsData
3. run
4. thread 1 // Switch to the parent thread
5. print thread

The above stated error occurs.

The reason for this is gdb does not fill in the private field of the thread_info structure of the
parent thread. The below patch sets up this private field before the child
threads are added to gdb's list.

I'm not sure if the patch below breaks any existing behaviour. I'm also not sure if this is the right way to go about this.
This is purely RFC.
If there's a better way of doing this please let me know.

--- linux-thread-db.c.old 2008-12-11 14:19:12.000000000 -0500
+++ linux-thread-db.c 2008-12-30 00:26:52.000000000 -0500
@@ -879,9 +879,33 @@ check_event (ptid_t ptid)
while (loop);
}

+void set_private_data (ptid_t ptid)
+{
+ td_thrhandle_t th;
+ struct thread_info *thread_info;
+ td_thrinfo_t ti;
+ td_err_e err;
+ struct private_thread_info *private;
+
+ private = xmalloc (sizeof (struct private_thread_info));
+ memset (private, 0, sizeof (struct private_thread_info));
+
+ err = td_ta_map_lwp2thr_p (thread_agent, GET_LWP (ptid), &th);
+ thread_get_info_callback (&th, &thread_info);
+ err = td_thr_get_info_p (&th, &ti);
+
+ if (ti.ti_tid == 0)
+ err = td_thr_event_enable_p (&th, 1);
+
+ private->th = th;
+ private->tid = ti.ti_tid;
+ thread_info->private = private;
+}
+
static ptid_t
thread_db_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
{
+ struct thread_info *tp;
ptid = target_beneath->to_wait (ptid, ourstatus);

if (ourstatus->kind == TARGET_WAITKIND_IGNORE)
@@ -900,6 +924,13 @@ thread_db_wait (ptid_t ptid, struct targ
return ptid;
}

+ tp = find_thread_pid (ptid);
+
+ if (!tp->private)
+ set_private_data(ptid);
+ else if (tp->private->tid == 0)
+ set_private_data(ptid);
+
/* If we do not know about the main thread yet, this would be a good time to
find it. */
if (ourstatus->kind == TARGET_WAITKIND_STOPPED && !have_threads ())

Regards,
VInay

---
Vinay Sridhar,
Linux Technology Center,
IBM ISTL,
Bangalore, India