(root)/
glibc-2.38/
sysdeps/
pthread/
tst-mutex9.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 <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/time.h>
      27  #include <sys/wait.h>
      28  #include <support/check.h>
      29  #include <support/timespec.h>
      30  #include <support/xunistd.h>
      31  #include <support/xthread.h>
      32  
      33  #ifdef ENABLE_PP
      34  #include "tst-tpp.h"
      35  #endif
      36  
      37  
      38  /* A bogus clock value that tells run_test to use pthread_mutex_timedlock
      39     rather than pthread_mutex_clocklock.  */
      40  #define CLOCK_USE_TIMEDLOCK (-1)
      41  
      42  static void
      43  do_test_clock (clockid_t clockid, int tmo_result)
      44  {
      45    const clockid_t clockid_for_get =
      46      (clockid == CLOCK_USE_TIMEDLOCK) ? CLOCK_REALTIME : clockid;
      47    size_t ps = sysconf (_SC_PAGESIZE);
      48    char tmpfname[] = "/tmp/tst-mutex9.XXXXXX";
      49    char data[ps];
      50    void *mem;
      51    int fd;
      52    pthread_mutex_t *m;
      53    pthread_mutexattr_t a;
      54    pid_t pid;
      55  
      56    fd = mkstemp (tmpfname);
      57    if (fd == -1)
      58        FAIL_EXIT1 ("cannot open temporary file: %m\n");
      59  
      60    /* Make sure it is always removed.  */
      61    unlink (tmpfname);
      62  
      63    /* Create one page of data.  */
      64    memset (data, '\0', ps);
      65  
      66    /* Write the data to the file.  */
      67    xwrite (fd, data, ps);
      68  
      69    mem = xmmap (NULL, ps, PROT_READ | PROT_WRITE, MAP_SHARED, fd);
      70  
      71    m = (pthread_mutex_t *) (((uintptr_t) mem + __alignof (pthread_mutex_t))
      72  			   & ~(__alignof (pthread_mutex_t) - 1));
      73  
      74    TEST_COMPARE (pthread_mutexattr_init (&a), 0);
      75  
      76    TEST_COMPARE (pthread_mutexattr_setpshared (&a, PTHREAD_PROCESS_SHARED), 0);
      77  
      78    TEST_COMPARE (pthread_mutexattr_settype (&a, PTHREAD_MUTEX_RECURSIVE), 0);
      79  
      80  #if defined ENABLE_PI
      81    TEST_COMPARE (pthread_mutexattr_setprotocol (&a, PTHREAD_PRIO_INHERIT), 0);
      82  #elif defined ENABLE_PP
      83    TEST_COMPARE (pthread_mutexattr_setprotocol (&a, PTHREAD_PRIO_PROTECT), 0);
      84    TEST_COMPARE (pthread_mutexattr_setprioceiling (&a, 6), 0);
      85  #endif
      86  
      87    int e;
      88    if ((e = pthread_mutex_init (m, &a)) != 0)
      89      {
      90  #ifdef ENABLE_PI
      91        if (e == ENOTSUP)
      92          FAIL_UNSUPPORTED ("PI mutexes unsupported");
      93  #endif
      94        FAIL_EXIT1 ("mutex_init failed");
      95      }
      96  
      97    TEST_COMPARE (pthread_mutex_lock (m), 0);
      98  
      99    TEST_COMPARE (pthread_mutexattr_destroy (&a), 0);
     100  
     101    puts ("going to fork now");
     102    pid = xfork ();
     103    if (pid == 0)
     104      {
     105        if (pthread_mutex_trylock (m) == 0)
     106          FAIL_EXIT1 ("child: mutex_trylock succeeded");
     107  
     108        if (pthread_mutex_unlock (m) == 0)
     109          FAIL_EXIT1 ("child: mutex_unlock succeeded");
     110  
     111        const struct timespec ts = timespec_add (xclock_now (clockid_for_get),
     112                                                 make_timespec (0, 500000000));
     113  
     114        if (clockid == CLOCK_USE_TIMEDLOCK)
     115          TEST_COMPARE (pthread_mutex_timedlock (m, &ts), tmo_result);
     116        else
     117          TEST_COMPARE (pthread_mutex_clocklock (m, clockid, &ts), tmo_result);
     118  
     119        alarm (1);
     120  
     121        pthread_mutex_lock (m);
     122  
     123        puts ("child: mutex_lock returned");
     124  
     125        exit (0);
     126      }
     127  
     128    sleep (2);
     129  
     130    int status;
     131    if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid)
     132      FAIL_EXIT1 ("waitpid failed");
     133    if (! WIFSIGNALED (status))
     134      FAIL_EXIT1 ("child not killed by signal");
     135    TEST_COMPARE (WTERMSIG (status), SIGALRM);
     136  }
     137  
     138  static int
     139  do_test (void)
     140  {
     141  #ifdef ENABLE_PP
     142    init_tpp_test ();
     143  #endif
     144  
     145    int monotonic_result =
     146  #ifdef ENABLE_PI
     147      support_mutex_pi_monotonic () ? ETIMEDOUT : EINVAL;
     148  #else
     149      ETIMEDOUT;
     150  #endif
     151  
     152    do_test_clock (CLOCK_USE_TIMEDLOCK, ETIMEDOUT);
     153    do_test_clock (CLOCK_REALTIME, ETIMEDOUT);
     154    do_test_clock (CLOCK_MONOTONIC, monotonic_result);
     155    return 0;
     156  }
     157  
     158  #include <support/test-driver.c>