1 /* Helper for exit/dlclose race test (Bug 22180).
2    Copyright (C) 2017-2022 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 <stdbool.h>
21 #include <stdlib.h>
22 #include <semaphore.h>
23 #include <unistd.h>
24 #include <support/check.h>
25 #include <support/xthread.h>
26 
27 /* Semaphore defined in executable to ensure we have a happens-before
28    between the first function starting and exit being called.  */
29 extern sem_t order1;
30 
31 /* Semaphore defined in executable to ensure we have a happens-before
32    between the second function starting and the first function returning.  */
33 extern sem_t order2;
34 
35 /* glibc function for registering DSO-specific exit functions.  */
36 extern int __cxa_atexit (void (*func) (void *), void *arg, void *dso_handle);
37 
38 /* Hidden compiler handle to this shared object.  */
39 extern void *__dso_handle __attribute__ ((__weak__));
40 
41 static void
first(void * start)42 first (void *start)
43 {
44   /* Let the exiting thread run.  */
45   sem_post (&order1);
46 
47   /* Wait for exiting thread to finish.  */
48   sem_wait (&order2);
49 
50   printf ("first\n");
51 }
52 
53 static void
second(void * start)54 second (void *start)
55 {
56   /* We may be called from different threads.
57      This lock protects called.  */
58   static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
59   static bool called = false;
60 
61   xpthread_mutex_lock (&mtx);
62   if (called)
63     FAIL_EXIT1 ("second called twice!");
64 
65   called = true;
66   xpthread_mutex_unlock (&mtx);
67 
68   printf ("second\n");
69 }
70 
71 
72 __attribute__ ((constructor)) static void
constructor(void)73 constructor (void)
74 {
75   sem_init (&order1, 0, 0);
76   sem_init (&order2, 0, 0);
77   __cxa_atexit (second, NULL, __dso_handle);
78   __cxa_atexit (first, NULL, __dso_handle);
79 }
80