(root)/
glibc-2.38/
sysdeps/
pthread/
tst-mutex4.c
       1  /* Copyright (C) 2002-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 <stdint.h>
      21  #include <stdio.h>
      22  #include <stdlib.h>
      23  #include <string.h>
      24  #include <unistd.h>
      25  #include <sys/mman.h>
      26  #include <sys/wait.h>
      27  
      28  
      29  static int
      30  do_test (void)
      31  {
      32    size_t ps = sysconf (_SC_PAGESIZE);
      33    char tmpfname[] = "/tmp/tst-mutex4.XXXXXX";
      34    char data[ps];
      35    void *mem;
      36    int fd;
      37    pthread_mutex_t *m;
      38    pthread_mutexattr_t a;
      39    pid_t pid;
      40    char *p;
      41    int err;
      42    int s;
      43    pthread_barrier_t *b;
      44    pthread_barrierattr_t ba;
      45  
      46    fd = mkstemp (tmpfname);
      47    if (fd == -1)
      48      {
      49        printf ("cannot open temporary file: %m\n");
      50        return 1;
      51      }
      52  
      53    /* Make sure it is always removed.  */
      54    unlink (tmpfname);
      55  
      56    /* Create one page of data.  */
      57    memset (data, '\0', ps);
      58  
      59    /* Write the data to the file.  */
      60    if (write (fd, data, ps) != (ssize_t) ps)
      61      {
      62        puts ("short write");
      63        return 1;
      64      }
      65  
      66    mem = mmap (NULL, ps, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
      67    if (mem == MAP_FAILED)
      68      {
      69        printf ("mmap failed: %m\n");
      70        return 1;
      71      }
      72  
      73    m = (pthread_mutex_t *) (((uintptr_t) mem + __alignof (pthread_mutex_t) - 1)
      74  			   & ~(__alignof (pthread_mutex_t) - 1));
      75    b = (pthread_barrier_t *) (((uintptr_t) (m + 1)
      76  			      + __alignof (pthread_barrier_t) - 1)
      77  			     & ~(__alignof (pthread_barrier_t) - 1));
      78    p = (char *) (b + 1);
      79  
      80    if (pthread_mutexattr_init (&a) != 0)
      81      {
      82        puts ("mutexattr_init failed");
      83        return 1;
      84      }
      85  
      86    if (pthread_mutexattr_getpshared (&a, &s) != 0)
      87      {
      88        puts ("1st mutexattr_getpshared failed");
      89        return 1;
      90      }
      91  
      92    if (s != PTHREAD_PROCESS_PRIVATE)
      93      {
      94        puts ("default pshared value wrong");
      95        return 1;
      96      }
      97  
      98    if (pthread_mutexattr_setpshared (&a, PTHREAD_PROCESS_SHARED) != 0)
      99      {
     100        puts ("mutexattr_setpshared failed");
     101        return 1;
     102      }
     103  
     104    if (pthread_mutexattr_getpshared (&a, &s) != 0)
     105      {
     106        puts ("2nd mutexattr_getpshared failed");
     107        return 1;
     108      }
     109  
     110    if (s != PTHREAD_PROCESS_SHARED)
     111      {
     112        puts ("pshared value after setpshared call wrong");
     113        return 1;
     114      }
     115  
     116  #ifdef ENABLE_PI
     117    if (pthread_mutexattr_setprotocol (&a, PTHREAD_PRIO_INHERIT) != 0)
     118      {
     119        puts ("pthread_mutexattr_setprotocol failed");
     120        return 1;
     121      }
     122  #endif
     123  
     124    if ((err = pthread_mutex_init (m, &a)) != 0)
     125      {
     126  #ifdef ENABLE_PI
     127        if (err == ENOTSUP)
     128  	{
     129  	  puts ("PI mutexes unsupported");
     130  	  return 0;
     131  	}
     132  #endif
     133        puts ("mutex_init failed");
     134        return 1;
     135      }
     136  
     137    if (pthread_mutex_lock (m) != 0)
     138      {
     139        puts ("mutex_lock failed");
     140        return 1;
     141      }
     142  
     143    if (pthread_mutexattr_destroy (&a) != 0)
     144      {
     145        puts ("mutexattr_destroy failed");
     146        return 1;
     147      }
     148  
     149    if (pthread_barrierattr_init (&ba) != 0)
     150      {
     151        puts ("barrierattr_init failed");
     152        return 1;
     153      }
     154  
     155    if (pthread_barrierattr_setpshared (&ba, PTHREAD_PROCESS_SHARED) != 0)
     156      {
     157        puts ("barrierattr_setpshared failed");
     158        return 1;
     159      }
     160  
     161    if (pthread_barrier_init (b, &ba, 2) != 0)
     162      {
     163        puts ("barrier_init failed");
     164        return 1;
     165      }
     166  
     167    if (pthread_barrierattr_destroy (&ba) != 0)
     168      {
     169        puts ("barrierattr_destroy failed");
     170        return 1;
     171      }
     172  
     173    err = pthread_mutex_trylock (m);
     174    if (err == 0)
     175      {
     176        puts ("mutex_trylock succeeded");
     177        return 1;
     178      }
     179    else if (err != EBUSY)
     180      {
     181        puts ("mutex_trylock didn't return EBUSY");
     182        return 1;
     183      }
     184  
     185    *p = 0;
     186  
     187    if (pthread_mutex_unlock (m) != 0)
     188      {
     189        puts ("parent: 1st mutex_unlock failed");
     190        return 1;
     191      }
     192  
     193    puts ("going to fork now");
     194    pid = fork ();
     195    if (pid == -1)
     196      {
     197        puts ("fork failed");
     198        return 1;
     199      }
     200    else if (pid == 0)
     201      {
     202        if (pthread_mutex_lock (m) != 0)
     203  	{
     204  	  puts ("child: mutex_lock failed");
     205  	  return 1;
     206  	}
     207  
     208        int e = pthread_barrier_wait (b);
     209        if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
     210  	{
     211  	  puts ("child: barrier_wait failed");
     212  	  return 1;
     213  	}
     214  
     215        if ((*p)++ != 0)
     216  	{
     217  	  puts ("child: *p != 0");
     218  	  return 1;
     219  	}
     220  
     221        if (pthread_mutex_unlock (m) != 0)
     222  	{
     223  	  puts ("child: mutex_unlock failed");
     224  	  return 1;
     225  	}
     226  
     227        puts ("child done");
     228      }
     229    else
     230      {
     231        int e = pthread_barrier_wait (b);
     232        if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
     233  	{
     234  	  puts ("parent: barrier_wait failed");
     235  	  return 1;
     236  	}
     237  
     238        if (pthread_mutex_lock (m) != 0)
     239  	{
     240  	  puts ("parent: 2nd mutex_lock failed");
     241  	  return 1;
     242  	}
     243  
     244        if (*p != 1)
     245  	{
     246  	  puts ("*p != 1");
     247  	  return 1;
     248  	}
     249  
     250        if (pthread_mutex_unlock (m) != 0)
     251  	{
     252  	  puts ("parent: 2nd mutex_unlock failed");
     253  	  return 1;
     254  	}
     255  
     256        if (pthread_mutex_destroy (m) != 0)
     257  	{
     258  	  puts ("mutex_destroy failed");
     259  	  return 1;
     260  	}
     261  
     262        if (pthread_barrier_destroy (b) != 0)
     263  	{
     264  	  puts ("barrier_destroy failed");
     265  	  return 1;
     266  	}
     267  
     268        puts ("parent done");
     269      }
     270  
     271    return 0;
     272  }
     273  
     274  #define TEST_FUNCTION do_test ()
     275  #include "../test-skeleton.c"