/* Copyright 2007, Red Hat Inc. */
+#define _GNU_SOURCE 1
+
#include <unistd.h>
#include <stdlib.h>
#include <assert.h>
#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)));
}
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). */
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). */
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. */
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);
{
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)
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);
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 ();