Implemented nptl_db testing.
[debugger.git] / testsuite.c
index ebd531b..c569777 100644 (file)
@@ -1,5 +1,7 @@
 /* Copyright 2007, Red Hat Inc.  */
 
+#define _GNU_SOURCE 1
+
 #include <unistd.h>
 #include <stdlib.h>
 #include <assert.h>
@@ -10,6 +12,7 @@
 #include <string.h>
 #include <pthread.h>
 #include <sys/syscall.h>
+#include <dlfcn.h>
 
 #include "debugger.h"
 
 #define tkill(tid, sig) syscall (SYS_tkill, (tid), (sig))
 
 
-static int attach_checked (pid_t pid, int redelivered_expect)
+static volatile int spawned_threads_count;     /* Set for the specific spawner.  */
+
+static struct attach_state_struct *attach_checked (pid_t pid, int redelivered_expect)
 {
-  int stopped;
+  struct attach_state_struct *attach_state;
 
   STATE (pid, (1 << STATE_SLEEPING) | (1 << STATE_RUNNING) | (1 << STATE_STOPPED));
-  stopped = attach (pid);
-  if (attach_redelivered != redelivered_expect)
+  attach_state = attach (pid);
+  if (redelivered_expect != attach_state_redelivered_get (attach_state))
     {
       fprintf (stderr, "Expecting redelivery of %d but found %d\n",
-              redelivered_expect, attach_redelivered);
+              redelivered_expect, attach_state_redelivered_get (attach_state));
       abort ();
     }
+  assert (spawned_threads_count == attach_state_threads_count_get (attach_state));
   /* FIXME: Why also STATE_STOPPED?  */
   STATE (pid, (1 << STATE_PTRACED) | (1 << STATE_STOPPED));
-  return stopped;
+  return attach_state;
 }
 
-static void detach_checked (pid_t pid, int stopped)
+static void detach_checked (struct attach_state_struct *attach_state)
 {
+  pid_t pid = attach_state_pid_get (attach_state);
+  int stopped = attach_state_stopped_get (attach_state);
+
   /* FIXME: Why STATE_STOPPED?  */
   STATE (pid, (stopped ? 1 << STATE_STOPPED : 1 << STATE_PTRACED));
-  detach (pid, stopped);
+  detach (attach_state);
   STATE (pid, (stopped ? 1 << STATE_STOPPED : (1 << STATE_SLEEPING) | (1 << STATE_RUNNING)));
 }
 
@@ -300,16 +309,16 @@ static void body_spawner (void *(*child) (void *data, void *input), void *data,
                          void *input)
 {
   pid_t inferior;
-  int stopped;
+  struct attach_state_struct *attach_state;
   int i;
 
   assert (input == NULL);
 
   /* Plain attach/detach.  */
   inferior = (unsigned long) (*child) (data, child_pause);
-  stopped = attach_checked (inferior, 0);
-  assert (stopped == 0);
-  detach_checked (inferior, stopped);
+  attach_state = attach_checked (inferior, 0);
+  assert (attach_state_stopped_get (attach_state) == 0);
+  detach_checked (attach_state);
   murder (inferior);
 
   /* Attach to a process stopped by standard kill(2).  */
@@ -318,9 +327,9 @@ static void body_spawner (void *(*child) (void *data, void *input), void *data,
   i = kill (inferior, SIGSTOP);
   assert (i == 0);
   STATE (inferior, 1 << STATE_STOPPED);
-  stopped = attach_checked (inferior, 0);
-  assert (stopped == 1);
-  detach_checked (inferior, stopped);
+  attach_state = attach_checked (inferior, 0);
+  assert (attach_state_stopped_get (attach_state) == 1);
+  detach_checked (attach_state);
   murder (inferior);
 
   /* Attach to a process stopped by Linux specific tkill(2).  */
@@ -329,9 +338,9 @@ static void body_spawner (void *(*child) (void *data, void *input), void *data,
   i = tkill (inferior, SIGSTOP);
   assert (i == 0);
   STATE (inferior, 1 << STATE_STOPPED);
-  stopped = attach_checked (inferior, 0);
-  assert (stopped == 1);
-  detach_checked (inferior, stopped);
+  attach_state = attach_checked (inferior, 0);
+  assert (attach_state_stopped_get (attach_state) == 1);
+  detach_checked (attach_state);
   murder (inferior);
 
   /* Attach to a stopped process with already pending SIGALRM.  */
@@ -348,12 +357,12 @@ static void body_spawner (void *(*child) (void *data, void *input), void *data,
   STATE (inferior, 1 << STATE_STOPPED);
   /* FIXME: SIGALRM did not get redelivered?  */
 #if 0
-  stopped = attach_checked (inferior, SIGALRM);
+  attach_state = attach_checked (inferior, SIGALRM);
 #else
-  stopped = attach_checked (inferior, 0);
+  attach_state = attach_checked (inferior, 0);
 #endif
-  assert (stopped == 1);
-  detach_checked (inferior, stopped);
+  assert (attach_state_stopped_get (attach_state) == 1);
+  detach_checked (attach_state);
   STATE (inferior, 1 << STATE_STOPPED);
   delay ();
   i = tkill (inferior, SIGCONT);
@@ -409,24 +418,48 @@ static void *spawn_threaded_parent (void *data, void *input)
 {
   pthread_t thread;
   int i;
+  void *handle;
+  void *retval;
+  int (*pthread_create_pointer) (pthread_t *thread,
+                                const pthread_attr_t *attr,
+                                void *(*start_routine) (void *),
+                                void *arg);
+
+  handle = dlopen ("libpthread.so.0", RTLD_LAZY);
+  assert (handle != NULL);
+  pthread_create_pointer = dlsym (handle, "pthread_create");
+  assert (pthread_create_pointer != NULL);
+
+  i = (*pthread_create_pointer) (&thread, NULL, spawn_threaded_parent_start,
+                                NULL);
+  assert (i == 0);
+  retval = pass (data, input);
 
-  i = pthread_create (&thread, NULL, spawn_threaded_parent_start, NULL);
+  i = dlclose (handle);
   assert (i == 0);
-  return pass (data, input);
+
+  return retval;
 }
 
 struct spawn_threaded_child_start
   {
     void *data;
     void *input;
+    void *lib_handle;
   };
 
 static void *spawn_threaded_child_start (void *arg_voidpointer)
 {
   struct spawn_threaded_child_start *arg = arg_voidpointer;
+  void *retval;
+  int i;
 
-  return pass (arg->data, arg->input);
-  /* NOTREACHED */
+  retval = pass (arg->data, arg->input);
+
+  i = dlclose (arg->lib_handle);
+  assert (i == 0);
+
+  return retval;
 }
 
 static void *spawn_threaded_child (void *data, void *input)
@@ -434,12 +467,25 @@ static void *spawn_threaded_child (void *data, void *input)
   pthread_t thread;
   int i;
   struct spawn_threaded_child_start arg_local;
+  int (*pthread_create_pointer) (pthread_t *thread,
+                                const pthread_attr_t *attr,
+                                void *(*start_routine) (void *),
+                                void *arg);
+  int (*pthread_join_pointer) (pthread_t thread, void **value_ptr);
+
+  arg_local.lib_handle = dlopen ("libpthread.so.0", RTLD_LAZY);
+  assert (arg_local.lib_handle != NULL);
+  pthread_create_pointer = dlsym (arg_local.lib_handle, "pthread_create");
+  assert (pthread_create_pointer != NULL);
+  pthread_join_pointer = dlsym (arg_local.lib_handle, "pthread_join");
+  assert (pthread_join_pointer != NULL);
 
   arg_local.data = data;
   arg_local.input = input;
-  i = pthread_create (&thread, NULL, spawn_threaded_child_start, &arg_local);
+  i = (*pthread_create_pointer) (&thread, NULL, spawn_threaded_child_start,
+                                &arg_local);
   assert (i == 0);
-  i = pthread_join (thread, NULL);
+  i = (*pthread_join_pointer) (thread, NULL);
   assert (i == 0);
 
   _exit (EXIT_SUCCESS);
@@ -499,8 +545,14 @@ int main (int argc, char **argv)
          printf ("%lu\n", loops);
          loops_print--;
        }
+
+      spawned_threads_count = 0;
       body_maywaiter (spawn_singlethreaded, NULL, NULL);
+
+      spawned_threads_count = 2;
       body_maywaiter (spawn_threaded_parent, NULL, NULL);
+
+      spawned_threads_count = 2;
       body_maywaiter (spawn_threaded_child, NULL, NULL);
 
       registry_cleanup ();