diff options
Diffstat (limited to 'test/nptl/tst-cond12.c')
| -rw-r--r-- | test/nptl/tst-cond12.c | 196 | 
1 files changed, 196 insertions, 0 deletions
| diff --git a/test/nptl/tst-cond12.c b/test/nptl/tst-cond12.c new file mode 100644 index 000000000..03e4881c9 --- /dev/null +++ b/test/nptl/tst-cond12.c @@ -0,0 +1,196 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. +   This file is part of the GNU C Library. +   Contributed by Ulrich Drepper <drepper@redhat.com>, 2003. + +   The GNU C Library is free software; you can redistribute it and/or +   modify it under the terms of the GNU Lesser General Public +   License as published by the Free Software Foundation; either +   version 2.1 of the License, or (at your option) any later version. + +   The GNU C Library is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +   Lesser General Public License for more details. + +   You should have received a copy of the GNU Lesser General Public +   License along with the GNU C Library; if not, write to the Free +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +   02111-1307 USA.  */ + +#include <errno.h> +#include <pthread.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/mman.h> +#include <sys/wait.h> + + +static char fname[] = "/tmp/tst-cond12-XXXXXX"; +static int fd; + + +static void prepare (void); +#define PREPARE(argc, argv) prepare () + +static int do_test (void); +#define TEST_FUNCTION do_test () + +#include "../test-skeleton.c" + + +static void +prepare (void) +{ +  fd = mkstemp (fname); +  if (fd == -1) +    { +      printf ("mkstemp failed: %m\n"); +      exit (1); +    } +  add_temp_file (fname); +  if (ftruncate (fd, 1000) < 0) +    { +      printf ("ftruncate failed: %m\n"); +      exit (1); +    } +} + + +static int +do_test (void) +{ +  struct +  { +    pthread_mutex_t m; +    pthread_cond_t c; +    int var; +  } *p = mmap (NULL, sizeof (*p), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); +  if (p == MAP_FAILED) +    { +      printf ("initial mmap failed: %m\n"); +      return 1; +    } + +  pthread_mutexattr_t ma; +  if (pthread_mutexattr_init (&ma) != 0) +    { +      puts ("mutexattr_init failed"); +      return 1; +    } +  if (pthread_mutexattr_setpshared (&ma, 1) != 0) +    { +      puts ("mutexattr_setpshared failed"); +      return 1; +    } +  if (pthread_mutex_init (&p->m, &ma) != 0) +    { +      puts ("mutex_init failed"); +      return 1; +    } +  if (pthread_mutexattr_destroy (&ma) != 0) +    { +      puts ("mutexattr_destroy failed"); +      return 1; +    } + +  pthread_condattr_t ca; +  if (pthread_condattr_init (&ca) != 0) +    { +      puts ("condattr_init failed"); +      return 1; +    } +  if (pthread_condattr_setpshared (&ca, 1) != 0) +    { +      puts ("condattr_setpshared failed"); +      return 1; +    } +  if (pthread_cond_init (&p->c, &ca) != 0) +    { +      puts ("mutex_init failed"); +      return 1; +    } +  if (pthread_condattr_destroy (&ca) != 0) +    { +      puts ("condattr_destroy failed"); +      return 1; +    } + +  if (pthread_mutex_lock (&p->m) != 0) +    { +      puts ("initial mutex_lock failed"); +      return 1; +    } + +  p->var = 42; + +  pid_t pid = fork (); +  if (pid == -1) +    { +      printf ("fork failed: %m\n"); +      return 1; +    } + +  if (pid == 0) +    { +      void *oldp = p; +      p = mmap (NULL, sizeof (*p), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); + +      if (p == oldp) +	{ +	  puts ("child: mapped to same address"); +	  kill (getppid (), SIGKILL); +	  exit (1); +	} + +      munmap (oldp, sizeof (*p)); + +      if (pthread_mutex_lock (&p->m) != 0) +	{ +	  puts ("child: mutex_lock failed"); +	  kill (getppid (), SIGKILL); +	  exit (1); +	} + +      p->var = 0; + +#ifndef USE_COND_SIGNAL +      if (pthread_cond_broadcast (&p->c) != 0) +	{ +	  puts ("child: cond_broadcast failed"); +	  kill (getppid (), SIGKILL); +	  exit (1); +	} +#else +      if (pthread_cond_signal (&p->c) != 0) +	{ +	  puts ("child: cond_signal failed"); +	  kill (getppid (), SIGKILL); +	  exit (1); +	} +#endif + +      if (pthread_mutex_unlock (&p->m) != 0) +	{ +	  puts ("child: mutex_unlock failed"); +	  kill (getppid (), SIGKILL); +	  exit (1); +	} + +      exit (0); +    } + +  do +    pthread_cond_wait (&p->c, &p->m); +  while (p->var != 0); + +  if (TEMP_FAILURE_RETRY (waitpid (pid, NULL, 0)) != pid) +    { +      printf ("waitpid failed: %m\n"); +      kill (pid, SIGKILL); +      return 1; +    } + +  return 0; +} | 
