hjl / source-git / glibc

Forked from source-git/glibc 3 years ago
Clone

Blame nptl/tst-mutex7.c

Packit 6c4009
/* Copyright (C) 2002-2018 Free Software Foundation, Inc.
Packit 6c4009
   This file is part of the GNU C Library.
Packit 6c4009
   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
Packit 6c4009
Packit 6c4009
   The GNU C Library is free software; you can redistribute it and/or
Packit 6c4009
   modify it under the terms of the GNU Lesser General Public
Packit 6c4009
   License as published by the Free Software Foundation; either
Packit 6c4009
   version 2.1 of the License, or (at your option) any later version.
Packit 6c4009
Packit 6c4009
   The GNU C Library is distributed in the hope that it will be useful,
Packit 6c4009
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6c4009
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6c4009
   Lesser General Public License for more details.
Packit 6c4009
Packit 6c4009
   You should have received a copy of the GNU Lesser General Public
Packit 6c4009
   License along with the GNU C Library; if not, see
Packit 6c4009
   <http://www.gnu.org/licenses/>.  */
Packit 6c4009
Packit 6c4009
#include <errno.h>
Packit 6c4009
#include <pthread.h>
Packit 6c4009
#include <stdio.h>
Packit 6c4009
#include <stdlib.h>
Packit 6c4009
#include <time.h>
Packit 6c4009
Packit 6c4009
/* This test is a template for other tests to use.  Other tests define
Packit 6c4009
   the following macros to change the behaviour of the template test.
Packit 6c4009
   The test is very simple, it configures N threads given the parameters
Packit 6c4009
   below and then proceeds to go through mutex lock and unlock
Packit 6c4009
   operations in each thread as described before for the thread
Packit 6c4009
   function.  */
Packit 6c4009
#ifndef TYPE
Packit 6c4009
# define TYPE PTHREAD_MUTEX_DEFAULT
Packit 6c4009
#endif
Packit 6c4009
#ifndef ROBUST
Packit 6c4009
# define ROBUST PTHREAD_MUTEX_STALLED
Packit 6c4009
#endif
Packit 6c4009
#ifndef DELAY_NSEC
Packit 6c4009
# define DELAY_NSEC 11000
Packit 6c4009
#endif
Packit 6c4009
#ifndef ROUNDS
Packit 6c4009
# define ROUNDS 1000
Packit 6c4009
#endif
Packit 6c4009
#ifndef N
Packit 6c4009
# define N 100
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
static pthread_mutex_t lock;
Packit 6c4009
Packit 6c4009
/* Each thread locks and the subsequently unlocks the lock, yielding
Packit 6c4009
   the smallest critical section possible.  After the unlock the thread
Packit 6c4009
   waits DELAY_NSEC nanoseconds before doing the lock and unlock again.
Packit 6c4009
   Every thread does this ROUNDS times.  The lock and unlock are
Packit 6c4009
   checked for errors.  */
Packit 6c4009
static void *
Packit 6c4009
tf (void *arg)
Packit 6c4009
{
Packit 6c4009
  int nr = (long int) arg;
Packit 6c4009
  int cnt;
Packit 6c4009
  struct timespec ts = { .tv_sec = 0, .tv_nsec = DELAY_NSEC };
Packit 6c4009
Packit 6c4009
  for (cnt = 0; cnt < ROUNDS; ++cnt)
Packit 6c4009
    {
Packit 6c4009
      if (pthread_mutex_lock (&lock) != 0)
Packit 6c4009
	{
Packit 6c4009
	  printf ("thread %d: failed to get the lock\n", nr);
Packit 6c4009
	  return (void *) 1l;
Packit 6c4009
	}
Packit 6c4009
Packit 6c4009
      if (pthread_mutex_unlock (&lock) != 0)
Packit 6c4009
	{
Packit 6c4009
	  printf ("thread %d: failed to release the lock\n", nr);
Packit 6c4009
	  return (void *) 1l;
Packit 6c4009
	}
Packit 6c4009
Packit 6c4009
      if ((ts.tv_sec > 0) || (ts.tv_nsec > 0))
Packit 6c4009
	nanosleep (&ts, NULL);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  return NULL;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
/* Setup and run N threads, where each thread does as described
Packit 6c4009
   in the above thread function.  The threads are given a minimal 1MiB
Packit 6c4009
   stack since they don't do anything between the lock and unlock.  */
Packit 6c4009
static int
Packit 6c4009
do_test (void)
Packit 6c4009
{
Packit 6c4009
  pthread_mutexattr_t a;
Packit 6c4009
Packit 6c4009
  if (pthread_mutexattr_init (&a) != 0)
Packit 6c4009
    {
Packit 6c4009
      puts ("mutexattr_init failed");
Packit 6c4009
      exit (1);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  if (pthread_mutexattr_settype (&a, TYPE) != 0)
Packit 6c4009
    {
Packit 6c4009
      puts ("mutexattr_settype failed");
Packit 6c4009
      exit (1);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  if (pthread_mutexattr_setrobust (&a, ROBUST) != 0)
Packit 6c4009
    {
Packit 6c4009
      puts ("mutexattr_setrobust failed");
Packit 6c4009
      exit (1);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
#ifdef ENABLE_PI
Packit 6c4009
  if (pthread_mutexattr_setprotocol (&a, PTHREAD_PRIO_INHERIT) != 0)
Packit 6c4009
    {
Packit 6c4009
      puts ("pthread_mutexattr_setprotocol failed");
Packit 6c4009
      return 1;
Packit 6c4009
    }
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
  int e = pthread_mutex_init (&lock, &a);
Packit 6c4009
  if (e != 0)
Packit 6c4009
    {
Packit 6c4009
#ifdef ENABLE_PI
Packit 6c4009
      if (e == ENOTSUP)
Packit 6c4009
	{
Packit 6c4009
	  puts ("PI mutexes unsupported");
Packit 6c4009
	  return 0;
Packit 6c4009
	}
Packit 6c4009
#endif
Packit 6c4009
      puts ("mutex_init failed");
Packit 6c4009
      return 1;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  if (pthread_mutexattr_destroy (&a) != 0)
Packit 6c4009
    {
Packit 6c4009
      puts ("mutexattr_destroy failed");
Packit 6c4009
      return 1;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  pthread_attr_t at;
Packit 6c4009
  pthread_t th[N];
Packit 6c4009
  int cnt;
Packit 6c4009
Packit 6c4009
  if (pthread_attr_init (&at) != 0)
Packit 6c4009
    {
Packit 6c4009
      puts ("attr_init failed");
Packit 6c4009
      return 1;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  if (pthread_attr_setstacksize (&at, 1 * 1024 * 1024) != 0)
Packit 6c4009
    {
Packit 6c4009
      puts ("attr_setstacksize failed");
Packit 6c4009
      return 1;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  if (pthread_mutex_lock (&lock) != 0)
Packit 6c4009
    {
Packit 6c4009
      puts ("locking in parent failed");
Packit 6c4009
      return 1;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  for (cnt = 0; cnt < N; ++cnt)
Packit 6c4009
    if (pthread_create (&th[cnt], &at, tf, (void *) (long int) cnt) != 0)
Packit 6c4009
      {
Packit 6c4009
	printf ("creating thread %d failed\n", cnt);
Packit 6c4009
	return 1;
Packit 6c4009
      }
Packit 6c4009
Packit 6c4009
  if (pthread_attr_destroy (&at) != 0)
Packit 6c4009
    {
Packit 6c4009
      puts ("attr_destroy failed");
Packit 6c4009
      return 1;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  if (pthread_mutex_unlock (&lock) != 0)
Packit 6c4009
    {
Packit 6c4009
      puts ("unlocking in parent failed");
Packit 6c4009
      return 1;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  for (cnt = 0; cnt < N; ++cnt)
Packit 6c4009
    if (pthread_join (th[cnt], NULL) != 0)
Packit 6c4009
      {
Packit 6c4009
	printf ("joining thread %d failed\n", cnt);
Packit 6c4009
	return 1;
Packit 6c4009
      }
Packit 6c4009
Packit 6c4009
  return 0;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
#define TIMEOUT 60
Packit 6c4009
#define TEST_FUNCTION do_test ()
Packit 6c4009
#include "../test-skeleton.c"