1 /* Test malloc with concurrent thread termination.
2 Copyright (C) 2015 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
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.
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.
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 <http://www.gnu.org/licenses/>. */
19 /* This thread spawns a number of outer threads, equal to the arena
20 limit. The outer threads run a loop which start and join two
21 different kinds of threads: the first kind allocates (attaching an
22 arena to the thread; malloc_first_thread) and waits, the second
23 kind waits and allocates (wait_first_threads). Both kinds of
24 threads exit immediately after waiting. The hope is that this will
25 exhibit races in thread termination and arena management,
26 particularly related to the arena free list. */
37 static bool termination_requested
;
38 static int inner_thread_count
= 4;
39 static size_t malloc_size
= 32;
42 __attribute__ ((noinline
, noclone
))
43 unoptimized_free (void *ptr
)
49 malloc_first_thread (void * closure
)
51 pthread_barrier_t
*barrier
= closure
;
52 void *ptr
= malloc (malloc_size
);
55 printf ("error: malloc: %m\n");
58 int ret
= pthread_barrier_wait (barrier
);
59 if (ret
!= 0 && ret
!= PTHREAD_BARRIER_SERIAL_THREAD
)
62 printf ("error: pthread_barrier_wait: %m\n");
65 unoptimized_free (ptr
);
70 wait_first_thread (void * closure
)
72 pthread_barrier_t
*barrier
= closure
;
73 int ret
= pthread_barrier_wait (barrier
);
74 if (ret
!= 0 && ret
!= PTHREAD_BARRIER_SERIAL_THREAD
)
77 printf ("error: pthread_barrier_wait: %m\n");
80 void *ptr
= malloc (malloc_size
);
83 printf ("error: malloc: %m\n");
86 unoptimized_free (ptr
);
91 outer_thread (void *closure
)
93 pthread_t
*threads
= calloc (sizeof (*threads
), inner_thread_count
);
96 printf ("error: calloc: %m\n");
100 while (!__atomic_load_n (&termination_requested
, __ATOMIC_RELAXED
))
102 pthread_barrier_t barrier
;
103 int ret
= pthread_barrier_init (&barrier
, NULL
, inner_thread_count
+ 1);
107 printf ("pthread_barrier_init: %m\n");
110 for (int i
= 0; i
< inner_thread_count
; ++i
)
112 void *(*func
) (void *);
114 func
= malloc_first_thread
;
116 func
= wait_first_thread
;
117 ret
= pthread_create (threads
+ i
, NULL
, func
, &barrier
);
121 printf ("error: pthread_create: %m\n");
125 ret
= pthread_barrier_wait (&barrier
);
126 if (ret
!= 0 && ret
!= PTHREAD_BARRIER_SERIAL_THREAD
)
129 printf ("pthread_wait: %m\n");
132 for (int i
= 0; i
< inner_thread_count
; ++i
)
134 ret
= pthread_join (threads
[i
], NULL
);
138 printf ("error: pthread_join: %m\n");
142 ret
= pthread_barrier_destroy (&barrier
);
146 printf ("pthread_barrier_destroy: %m\n");
159 /* The number of top-level threads should be equal to the number of
160 arenas. See arena_get2. */
161 long outer_thread_count
= sysconf (_SC_NPROCESSORS_ONLN
);
162 if (outer_thread_count
>= 1)
164 /* See NARENAS_FROM_NCORES in malloc.c. */
165 if (sizeof (long) == 4)
166 outer_thread_count
*= 2;
168 outer_thread_count
*= 8;
171 /* Leave some room for shutting down all threads gracefully. */
172 int timeout
= TIMEOUT
- 2;
174 pthread_t
*threads
= calloc (sizeof (*threads
), outer_thread_count
);
177 printf ("error: calloc: %m\n");
181 for (long i
= 0; i
< outer_thread_count
; ++i
)
183 int ret
= pthread_create (threads
+ i
, NULL
, outer_thread
, NULL
);
187 printf ("error: pthread_create: %m\n");
192 struct timespec ts
= {timeout
, 0};
193 if (nanosleep (&ts
, NULL
))
195 printf ("error: error: nanosleep: %m\n");
199 __atomic_store_n (&termination_requested
, true, __ATOMIC_RELAXED
);
201 for (long i
= 0; i
< outer_thread_count
; ++i
)
203 int ret
= pthread_join (threads
[i
], NULL
);
207 printf ("error: pthread_join: %m\n");
216 #define TEST_FUNCTION do_test ()
217 #include "../test-skeleton.c"