(root)/
glibc-2.38/
nptl/
test-mutex-printers.c
       1  /* Helper program for testing the pthread_mutex_t pretty printer.
       2  
       3     Copyright (C) 2016-2023 Free Software Foundation, Inc.
       4     This file is part of the GNU C Library.
       5  
       6     The GNU C Library is free software; you can redistribute it and/or
       7     modify it under the terms of the GNU Lesser General Public
       8     License as published by the Free Software Foundation; either
       9     version 2.1 of the License, or (at your option) any later version.
      10  
      11     The GNU C Library is distributed in the hope that it will be useful,
      12     but WITHOUT ANY WARRANTY; without even the implied warranty of
      13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14     Lesser General Public License for more details.
      15  
      16     You should have received a copy of the GNU Lesser General Public
      17     License along with the GNU C Library; if not, see
      18     <https://www.gnu.org/licenses/>.  */
      19  
      20  /* Keep the calls to the pthread_* functions on separate lines to make it easy
      21     to advance through the program using the gdb 'next' command.  */
      22  
      23  #include <stdlib.h>
      24  #include <errno.h>
      25  #include <pthread.h>
      26  
      27  #define PASS 0
      28  #define FAIL 1
      29  
      30  static int test_status_destroyed (pthread_mutex_t *mutex);
      31  static int test_status_no_robust (pthread_mutex_t *mutex,
      32  				  pthread_mutexattr_t *attr);
      33  static int test_status_robust (pthread_mutex_t *mutex,
      34  			       pthread_mutexattr_t *attr);
      35  static int test_locking_state_robust (pthread_mutex_t *mutex);
      36  static void *thread_func (void *arg);
      37  static int test_recursive_locks (pthread_mutex_t *mutex,
      38  				 pthread_mutexattr_t *attr);
      39  
      40  int
      41  main (void)
      42  {
      43    pthread_mutex_t mutex;
      44    pthread_mutexattr_t attr;
      45    int result = FAIL;
      46  
      47    if (pthread_mutexattr_init (&attr) == 0
      48        && test_status_destroyed (&mutex) == PASS
      49        && test_status_no_robust (&mutex, &attr) == PASS
      50        && test_status_robust (&mutex, &attr) == PASS
      51        && test_recursive_locks (&mutex, &attr) == PASS)
      52      result = PASS;
      53    /* Else, one of the pthread_mutex* functions failed.  */
      54  
      55    return result;
      56  }
      57  
      58  /* Initializes MUTEX, then destroys it.  */
      59  static int
      60  test_status_destroyed (pthread_mutex_t *mutex)
      61  {
      62    int result = FAIL;
      63  
      64    if (pthread_mutex_init (mutex, NULL) == 0
      65        && pthread_mutex_destroy (mutex) == 0)
      66      result = PASS; /* Test status (destroyed).  */
      67  
      68    return result;
      69  }
      70  
      71  /* Tests locking of non-robust mutexes.  */
      72  static int
      73  test_status_no_robust (pthread_mutex_t *mutex, pthread_mutexattr_t *attr)
      74  {
      75    int result = FAIL;
      76  
      77    if (pthread_mutexattr_setrobust (attr, PTHREAD_MUTEX_STALLED) == 0
      78        && pthread_mutex_init (mutex, attr) == 0
      79        && pthread_mutex_lock (mutex) == 0 /* Test status (non-robust).  */
      80        && pthread_mutex_unlock (mutex) == 0
      81        && pthread_mutex_destroy (mutex) == 0)
      82      result = PASS;
      83  
      84    return result;
      85  }
      86  
      87  /* Tests locking of robust mutexes.  */
      88  static int
      89  test_status_robust (pthread_mutex_t *mutex, pthread_mutexattr_t *attr)
      90  {
      91    int result = FAIL;
      92  
      93    if (pthread_mutexattr_setrobust (attr, PTHREAD_MUTEX_ROBUST) == 0
      94        && pthread_mutex_init (mutex, attr) == 0
      95        && test_locking_state_robust (mutex) == PASS /* Test status (robust).  */
      96        && pthread_mutex_destroy (mutex) == 0)
      97      result = PASS;
      98  
      99    return result;
     100  }
     101  
     102  /* Tests locking and state corruption of robust mutexes.  We'll mark it as
     103     inconsistent, then not recoverable.  */
     104  static int
     105  test_locking_state_robust (pthread_mutex_t *mutex)
     106  {
     107    int result = FAIL;
     108    pthread_t thread;
     109  
     110    if (pthread_create (&thread, NULL, thread_func, mutex) == 0 /* Create.  */
     111        && pthread_join (thread, NULL) == 0
     112        && pthread_mutex_lock (mutex) == EOWNERDEAD /* Test locking (robust).  */
     113        && pthread_mutex_unlock (mutex) == 0)
     114      result = PASS;
     115  
     116    return result;
     117  }
     118  
     119  /* Function to be called by the child thread when testing robust mutexes.  */
     120  static void *
     121  thread_func (void *arg)
     122  {
     123    pthread_mutex_t *mutex = (pthread_mutex_t *)arg;
     124  
     125    if (pthread_mutex_lock (mutex) != 0) /* Thread function.  */
     126      exit (FAIL);
     127  
     128    /* Thread terminates without unlocking the mutex, thus marking it as
     129       inconsistent.  */
     130    return NULL;
     131  }
     132  
     133  /* Tests locking the mutex multiple times in a row.  */
     134  static int
     135  test_recursive_locks (pthread_mutex_t *mutex, pthread_mutexattr_t *attr)
     136  {
     137    int result = FAIL;
     138  
     139    if (pthread_mutexattr_settype (attr, PTHREAD_MUTEX_RECURSIVE) == 0
     140        && pthread_mutex_init (mutex, attr) == 0
     141        && pthread_mutex_lock (mutex) == 0
     142        && pthread_mutex_lock (mutex) == 0
     143        && pthread_mutex_lock (mutex) == 0 /* Test recursive locks.  */
     144        && pthread_mutex_unlock (mutex) == 0
     145        && pthread_mutex_unlock (mutex) == 0
     146        && pthread_mutex_unlock (mutex) == 0
     147        && pthread_mutex_destroy (mutex) == 0)
     148      result = PASS;
     149  
     150    return result;
     151  }