Beispiel #1
0
static void *
allocation_thread_function (void *closure)
{
  struct list
  {
    struct list *next;
    long dummy[4];
  };

  struct list *head = NULL;
  size_t allocated = 0;
  while (allocated < per_thread_allocations)
    {
      struct list *new_head = xmalloc (sizeof (*new_head));
      allocated += sizeof (*new_head);
      new_head->next = head;
      head = new_head;
    }

  xpthread_barrier_wait (&barrier);

  /* Main thread prints first statistics here.  */

  xpthread_barrier_wait (&barrier);

  while (head != NULL)
    {
      struct list *next_head = head->next;
      free (head);
      head = next_head;
    }

  return NULL;
}
Beispiel #2
0
static void *
tf_read  (void *arg)
{
  int fd;

  if (arg == NULL)
    fd = fds[0];
  else
    {
      char fname[] = "/tmp/tst-cancel4-fd-XXXXXX";
      tempfd = fd = mkstemp (fname);
      if (fd == -1)
	FAIL_EXIT1 ("mkstemp failed: %m");
      unlink (fname);

      xpthread_barrier_wait (&b2);
    }

  xpthread_barrier_wait (&b2);

  ssize_t s;
  pthread_cleanup_push (cl, NULL);

  char buf[100];
  s = read (fd, buf, sizeof (buf));

  pthread_cleanup_pop (0);

  FAIL_EXIT1 ("read returns with %zd", s);
}
Beispiel #3
0
static void *
tf_readv  (void *arg)
{
  int fd;

  if (arg == NULL)
    fd = fds[0];
  else
    {
      char fname[] = "/tmp/tst-cancel4-fd-XXXXXX";
      tempfd = fd = mkstemp (fname);
      if (fd == -1)
	FAIL_EXIT1 ("mkstemp failed: %m");
      unlink (fname);

      xpthread_barrier_wait (&b2);
    }

  xpthread_barrier_wait (&b2);

  ssize_t s;
  pthread_cleanup_push (cl, NULL);

  char buf[100];
  struct iovec iov[1] = { [0] = { .iov_base = buf, .iov_len = sizeof (buf) } };
Beispiel #4
0
static void *
thr_func (void *arg)
{
  long long int i;
  for (i = 0; i < iteration_count; i++)
    {
      if ((uintptr_t) arg == 0)
	{
	  xpthread_mutex_destroy (&mutex);
	  xpthread_mutex_init (&mutex, NULL);
	}

      xpthread_barrier_wait (&barrier);

      /* Test if enabling lock elision works if it is enabled concurrently.
	 There was a race in FORCE_ELISION macro which leads to either
	 pthread_mutex_destroy returning EBUSY as the owner was recorded
	 by pthread_mutex_lock - in "normal mutex" code path - but was not
	 resetted in pthread_mutex_unlock - in "elision" code path.
	 Or it leads to the assertion in nptl/pthread_mutex_lock.c:
	 assert (mutex->__data.__owner == 0);
	 Please ensure that the test is run with lock elision:
	 export GLIBC_TUNABLES=glibc.elision.enable=1  */
      xpthread_mutex_lock (&mutex);
      xpthread_mutex_unlock (&mutex);

      xpthread_barrier_wait (&barrier);
    }
  return NULL;
}
Beispiel #5
0
static void *
tf (void *arg)
{
    xpthread_barrier_wait (&b);

    posix_spawn_file_actions_t a;
    if (posix_spawn_file_actions_init (&a) != 0)
    {
        puts ("error: spawn_file_actions_init failed");
        exit (1);
    }

    if (posix_spawn_file_actions_adddup2 (&a, pipefd[1], STDOUT_FILENO) != 0)
    {
        puts ("error: spawn_file_actions_adddup2 failed");
        exit (1);
    }

    if (posix_spawn_file_actions_addclose (&a, pipefd[0]) != 0)
    {
        puts ("error: spawn_file_actions_addclose");
        exit (1);
    }

    char *argv[] = { (char *) _PATH_BSHELL, (char *) "-c", (char *) "echo $$",
                     NULL
                   };
    if (posix_spawn (&pid, _PATH_BSHELL, &a, NULL, argv, NULL) != 0)
    {
        puts ("error: spawn failed");
        exit (1);
    }

    return NULL;
}
Beispiel #6
0
static void *
outer_thread (void *closure)
{
  pthread_t *threads = xcalloc (sizeof (*threads), inner_thread_count);
  while (!__atomic_load_n (&termination_requested, __ATOMIC_RELAXED))
    {
      pthread_barrier_t barrier;
      xpthread_barrier_init (&barrier, NULL, inner_thread_count + 1);
      for (int i = 0; i < inner_thread_count; ++i)
        {
          void *(*func) (void *);
          if ((i  % 2) == 0)
            func = malloc_first_thread;
          else
            func = wait_first_thread;
          threads[i] = xpthread_create (NULL, func, &barrier);
        }
      xpthread_barrier_wait (&barrier);
      for (int i = 0; i < inner_thread_count; ++i)
        xpthread_join (threads[i]);
      xpthread_barrier_destroy (&barrier);
    }

  free (threads);

  return NULL;
}
Beispiel #7
0
static void *
wait_first_thread (void * closure)
{
  pthread_barrier_t *barrier = closure;
  xpthread_barrier_wait (barrier);
  void *ptr = xmalloc (malloc_size);
  unoptimized_free (ptr);
  return NULL;
}
Beispiel #8
0
static int
do_test (void)
{
  xpthread_barrier_init (&barrier, NULL, thread_count + 1);

  pthread_t threads[thread_count];
  for (size_t i = 0; i < array_length (threads); ++i)
    threads[i] = xpthread_create (NULL, allocation_thread_function, NULL);

  xpthread_barrier_wait (&barrier);
  puts ("info: After allocation:");
  malloc_info (0, stdout);

  xpthread_barrier_wait (&barrier);
  for (size_t i = 0; i < array_length (threads); ++i)
    xpthread_join (threads[i]);

  puts ("\ninfo: After deallocation:");
  malloc_info (0, stdout);

  return 0;
}
static void *
creator_thread (void *arg)
{
  int ret;
  xpthread_barrier_wait (&barrier);

  while (true)
    {
      pthread_t thr;
      /* Thread creation will fail if the kernel does not free old
	 threads quickly enough, so we do not report errors.  */
      ret = pthread_create (&thr, &detached, do_nothing, NULL);
      if (ret == 0 && __atomic_add_fetch (&threads_created, 1, __ATOMIC_SEQ_CST)
          >= threads_to_create)
        break;
    }

  return NULL;
}
Beispiel #10
0
static int
do_test (void)
{
    /* The test basically pipe a 'echo $$' created by a thread with a
       cancellation pending.  It then checks if the thread is not cancelled,
       the process is created and if the output is the expected one.  */

    if (pipe (pipefd) != 0)
    {
        puts ("error: pipe failed");
        exit (1);
    }

    /* Not interested in knowing when the pipe is closed.  */
    if (sigignore (SIGPIPE) != 0)
    {
        puts ("error: sigignore failed");
        exit (1);
    }

    /* To synchronize with the thread.  */
    if (pthread_barrier_init (&b, NULL, 2) != 0)
    {
        puts ("error: pthread_barrier_init failed");
        exit (1);
    }

    pthread_t th = xpthread_create (NULL, &tf, NULL);

    if (pthread_cancel (th) != 0)
    {
        puts ("error: pthread_cancel failed");
        return 1;
    }

    xpthread_barrier_wait (&b);

    if (xpthread_join (th) == PTHREAD_CANCELED)
    {
        puts ("error: thread cancelled");
        exit (1);
    }

    close (pipefd[1]);

    /* The global 'pid' should be set by thread posix_spawn calling.  Check
       below if it was executed correctly and with expected output.  */

    char buf[64];
    ssize_t n;
    bool seen_pid = false;
    while (TEMP_FAILURE_RETRY ((n = read (pipefd[0], buf, sizeof (buf)))) > 0)
    {
        /* We only expect to read the PID.  */
        char *endp;
        long int rpid = strtol (buf, &endp, 10);

        if (*endp != '\n')
        {
            printf ("error: didn't parse whole line: \"%s\"\n", buf);
            exit (1);
        }
        if (endp == buf)
        {
            puts ("error: read empty line");
            exit (1);
        }

        if (rpid != pid)
        {
            printf ("error: found \"%s\", expected PID %ld\n", buf,
                    (long int) pid);
            exit (1);
        }

        if (seen_pid)
        {
            puts ("error: found more than one PID line");
            exit (1);
        }

        seen_pid = true;
    }

    close (pipefd[0]);

    int status;
    int err = waitpid (pid, &status, 0);
    if (err != pid)
    {
        puts ("errnor: waitpid failed");
        exit (1);
    }

    if (!seen_pid)
    {
        puts ("error: didn't get PID");
        exit (1);
    }

    return 0;
}