(root)/
glibc-2.38/
elf/
tst-single_threaded-pthread.c
       1  /* Test support for single-thread optimizations.  With threads.
       2     Copyright (C) 2020-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 <stddef.h>
      20  #include <stdio.h>
      21  #include <support/check.h>
      22  #include <support/namespace.h>
      23  #include <support/xdlfcn.h>
      24  #include <support/xthread.h>
      25  #include <sys/single_threaded.h>
      26  
      27  /* First barrier synchronizes main thread, thread 1, thread 2.  */
      28  static pthread_barrier_t barrier1;
      29  
      30  /* Second barrier synchronizes main thread, thread 2.  */
      31  static pthread_barrier_t barrier2;
      32  
      33  /* Defined in tst-single-threaded-mod1.so.  */
      34  _Bool single_threaded_1 (void);
      35  
      36  /* Initialized via dlsym.  */
      37  static _Bool (*single_threaded_2) (void);
      38  static _Bool (*single_threaded_3) (void);
      39  static _Bool (*single_threaded_4) (void);
      40  
      41  static void *
      42  threadfunc (void *closure)
      43  {
      44    TEST_VERIFY (!__libc_single_threaded);
      45    TEST_VERIFY (!single_threaded_1 ());
      46    TEST_VERIFY (!single_threaded_2 ());
      47  
      48    /* Wait until the main thread loads more functions.  */
      49    xpthread_barrier_wait (&barrier1);
      50  
      51    TEST_VERIFY (!__libc_single_threaded);
      52    TEST_VERIFY (!single_threaded_1 ());
      53    TEST_VERIFY (!single_threaded_2 ());
      54    TEST_VERIFY (!single_threaded_3 ());
      55    TEST_VERIFY (!single_threaded_4 ());
      56  
      57    /* Second thread waits on second barrier, too.  */
      58    if (closure != NULL)
      59      xpthread_barrier_wait (&barrier2);
      60    TEST_VERIFY (!__libc_single_threaded);
      61    TEST_VERIFY (!single_threaded_1 ());
      62    TEST_VERIFY (!single_threaded_2 ());
      63    TEST_VERIFY (!single_threaded_3 ());
      64    TEST_VERIFY (!single_threaded_4 ());
      65  
      66    return NULL;
      67  }
      68  
      69  /* Used for closure arguments to the subprocess function.  */
      70  static char expected_false = 0;
      71  static char expected_true = 1;
      72  
      73  /* A subprocess inherits currently inherits the single-threaded state
      74     of the parent process.  */
      75  static void
      76  subprocess (void *closure)
      77  {
      78    const char *expected = closure;
      79    TEST_COMPARE (__libc_single_threaded, *expected);
      80    TEST_COMPARE (single_threaded_1 (), *expected);
      81    if (single_threaded_2 != NULL)
      82      TEST_COMPARE (single_threaded_2 (), *expected);
      83    if (single_threaded_3 != NULL)
      84      TEST_COMPARE (single_threaded_3 (), *expected);
      85    if (single_threaded_4 != NULL)
      86      TEST_VERIFY (!single_threaded_4 ());
      87  }
      88  
      89  static int
      90  do_test (void)
      91  {
      92    printf ("info: main __libc_single_threaded address: %p\n",
      93            &__libc_single_threaded);
      94    TEST_VERIFY (__libc_single_threaded);
      95    TEST_VERIFY (single_threaded_1 ());
      96    support_isolate_in_subprocess (subprocess, &expected_true);
      97  
      98    void *handle_mod2 = xdlopen ("tst-single_threaded-mod2.so", RTLD_LAZY);
      99    single_threaded_2 = xdlsym (handle_mod2, "single_threaded_2");
     100    TEST_VERIFY (single_threaded_2 ());
     101  
     102    /* Two threads plus main thread.  */
     103    xpthread_barrier_init (&barrier1, NULL, 3);
     104  
     105    /* Main thread and second thread.  */
     106    xpthread_barrier_init (&barrier2, NULL, 2);
     107  
     108    pthread_t thr1 = xpthread_create (NULL, threadfunc, NULL);
     109    TEST_VERIFY (!__libc_single_threaded);
     110    TEST_VERIFY (!single_threaded_1 ());
     111    TEST_VERIFY (!single_threaded_2 ());
     112    support_isolate_in_subprocess (subprocess, &expected_false);
     113  
     114    pthread_t thr2 = xpthread_create (NULL, threadfunc, &thr2);
     115    TEST_VERIFY (!__libc_single_threaded);
     116    TEST_VERIFY (!single_threaded_1 ());
     117    TEST_VERIFY (!single_threaded_2 ());
     118    support_isolate_in_subprocess (subprocess, &expected_false);
     119  
     120    /* Delayed library load, while already multi-threaded.  */
     121    void *handle_mod3 = xdlopen ("tst-single_threaded-mod3.so", RTLD_LAZY);
     122    single_threaded_3 = xdlsym (handle_mod3, "single_threaded_3");
     123    TEST_VERIFY (!__libc_single_threaded);
     124    TEST_VERIFY (!single_threaded_1 ());
     125    TEST_VERIFY (!single_threaded_2 ());
     126    TEST_VERIFY (!single_threaded_3 ());
     127    support_isolate_in_subprocess (subprocess, &expected_false);
     128  
     129    /* Same with dlmopen.  */
     130    void *handle_mod4 = dlmopen (LM_ID_NEWLM, "tst-single_threaded-mod4.so",
     131                                 RTLD_LAZY);
     132    single_threaded_4 = xdlsym (handle_mod4, "single_threaded_4");
     133    TEST_VERIFY (!__libc_single_threaded);
     134    TEST_VERIFY (!single_threaded_1 ());
     135    TEST_VERIFY (!single_threaded_2 ());
     136    TEST_VERIFY (!single_threaded_3 ());
     137    TEST_VERIFY (!single_threaded_4 ());
     138    support_isolate_in_subprocess (subprocess, &expected_false);
     139  
     140    /* Run the newly loaded functions from the other threads as
     141       well.  */
     142    xpthread_barrier_wait (&barrier1);
     143    TEST_VERIFY (!__libc_single_threaded);
     144    TEST_VERIFY (!single_threaded_1 ());
     145    TEST_VERIFY (!single_threaded_2 ());
     146    TEST_VERIFY (!single_threaded_3 ());
     147    TEST_VERIFY (!single_threaded_4 ());
     148    support_isolate_in_subprocess (subprocess, &expected_false);
     149  
     150    /* Join first thread.  This should not bring us back into
     151       single-threaded mode.  */
     152    xpthread_join (thr1);
     153    TEST_VERIFY (!__libc_single_threaded);
     154    TEST_VERIFY (!single_threaded_1 ());
     155    TEST_VERIFY (!single_threaded_2 ());
     156    TEST_VERIFY (!single_threaded_3 ());
     157    TEST_VERIFY (!single_threaded_4 ());
     158    support_isolate_in_subprocess (subprocess, &expected_false);
     159  
     160    /* We may be back in single-threaded mode after joining both
     161       threads, but this is not guaranteed.  */
     162    xpthread_barrier_wait (&barrier2);
     163    xpthread_join (thr2);
     164    printf ("info: __libc_single_threaded after joining all threads: %d\n",
     165            __libc_single_threaded);
     166  
     167    xdlclose (handle_mod4);
     168    xdlclose (handle_mod3);
     169    xdlclose (handle_mod2);
     170  
     171    return 0;
     172  }
     173  
     174  #include <support/test-driver.c>