+2014-01-09  Pedro Alves  <palves@redhat.com>
+
+       Skip enabling event reporting if the kernel supports
+       PTRACE_EVENT_CLONE.
+       * linux-thread-db.c: Include "nat/linux-ptrace.h".
+       (thread_db_use_events): New function.
+       (try_thread_db_load_1): Check thread_db_use_events before enabling
+       event reporting.
+       (update_thread_state): New function.
+       (attach_thread): Use it.  Check thread_db_use_events before
+       enabling event reporting.
+       (thread_db_detach): Check thread_db_use_events before disabling
+       event reporting.
+       (find_new_threads_callback): Check thread_db_use_events before
+       enabling event reporting.  Update the thread's state if not using
+       libthread_db events.
+
 2015-01-09  Pedro Alves  <palves@redhat.com>
 
        * linux-nat.c (lin_lwp_attach_lwp): Assert that the lwp id we're
 
 #include "observer.h"
 #include "linux-nat.h"
 #include "nat/linux-procfs.h"
+#include "nat/linux-ptrace.h"
 #include "nat/linux-osdata.h"
 #include "auto-load.h"
 #include "cli/cli-utils.h"
    by the "set auto-load libthread-db" command.  */
 static int auto_load_thread_db = 1;
 
+/* Returns true if we need to use thread_db thread create/death event
+   breakpoints to learn about threads.  */
+
+static int
+thread_db_use_events (void)
+{
+  /* Not necessary if the kernel supports clone events.  */
+  return !linux_supports_traceclone ();
+}
+
 /* "show" command for the auto_load_thread_db configuration variable.  */
 
 static void
     push_target (&thread_db_ops);
 
   /* Enable event reporting, but not when debugging a core file.  */
-  if (target_has_execution)
+  if (target_has_execution && thread_db_use_events ())
     enable_thread_event_reporting ();
 
   return 1;
   check_for_thread_db ();
 }
 
+/* Update the thread's state (what's displayed in "info threads"),
+   from libthread_db thread state information.  */
+
+static void
+update_thread_state (struct private_thread_info *private,
+                    const td_thrinfo_t *ti_p)
+{
+  private->dying = (ti_p->ti_state == TD_THR_UNKNOWN
+                   || ti_p->ti_state == TD_THR_ZOMBIE);
+}
+
 /* Attach to a new thread.  This function is called when we receive a
    TD_CREATE event or when we iterate over all threads and find one
    that wasn't already in our list.  Returns true on success.  */
   gdb_assert (ti_p->ti_tid != 0);
   private->th = *th_p;
   private->tid = ti_p->ti_tid;
-  if (ti_p->ti_state == TD_THR_UNKNOWN || ti_p->ti_state == TD_THR_ZOMBIE)
-    private->dying = 1;
+  update_thread_state (private, ti_p);
 
   /* Add the thread to GDB's thread list.  */
   if (tp == NULL)
 
   /* Enable thread event reporting for this thread, except when
      debugging a core file.  */
-  if (target_has_execution)
+  if (target_has_execution && thread_db_use_events ())
     {
       err = info->td_thr_event_enable_p (th_p, 1);
       if (err != TD_OK)
 
   if (info)
     {
-      if (target_has_execution)
+      if (target_has_execution && thread_db_use_events ())
        {
          disable_thread_event_reporting (info);
 
         need this glibc bug workaround.  */
       info->need_stale_parent_threads_check = 0;
 
-      if (target_has_execution)
+      if (target_has_execution && thread_db_use_events ())
        {
          err = info->td_thr_event_enable_p (th_p, 1);
          if (err != TD_OK)
           iteration: thread_db_find_new_threads_2 will retry.  */
        return 1;
     }
+  else if (target_has_execution && !thread_db_use_events ())
+    {
+      /* Need to update this if not using the libthread_db events
+        (particularly, the TD_DEATH event).  */
+      update_thread_state (tp->private, &ti);
+    }
 
   return 0;
 }
 
   signal (SIGUSR1, handler_sigusr1);
   signal (SIGUSR2, handler_sigusr2);
 
-  pthread_barrier_init (&barrier, NULL, 3);
-
   for (i = 0; i < 2; i++)
-    pthread_create (&child_thread[i], NULL, thread_function, NULL);
-
-  pthread_barrier_wait (&barrier);
+    {
+      pthread_barrier_init (&barrier, NULL, 2);
+      pthread_create (&child_thread[i], NULL, thread_function, NULL);
+      pthread_barrier_wait (&barrier);
+      pthread_barrier_destroy (&barrier);
+    }
 
   all_threads_started ();