(root)/
glibc-2.38/
sysdeps/
pthread/
tst-create1.c
       1  /* Verify that pthread_create does not deadlock when ctors take locks.
       2     Copyright (C) 2021-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  #include <stdio.h>
      20  #include <support/xdlfcn.h>
      21  #include <support/xthread.h>
      22  
      23  /*
      24  Check if ctor and pthread_create deadlocks in
      25  
      26  thread 1: dlopen -> ctor -> lock(user_lock)
      27  thread 2: lock(user_lock) -> pthread_create
      28  
      29  or in
      30  
      31  thread 1: dlclose -> dtor -> lock(user_lock)
      32  thread 2: lock(user_lock) -> pthread_create
      33  */
      34  
      35  static pthread_barrier_t bar_ctor;
      36  static pthread_barrier_t bar_ctor_finish;
      37  static pthread_barrier_t bar_dtor;
      38  static pthread_mutex_t user_lock = PTHREAD_MUTEX_INITIALIZER;
      39  
      40  void
      41  ctor (void)
      42  {
      43    xpthread_barrier_wait (&bar_ctor);
      44    dprintf (1, "thread 1: in ctor: started.\n");
      45    xpthread_mutex_lock (&user_lock);
      46    dprintf (1, "thread 1: in ctor: locked user_lock.\n");
      47    xpthread_mutex_unlock (&user_lock);
      48    dprintf (1, "thread 1: in ctor: unlocked user_lock.\n");
      49    dprintf (1, "thread 1: in ctor: done.\n");
      50    xpthread_barrier_wait (&bar_ctor_finish);
      51  }
      52  
      53  void
      54  dtor (void)
      55  {
      56    xpthread_barrier_wait (&bar_dtor);
      57    dprintf (1, "thread 1: in dtor: started.\n");
      58    xpthread_mutex_lock (&user_lock);
      59    dprintf (1, "thread 1: in dtor: locked user_lock.\n");
      60    xpthread_mutex_unlock (&user_lock);
      61    dprintf (1, "thread 1: in dtor: unlocked user_lock.\n");
      62    dprintf (1, "thread 1: in dtor: done.\n");
      63  }
      64  
      65  static void *
      66  thread3 (void *a)
      67  {
      68    dprintf (1, "thread 3: started.\n");
      69    dprintf (1, "thread 3: done.\n");
      70    return 0;
      71  }
      72  
      73  static void *
      74  thread2 (void *a)
      75  {
      76    pthread_t t3;
      77    dprintf (1, "thread 2: started.\n");
      78  
      79    xpthread_mutex_lock (&user_lock);
      80    dprintf (1, "thread 2: locked user_lock.\n");
      81    xpthread_barrier_wait (&bar_ctor);
      82    t3 = xpthread_create (0, thread3, 0);
      83    xpthread_mutex_unlock (&user_lock);
      84    dprintf (1, "thread 2: unlocked user_lock.\n");
      85    xpthread_join (t3);
      86    xpthread_barrier_wait (&bar_ctor_finish);
      87  
      88    xpthread_mutex_lock (&user_lock);
      89    dprintf (1, "thread 2: locked user_lock.\n");
      90    xpthread_barrier_wait (&bar_dtor);
      91    t3 = xpthread_create (0, thread3, 0);
      92    xpthread_mutex_unlock (&user_lock);
      93    dprintf (1, "thread 2: unlocked user_lock.\n");
      94    xpthread_join (t3);
      95  
      96    dprintf (1, "thread 2: done.\n");
      97    return 0;
      98  }
      99  
     100  static void
     101  thread1 (void)
     102  {
     103    dprintf (1, "thread 1: started.\n");
     104    xpthread_barrier_init (&bar_ctor, NULL, 2);
     105    xpthread_barrier_init (&bar_ctor_finish, NULL, 2);
     106    xpthread_barrier_init (&bar_dtor, NULL, 2);
     107    pthread_t t2 = xpthread_create (0, thread2, 0);
     108    void *p = xdlopen ("tst-create1mod.so", RTLD_NOW | RTLD_GLOBAL);
     109    dprintf (1, "thread 1: dlopen done.\n");
     110    xdlclose (p);
     111    dprintf (1, "thread 1: dlclose done.\n");
     112    xpthread_join (t2);
     113    dprintf (1, "thread 1: done.\n");
     114  }
     115  
     116  static int
     117  do_test (void)
     118  {
     119    thread1 ();
     120    return 0;
     121  }
     122  
     123  #include <support/test-driver.c>