(root)/
glibc-2.38/
sysdeps/
pthread/
tst-cond12.c
       1  /* Copyright (C) 2003-2023 Free Software Foundation, Inc.
       2     This file is part of the GNU C Library.
       3  
       4     The GNU C Library is free software; you can redistribute it and/or
       5     modify it under the terms of the GNU Lesser General Public
       6     License as published by the Free Software Foundation; either
       7     version 2.1 of the License, or (at your option) any later version.
       8  
       9     The GNU C Library is distributed in the hope that it will be useful,
      10     but WITHOUT ANY WARRANTY; without even the implied warranty of
      11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12     Lesser General Public License for more details.
      13  
      14     You should have received a copy of the GNU Lesser General Public
      15     License along with the GNU C Library; if not, see
      16     <https://www.gnu.org/licenses/>.  */
      17  
      18  #include <errno.h>
      19  #include <pthread.h>
      20  #include <signal.h>
      21  #include <stdio.h>
      22  #include <stdlib.h>
      23  #include <unistd.h>
      24  #include <sys/mman.h>
      25  #include <sys/wait.h>
      26  
      27  
      28  static char fname[] = "/tmp/tst-cond12-XXXXXX";
      29  static int fd;
      30  
      31  
      32  static void prepare (void);
      33  #define PREPARE(argc, argv) prepare ()
      34  
      35  static int do_test (void);
      36  #define TEST_FUNCTION do_test ()
      37  
      38  #include "../test-skeleton.c"
      39  
      40  
      41  static void
      42  prepare (void)
      43  {
      44    fd = mkstemp (fname);
      45    if (fd == -1)
      46      {
      47        printf ("mkstemp failed: %m\n");
      48        exit (1);
      49      }
      50    add_temp_file (fname);
      51    if (ftruncate (fd, 1000) < 0)
      52      {
      53        printf ("ftruncate failed: %m\n");
      54        exit (1);
      55      }
      56  }
      57  
      58  
      59  static int
      60  do_test (void)
      61  {
      62    struct
      63    {
      64      pthread_mutex_t m;
      65      pthread_cond_t c;
      66      int var;
      67    } *p = mmap (NULL, sizeof (*p), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
      68    if (p == MAP_FAILED)
      69      {
      70        printf ("initial mmap failed: %m\n");
      71        return 1;
      72      }
      73  
      74    pthread_mutexattr_t ma;
      75    if (pthread_mutexattr_init (&ma) != 0)
      76      {
      77        puts ("mutexattr_init failed");
      78        return 1;
      79      }
      80    if (pthread_mutexattr_setpshared (&ma, 1) != 0)
      81      {
      82        puts ("mutexattr_setpshared failed");
      83        return 1;
      84      }
      85    if (pthread_mutex_init (&p->m, &ma) != 0)
      86      {
      87        puts ("mutex_init failed");
      88        return 1;
      89      }
      90    if (pthread_mutexattr_destroy (&ma) != 0)
      91      {
      92        puts ("mutexattr_destroy failed");
      93        return 1;
      94      }
      95  
      96    pthread_condattr_t ca;
      97    if (pthread_condattr_init (&ca) != 0)
      98      {
      99        puts ("condattr_init failed");
     100        return 1;
     101      }
     102    if (pthread_condattr_setpshared (&ca, 1) != 0)
     103      {
     104        puts ("condattr_setpshared failed");
     105        return 1;
     106      }
     107    if (pthread_cond_init (&p->c, &ca) != 0)
     108      {
     109        puts ("mutex_init failed");
     110        return 1;
     111      }
     112    if (pthread_condattr_destroy (&ca) != 0)
     113      {
     114        puts ("condattr_destroy failed");
     115        return 1;
     116      }
     117  
     118    if (pthread_mutex_lock (&p->m) != 0)
     119      {
     120        puts ("initial mutex_lock failed");
     121        return 1;
     122      }
     123  
     124    p->var = 42;
     125  
     126    pid_t pid = fork ();
     127    if (pid == -1)
     128      {
     129        printf ("fork failed: %m\n");
     130        return 1;
     131      }
     132  
     133    if (pid == 0)
     134      {
     135        void *oldp = p;
     136        p = mmap (NULL, sizeof (*p), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
     137  
     138        if (p == oldp)
     139  	{
     140  	  puts ("child: mapped to same address");
     141  	  kill (getppid (), SIGKILL);
     142  	  exit (1);
     143  	}
     144  
     145        munmap (oldp, sizeof (*p));
     146  
     147        if (pthread_mutex_lock (&p->m) != 0)
     148  	{
     149  	  puts ("child: mutex_lock failed");
     150  	  kill (getppid (), SIGKILL);
     151  	  exit (1);
     152  	}
     153  
     154        p->var = 0;
     155  
     156  #ifndef USE_COND_SIGNAL
     157        if (pthread_cond_broadcast (&p->c) != 0)
     158  	{
     159  	  puts ("child: cond_broadcast failed");
     160  	  kill (getppid (), SIGKILL);
     161  	  exit (1);
     162  	}
     163  #else
     164        if (pthread_cond_signal (&p->c) != 0)
     165  	{
     166  	  puts ("child: cond_signal failed");
     167  	  kill (getppid (), SIGKILL);
     168  	  exit (1);
     169  	}
     170  #endif
     171  
     172        if (pthread_mutex_unlock (&p->m) != 0)
     173  	{
     174  	  puts ("child: mutex_unlock failed");
     175  	  kill (getppid (), SIGKILL);
     176  	  exit (1);
     177  	}
     178  
     179        exit (0);
     180      }
     181  
     182    do
     183      pthread_cond_wait (&p->c, &p->m);
     184    while (p->var != 0);
     185  
     186    if (TEMP_FAILURE_RETRY (waitpid (pid, NULL, 0)) != pid)
     187      {
     188        printf ("waitpid failed: %m\n");
     189        kill (pid, SIGKILL);
     190        return 1;
     191      }
     192  
     193    return 0;
     194  }