From 5521677adbd492472de047a9d31597addb9502f4 Mon Sep 17 00:00:00 2001
From: Aditya Vidyadhar Kamath <Aditya.Kamath1@ibm.com>
Date: Tue, 29 Nov 2022 00:20:19 -0600
Subject: [PATCH] Fix multi thread bug in AIX

---
 gdb/aix-thread.c     | 66 +++++++++++++++++++++-----------------------
 gdb/rs6000-aix-nat.c | 48 ++++++++++++++++++++++++++++++--
 2 files changed, 77 insertions(+), 37 deletions(-)

diff --git a/gdb/aix-thread.c b/gdb/aix-thread.c
index e556c153576..6783aa4999f 100644
--- a/gdb/aix-thread.c
+++ b/gdb/aix-thread.c
@@ -508,14 +508,13 @@ pdc_read_data (pthdb_user_t user_current_pid, void *buf,
   /* This is needed to eliminate the dependency of current thread
      which is null so that thread reads the correct target memory.  */
   {
-    scoped_restore_current_thread restore_current_thread;
+    scoped_restore save_inferior_ptid = make_scoped_restore (&inferior_ptid);
     /* Before the first inferior is added, we pass inferior_ptid.pid ()
        from pd_enable () which is 0.  There is no need to switch threads
        during first initialisation.  In the rest of the callbacks the
        current thread needs to be correct.  */
     if (user_current_pid != 0)
-      switch_to_thread (current_inferior ()->process_target (),
-			ptid_t (user_current_pid));
+      inferior_ptid = ptid_t (user_current_pid);
     status = target_read_memory (addr, (gdb_byte *) buf, len);
   }
   ret = status == 0 ? PDC_SUCCESS : PDC_FAILURE;
@@ -639,36 +638,24 @@ pcmp (const void *p1v, const void *p2v)
   return p1->pthid < p2->pthid ? -1 : p1->pthid > p2->pthid;
 }
 
-/* iterate_over_threads() callback for counting GDB threads.
+/* iterate_over_threads() callback for counting GDB threads.  */
 
-   Do not count the main thread (whose tid is zero).  This matches
-   the list of threads provided by the pthreaddebug library, which
-   does not include that main thread either, and thus allows us
-   to compare the two lists.  */
 
 static int
 giter_count (struct thread_info *thread, void *countp)
 {
-  if (PD_TID (thread->ptid))
-    (*(int *) countp)++;
+  (*(int *) countp)++;
   return 0;
 }
 
-/* iterate_over_threads() callback for accumulating GDB thread pids.
-
-   Do not include the main thread (whose tid is zero).  This matches
-   the list of threads provided by the pthreaddebug library, which
-   does not include that main thread either, and thus allows us
-   to compare the two lists.  */
+/* iterate_over_threads() callback for accumulating GDB thread pids.  */
 
 static int
 giter_accum (struct thread_info *thread, void *bufp)
 {
-  if (PD_TID (thread->ptid))
-    {
-      **(struct thread_info ***) bufp = thread;
-      (*(struct thread_info ***) bufp)++;
-    }
+  **(struct thread_info ***) bufp = thread;
+  (*(struct thread_info ***) bufp)++;
+    
   return 0;
 }
 
@@ -704,8 +691,8 @@ gcmp (const void *t1v, const void *t2v)
 }
 
 /* Search through the list of all kernel threads for the thread
-   that has stopped on a SIGTRAP signal, and return its TID.
-   Return 0 if none found.  */
+   that has stopped on a SIGTRAP or SIGINT signal, and return
+   its TID.  Return 0 if none found.  */
 
 static pthdb_tid_t
 get_signaled_thread (int pid)
@@ -719,7 +706,7 @@ get_signaled_thread (int pid)
 		    sizeof (thrinf), &ktid, 1) != 1)
 	break;
 
-      if (thrinf.ti_cursig == SIGTRAP)
+      if (thrinf.ti_cursig == SIGTRAP || thrinf.ti_cursig == SIGINT)
 	return thrinf.ti_tid;
     }
 
@@ -750,6 +737,9 @@ sync_threadlists (int pid)
   pthdb_pthread_t pdtid;
   pthread_t pthid;
   pthdb_tid_t tid;
+  process_stratum_target *proc_target
+	= current_inferior ()->process_target ();
+  thread_info *tp;
 
   /* Accumulate an array of libpthdebug threads sorted by pthread id.  */
 
@@ -810,10 +800,8 @@ sync_threadlists (int pid)
 	  priv->pdtid = pbuf[pi].pdtid;
 	  priv->tid = pbuf[pi].tid;
 
-	  process_stratum_target *proc_target
-	    = current_inferior ()->process_target ();
 	  thread = add_thread_with_info (proc_target,
-					 ptid_t (pid, 0, pbuf[pi].pthid),
+					 ptid_t (pid, pbuf[pi].tid, pbuf[pi].pthid),
 					 priv);
 
 	  pi++;
@@ -823,7 +811,7 @@ sync_threadlists (int pid)
 	  ptid_t pptid, gptid;
 	  int cmp_result;
 
-	  pptid = ptid_t (pid, 0, pbuf[pi].pthid);
+	  pptid = ptid_t (pid, pbuf[pi].tid, pbuf[pi].pthid);
 	  gptid = gbuf[gi]->ptid;
 	  pdtid = pbuf[pi].pdtid;
 	  tid = pbuf[pi].tid;
@@ -841,8 +829,22 @@ sync_threadlists (int pid)
 	    }
 	  else if (cmp_result > 0)
 	    {
-	      delete_thread (gbuf[gi]);
-	      gi++;
+	      if (gptid.is_pid ())
+		{
+		  thread_change_ptid (proc_target, gptid, pptid);
+		  aix_thread_info *priv = new aix_thread_info;
+                  priv->pdtid = pbuf[pi].pdtid;
+                  priv->tid = pbuf[pi].tid;
+		  tp = find_thread_ptid (proc_target, pptid);
+		  tp->priv.reset (priv);
+		  pi++;
+		  gi++;
+		}
+	      else
+		{
+		  delete_thread (gbuf[gi]);
+		  gi++;
+		}
 	    }
 	  else
 	    {
@@ -1091,10 +1093,6 @@ aix_thread_target::wait (ptid_t ptid, struct target_waitstatus *status,
   if (ptid.pid () == -1)
     return ptid_t (-1);
 
-  /* The target beneath does not deal with threads, so it should only return
-     pid-only ptids.  */
-  gdb_assert (ptid.is_pid ());
-
   /* Check whether libpthdebug might be ready to be initialized.  */
   if (!pd_active && status->kind () == TARGET_WAITKIND_STOPPED
       && status->sig () == GDB_SIGNAL_TRAP)
diff --git a/gdb/rs6000-aix-nat.c b/gdb/rs6000-aix-nat.c
index 2ac1f6e70b6..db45a95952a 100644
--- a/gdb/rs6000-aix-nat.c
+++ b/gdb/rs6000-aix-nat.c
@@ -619,6 +619,48 @@ rs6000_nat_target::xfer_partial (enum target_object object,
     }
 }
 
+/* Search through the list of all kernel threads for the thread
+   that has stopped on a SIGTRAP or SIGINT signal, and return
+   its TID.  Return 0 if none found.  */
+
+static tid_t
+get_signaled_thread_rs6000 (int pid)
+{
+  struct thrdsinfo64 thrinf;
+  tid_t ktid = 0;
+
+  while (1)
+    {
+      if (getthrds (pid, &thrinf,
+                    sizeof (thrinf), &ktid, 1) != 1)
+        break;
+
+      if (thrinf.ti_cursig == SIGTRAP || thrinf.ti_cursig == SIGINT)
+        return thrinf.ti_tid;
+    }
+
+  /* Didn't find any thread stopped on a SIGTRAP signal.  */
+  return 0;
+}
+
+/* If my process is pthreaded I need to return that ptid else ptid_t
+   (pid).  */
+
+static ptid_t
+find_the_return_ptid (pid_t pid)
+{
+  ptid_t ptid = ptid_t (pid);
+  process_stratum_target *proc_target
+        = current_inferior ()->process_target ();
+  inferior *inf = find_inferior_pid (proc_target, pid);
+  thread_info *tp = find_thread_ptid (inf, ptid_t (pid));
+  if (tp == nullptr)
+    for (thread_info *tp1 : inf->threads ())
+       if (tp1->ptid.lwp () == get_signaled_thread_rs6000 (pid))
+         return tp1->ptid;
+  return ptid;
+}
+
 /* Wait for the child specified by PTID to do something.  Return the
    process ID of the child, or MINUS_ONE_PTID in case of error; store
    the status in *OURSTATUS.  */
@@ -672,7 +714,7 @@ rs6000_nat_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus,
 	      if (parent_pid > 0)
 		{
 		  ourstatus->set_forked (ptid_t (pid));
-		  return ptid_t (parent_pid);
+		  return find_the_return_ptid (parent_pid);
 		}
 	      aix_remember_child (pid);
 	    }
@@ -687,7 +729,7 @@ rs6000_nat_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus,
 	      if (child_pid > 0)
 		{
 		  ourstatus->set_forked (ptid_t (child_pid));
-		  return ptid_t (pid);
+		  return find_the_return_ptid (pid);
 		}
 	      aix_remember_parent (pid);
 	    }
@@ -712,7 +754,7 @@ rs6000_nat_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus,
   else
     *ourstatus = host_status_to_waitstatus (status);
 
-  return ptid_t (pid);
+  return find_the_return_ptid (pid);
 }
 
 
-- 
2.31.1

