Blame nptl/tst-mutex8.c

Packit Service 82fcde
/* Copyright (C) 2003-2018 Free Software Foundation, Inc.
Packit Service 82fcde
   This file is part of the GNU C Library.
Packit Service 82fcde
   Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is free software; you can redistribute it and/or
Packit Service 82fcde
   modify it under the terms of the GNU Lesser General Public
Packit Service 82fcde
   License as published by the Free Software Foundation; either
Packit Service 82fcde
   version 2.1 of the License, or (at your option) any later version.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is distributed in the hope that it will be useful,
Packit Service 82fcde
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 82fcde
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 82fcde
   Lesser General Public License for more details.
Packit Service 82fcde
Packit Service 82fcde
   You should have received a copy of the GNU Lesser General Public
Packit Service 82fcde
   License along with the GNU C Library; if not, see
Packit Service 82fcde
   <http://www.gnu.org/licenses/>.  */
Packit Service 82fcde
Packit Service 82fcde
/* This test checks behavior not required by POSIX.  */
Packit Service 82fcde
#include <errno.h>
Packit Service 82fcde
#include <pthread.h>
Packit Service 82fcde
#include <stdbool.h>
Packit Service 82fcde
#include <stdio.h>
Packit Service 82fcde
#include <stdlib.h>
Packit Service 82fcde
#include <unistd.h>
Packit Service 82fcde
#include <elf/dl-tunables.h>
Packit Service 82fcde
Packit Service 82fcde
static pthread_mutex_t *m;
Packit Service 82fcde
static pthread_barrier_t b;
Packit Service 82fcde
static pthread_cond_t c;
Packit Service 82fcde
static bool done;
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
static void
Packit Service 82fcde
cl (void *arg)
Packit Service 82fcde
{
Packit Service 82fcde
  if (pthread_mutex_unlock (m) != 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      puts ("cl: mutex_unlocked failed");
Packit Service 82fcde
      exit (1);
Packit Service 82fcde
    }
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
static void *
Packit Service 82fcde
tf (void *arg)
Packit Service 82fcde
{
Packit Service 82fcde
  if (pthread_mutex_lock (m) != 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      puts ("tf: mutex_lock failed");
Packit Service 82fcde
      return (void *) 1l;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  int e = pthread_barrier_wait (&b);
Packit Service 82fcde
  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
Packit Service 82fcde
    {
Packit Service 82fcde
      puts ("barrier_wait failed");
Packit Service 82fcde
      return (void *) 1l;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  if (arg == NULL)
Packit Service 82fcde
    do
Packit Service 82fcde
      if (pthread_cond_wait (&c, m) != 0)
Packit Service 82fcde
	{
Packit Service 82fcde
	  puts ("tf: cond_wait failed");
Packit Service 82fcde
	  return (void *) 1l;
Packit Service 82fcde
	}
Packit Service 82fcde
    while (! done);
Packit Service 82fcde
  else
Packit Service 82fcde
    do
Packit Service 82fcde
      {
Packit Service 82fcde
	pthread_cleanup_push (cl, NULL);
Packit Service 82fcde
Packit Service 82fcde
	if (pthread_cond_wait (&c, m) != 0)
Packit Service 82fcde
	  {
Packit Service 82fcde
	    puts ("tf: cond_wait failed");
Packit Service 82fcde
	    return (void *) 1l;
Packit Service 82fcde
	  }
Packit Service 82fcde
Packit Service 82fcde
	pthread_cleanup_pop (0);
Packit Service 82fcde
      }
Packit Service 82fcde
    while (! done);
Packit Service 82fcde
Packit Service 82fcde
  if (pthread_mutex_unlock (m) != 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      puts ("tf: mutex_unlock failed");
Packit Service 82fcde
      return (void *) 1l;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  return NULL;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
static int
Packit Service 82fcde
check_type (const char *mas, pthread_mutexattr_t *ma)
Packit Service 82fcde
{
Packit Service 82fcde
  int e;
Packit Service 82fcde
Packit Service 82fcde
  /* Check if a mutex will be elided.  Lock elision can only be activated via
Packit Service 82fcde
     the tunables framework.  By default, lock elision is disabled.  */
Packit Service 82fcde
  bool assume_elided_mutex = false;
Packit Service 82fcde
#if HAVE_TUNABLES
Packit Service 82fcde
  int ma_type = PTHREAD_MUTEX_TIMED_NP;
Packit Service 82fcde
  if (ma != NULL)
Packit Service 82fcde
    {
Packit Service 82fcde
      e = pthread_mutexattr_gettype (ma, &ma_type);
Packit Service 82fcde
      if (e != 0)
Packit Service 82fcde
	{
Packit Service 82fcde
	  printf ("pthread_mutexattr_gettype failed with %d (%m)\n", e);
Packit Service 82fcde
	  return 1;
Packit Service 82fcde
	}
Packit Service 82fcde
    }
Packit Service 82fcde
  if (ma_type == PTHREAD_MUTEX_TIMED_NP)
Packit Service 82fcde
    {
Packit Service 82fcde
      /* This type of mutex can be elided if elision is enabled via the tunables
Packit Service 82fcde
	 framework.  Some tests below are failing if the mutex is elided.
Packit Service 82fcde
	 Thus we only run those if we assume that the mutex won't be elided.  */
Packit Service 82fcde
      if (TUNABLE_GET_FULL (glibc, elision, enable, int32_t, NULL) == 1)
Packit Service 82fcde
	assume_elided_mutex = true;
Packit Service 82fcde
    }
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
  e = pthread_mutex_init (m, ma);
Packit Service 82fcde
  if (e != 0)
Packit Service 82fcde
    {
Packit Service 82fcde
#ifdef ENABLE_PI
Packit Service 82fcde
      if (e == ENOTSUP)
Packit Service 82fcde
	{
Packit Service 82fcde
	  puts ("PI mutexes unsupported");
Packit Service 82fcde
	  return 0;
Packit Service 82fcde
	}
Packit Service 82fcde
#endif
Packit Service 82fcde
      printf ("1st mutex_init failed for %s\n", mas);
Packit Service 82fcde
      return 1;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  if (pthread_mutex_destroy (m) != 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      printf ("immediate mutex_destroy failed for %s\n", mas);
Packit Service 82fcde
      return 1;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  if (pthread_mutex_init (m, ma) != 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      printf ("2nd mutex_init failed for %s\n", mas);
Packit Service 82fcde
      return 1;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  if (pthread_mutex_lock (m) != 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      printf ("1st mutex_lock failed for %s\n", mas);
Packit Service 82fcde
      return 1;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* Elided mutexes don't fail destroy, thus only test this if we don't assume
Packit Service 82fcde
     elision.  */
Packit Service 82fcde
  if (assume_elided_mutex == false)
Packit Service 82fcde
    {
Packit Service 82fcde
      e = pthread_mutex_destroy (m);
Packit Service 82fcde
      if (e == 0)
Packit Service 82fcde
	{
Packit Service 82fcde
	  printf ("mutex_destroy of self-locked mutex succeeded for %s\n", mas);
Packit Service 82fcde
	  return 1;
Packit Service 82fcde
	}
Packit Service 82fcde
      if (e != EBUSY)
Packit Service 82fcde
	{
Packit Service 82fcde
	  printf ("\
Packit Service 82fcde
mutex_destroy of self-locked mutex did not return EBUSY %s\n",
Packit Service 82fcde
		  mas);
Packit Service 82fcde
	  return 1;
Packit Service 82fcde
	}
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  if (pthread_mutex_unlock (m) != 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      printf ("1st mutex_unlock failed for %s\n", mas);
Packit Service 82fcde
      return 1;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  if (pthread_mutex_trylock (m) != 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      printf ("mutex_trylock failed for %s\n", mas);
Packit Service 82fcde
      return 1;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* Elided mutexes don't fail destroy.  */
Packit Service 82fcde
  if (assume_elided_mutex == false)
Packit Service 82fcde
    {
Packit Service 82fcde
      e = pthread_mutex_destroy (m);
Packit Service 82fcde
      if (e == 0)
Packit Service 82fcde
	{
Packit Service 82fcde
	  printf ("mutex_destroy of self-trylocked mutex succeeded for %s\n",
Packit Service 82fcde
		  mas);
Packit Service 82fcde
	  return 1;
Packit Service 82fcde
	}
Packit Service 82fcde
      if (e != EBUSY)
Packit Service 82fcde
	{
Packit Service 82fcde
	  printf ("\
Packit Service 82fcde
mutex_destroy of self-trylocked mutex did not return EBUSY %s\n",
Packit Service 82fcde
		  mas);
Packit Service 82fcde
	  return 1;
Packit Service 82fcde
	}
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  if (pthread_mutex_unlock (m) != 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      printf ("2nd mutex_unlock failed for %s\n", mas);
Packit Service 82fcde
      return 1;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  pthread_t th;
Packit Service 82fcde
  if (pthread_create (&th, NULL, tf, NULL) != 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      puts ("1st create failed");
Packit Service 82fcde
      return 1;
Packit Service 82fcde
    }
Packit Service 82fcde
  done = false;
Packit Service 82fcde
Packit Service 82fcde
  e = pthread_barrier_wait (&b);
Packit Service 82fcde
  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
Packit Service 82fcde
    {
Packit Service 82fcde
      puts ("1st barrier_wait failed");
Packit Service 82fcde
      return 1;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  if (pthread_mutex_lock (m) != 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      printf ("2nd mutex_lock failed for %s\n", mas);
Packit Service 82fcde
      return 1;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  if (pthread_mutex_unlock (m) != 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      printf ("3rd mutex_unlock failed for %s\n", mas);
Packit Service 82fcde
      return 1;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* Elided mutexes don't fail destroy.  */
Packit Service 82fcde
  if (assume_elided_mutex == false)
Packit Service 82fcde
    {
Packit Service 82fcde
      e = pthread_mutex_destroy (m);
Packit Service 82fcde
      if (e == 0)
Packit Service 82fcde
	{
Packit Service 82fcde
	  printf ("mutex_destroy of condvar-used mutex succeeded for %s\n",
Packit Service 82fcde
		  mas);
Packit Service 82fcde
	  return 1;
Packit Service 82fcde
	}
Packit Service 82fcde
      if (e != EBUSY)
Packit Service 82fcde
	{
Packit Service 82fcde
	  printf ("\
Packit Service 82fcde
mutex_destroy of condvar-used mutex did not return EBUSY for %s\n", mas);
Packit Service 82fcde
	  return 1;
Packit Service 82fcde
	}
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  done = true;
Packit Service 82fcde
  if (pthread_cond_signal (&c) != 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      puts ("cond_signal failed");
Packit Service 82fcde
      return 1;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  void *r;
Packit Service 82fcde
  if (pthread_join (th, &r) != 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      puts ("join failed");
Packit Service 82fcde
      return 1;
Packit Service 82fcde
    }
Packit Service 82fcde
  if (r != NULL)
Packit Service 82fcde
    {
Packit Service 82fcde
      puts ("thread didn't return NULL");
Packit Service 82fcde
      return 1;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  if (pthread_mutex_destroy (m) != 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      printf ("mutex_destroy after condvar-use failed for %s\n", mas);
Packit Service 82fcde
      return 1;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  if (pthread_mutex_init (m, ma) != 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      printf ("3rd mutex_init failed for %s\n", mas);
Packit Service 82fcde
      return 1;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  if (pthread_create (&th, NULL, tf, (void *) 1) != 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      puts ("2nd create failed");
Packit Service 82fcde
      return 1;
Packit Service 82fcde
    }
Packit Service 82fcde
  done = false;
Packit Service 82fcde
Packit Service 82fcde
  e = pthread_barrier_wait (&b);
Packit Service 82fcde
  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
Packit Service 82fcde
    {
Packit Service 82fcde
      puts ("2nd barrier_wait failed");
Packit Service 82fcde
      return 1;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  if (pthread_mutex_lock (m) != 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      printf ("3rd mutex_lock failed for %s\n", mas);
Packit Service 82fcde
      return 1;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  if (pthread_mutex_unlock (m) != 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      printf ("4th mutex_unlock failed for %s\n", mas);
Packit Service 82fcde
      return 1;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* Elided mutexes don't fail destroy.  */
Packit Service 82fcde
  if (assume_elided_mutex == false)
Packit Service 82fcde
    {
Packit Service 82fcde
      e = pthread_mutex_destroy (m);
Packit Service 82fcde
      if (e == 0)
Packit Service 82fcde
	{
Packit Service 82fcde
	  printf ("2nd mutex_destroy of condvar-used mutex succeeded for %s\n",
Packit Service 82fcde
		  mas);
Packit Service 82fcde
	  return 1;
Packit Service 82fcde
	}
Packit Service 82fcde
      if (e != EBUSY)
Packit Service 82fcde
	{
Packit Service 82fcde
	  printf ("\
Packit Service 82fcde
2nd mutex_destroy of condvar-used mutex did not return EBUSY for %s\n",
Packit Service 82fcde
		  mas);
Packit Service 82fcde
	  return 1;
Packit Service 82fcde
	}
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  if (pthread_cancel (th) != 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      puts ("cond_cancel failed");
Packit Service 82fcde
      return 1;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  if (pthread_join (th, &r) != 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      puts ("join failed");
Packit Service 82fcde
      return 1;
Packit Service 82fcde
    }
Packit Service 82fcde
  if (r != PTHREAD_CANCELED)
Packit Service 82fcde
    {
Packit Service 82fcde
      puts ("thread not canceled");
Packit Service 82fcde
      return 1;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  if (pthread_mutex_destroy (m) != 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      printf ("mutex_destroy after condvar-canceled failed for %s\n", mas);
Packit Service 82fcde
      return 1;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  return 0;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
static int
Packit Service 82fcde
do_test (void)
Packit Service 82fcde
{
Packit Service 82fcde
  pthread_mutex_t mm;
Packit Service 82fcde
  m = &mm;
Packit Service 82fcde
Packit Service 82fcde
  if (pthread_barrier_init (&b, NULL, 2) != 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      puts ("barrier_init failed");
Packit Service 82fcde
      return 1;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  if (pthread_cond_init (&c, NULL) != 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      puts ("cond_init failed");
Packit Service 82fcde
      return 1;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  puts ("check normal mutex");
Packit Service 82fcde
  int res = check_type ("normal", NULL);
Packit Service 82fcde
Packit Service 82fcde
  pthread_mutexattr_t ma;
Packit Service 82fcde
  if (pthread_mutexattr_init (&ma) != 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      puts ("1st mutexattr_init failed");
Packit Service 82fcde
      return 1;
Packit Service 82fcde
    }
Packit Service 82fcde
  if (pthread_mutexattr_settype (&ma, PTHREAD_MUTEX_RECURSIVE) != 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      puts ("1st mutexattr_settype failed");
Packit Service 82fcde
      return 1;
Packit Service 82fcde
    }
Packit Service 82fcde
#ifdef ENABLE_PI
Packit Service 82fcde
  if (pthread_mutexattr_setprotocol (&ma, PTHREAD_PRIO_INHERIT))
Packit Service 82fcde
    {
Packit Service 82fcde
      puts ("1st pthread_mutexattr_setprotocol failed");
Packit Service 82fcde
      return 1;
Packit Service 82fcde
    }
Packit Service 82fcde
#endif
Packit Service 82fcde
  puts ("check recursive mutex");
Packit Service 82fcde
  res |= check_type ("recursive", &ma);
Packit Service 82fcde
  if (pthread_mutexattr_destroy (&ma) != 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      puts ("1st mutexattr_destroy failed");
Packit Service 82fcde
      return 1;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  if (pthread_mutexattr_init (&ma) != 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      puts ("2nd mutexattr_init failed");
Packit Service 82fcde
      return 1;
Packit Service 82fcde
    }
Packit Service 82fcde
  if (pthread_mutexattr_settype (&ma, PTHREAD_MUTEX_ERRORCHECK) != 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      puts ("2nd mutexattr_settype failed");
Packit Service 82fcde
      return 1;
Packit Service 82fcde
    }
Packit Service 82fcde
#ifdef ENABLE_PI
Packit Service 82fcde
  if (pthread_mutexattr_setprotocol (&ma, PTHREAD_PRIO_INHERIT))
Packit Service 82fcde
    {
Packit Service 82fcde
      puts ("2nd pthread_mutexattr_setprotocol failed");
Packit Service 82fcde
      return 1;
Packit Service 82fcde
    }
Packit Service 82fcde
#endif
Packit Service 82fcde
  puts ("check error-checking mutex");
Packit Service 82fcde
  res |= check_type ("error-checking", &ma);
Packit Service 82fcde
  if (pthread_mutexattr_destroy (&ma) != 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      puts ("2nd mutexattr_destroy failed");
Packit Service 82fcde
      return 1;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  return res;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
#define TEST_FUNCTION do_test ()
Packit Service 82fcde
#include "../test-skeleton.c"