]>
Commit | Line | Data |
---|---|---|
3da825ce | 1 | /* Test malloc with concurrent thread termination. |
f7a9f785 | 2 | Copyright (C) 2015-2016 Free Software Foundation, Inc. |
3da825ce FW |
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 | <http://www.gnu.org/licenses/>. */ | |
18 | ||
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. */ | |
27 | ||
28 | #include <errno.h> | |
2a386889 | 29 | #include <malloc.h> |
3da825ce FW |
30 | #include <pthread.h> |
31 | #include <stdbool.h> | |
32 | #include <stdio.h> | |
33 | #include <stdlib.h> | |
34 | #include <unistd.h> | |
35 | ||
c23de0aa FW |
36 | #include <support/support.h> |
37 | #include <support/xthread.h> | |
38 | #include <support/test-driver.h> | |
3da825ce FW |
39 | |
40 | static bool termination_requested; | |
41 | static int inner_thread_count = 4; | |
42 | static size_t malloc_size = 32; | |
43 | ||
44 | static void | |
45 | __attribute__ ((noinline, noclone)) | |
46 | unoptimized_free (void *ptr) | |
47 | { | |
48 | free (ptr); | |
49 | } | |
50 | ||
51 | static void * | |
52 | malloc_first_thread (void * closure) | |
53 | { | |
54 | pthread_barrier_t *barrier = closure; | |
c23de0aa FW |
55 | void *ptr = xmalloc (malloc_size); |
56 | xpthread_barrier_wait (barrier); | |
3da825ce FW |
57 | unoptimized_free (ptr); |
58 | return NULL; | |
59 | } | |
60 | ||
61 | static void * | |
62 | wait_first_thread (void * closure) | |
63 | { | |
64 | pthread_barrier_t *barrier = closure; | |
c23de0aa FW |
65 | xpthread_barrier_wait (barrier); |
66 | void *ptr = xmalloc (malloc_size); | |
3da825ce FW |
67 | unoptimized_free (ptr); |
68 | return NULL; | |
69 | } | |
70 | ||
71 | static void * | |
72 | outer_thread (void *closure) | |
73 | { | |
c23de0aa | 74 | pthread_t *threads = xcalloc (sizeof (*threads), inner_thread_count); |
3da825ce FW |
75 | while (!__atomic_load_n (&termination_requested, __ATOMIC_RELAXED)) |
76 | { | |
77 | pthread_barrier_t barrier; | |
c23de0aa | 78 | xpthread_barrier_init (&barrier, NULL, inner_thread_count + 1); |
3da825ce FW |
79 | for (int i = 0; i < inner_thread_count; ++i) |
80 | { | |
81 | void *(*func) (void *); | |
82 | if ((i % 2) == 0) | |
83 | func = malloc_first_thread; | |
84 | else | |
85 | func = wait_first_thread; | |
c23de0aa | 86 | threads[i] = xpthread_create (NULL, func, &barrier); |
3da825ce | 87 | } |
c23de0aa | 88 | xpthread_barrier_wait (&barrier); |
3da825ce | 89 | for (int i = 0; i < inner_thread_count; ++i) |
c23de0aa FW |
90 | xpthread_join (threads[i]); |
91 | xpthread_barrier_destroy (&barrier); | |
3da825ce FW |
92 | } |
93 | ||
94 | free (threads); | |
95 | ||
96 | return NULL; | |
97 | } | |
98 | ||
99 | static int | |
100 | do_test (void) | |
101 | { | |
2a386889 FW |
102 | /* The number of threads should be smaller than the number of |
103 | arenas, so that there will be some free arenas to add to the | |
104 | arena free list. */ | |
105 | enum { outer_thread_count = 2 }; | |
106 | if (mallopt (M_ARENA_MAX, 8) == 0) | |
3da825ce | 107 | { |
2a386889 FW |
108 | printf ("error: mallopt (M_ARENA_MAX) failed\n"); |
109 | return 1; | |
3da825ce FW |
110 | } |
111 | ||
112 | /* Leave some room for shutting down all threads gracefully. */ | |
2a386889 | 113 | int timeout = 3; |
c23de0aa FW |
114 | if (timeout > DEFAULT_TIMEOUT) |
115 | timeout = DEFAULT_TIMEOUT - 1; | |
3da825ce | 116 | |
c23de0aa | 117 | pthread_t *threads = xcalloc (sizeof (*threads), outer_thread_count); |
3da825ce | 118 | for (long i = 0; i < outer_thread_count; ++i) |
c23de0aa | 119 | threads[i] = xpthread_create (NULL, outer_thread, NULL); |
3da825ce FW |
120 | |
121 | struct timespec ts = {timeout, 0}; | |
122 | if (nanosleep (&ts, NULL)) | |
123 | { | |
124 | printf ("error: error: nanosleep: %m\n"); | |
125 | abort (); | |
126 | } | |
127 | ||
128 | __atomic_store_n (&termination_requested, true, __ATOMIC_RELAXED); | |
129 | ||
130 | for (long i = 0; i < outer_thread_count; ++i) | |
c23de0aa | 131 | xpthread_join (threads[i]); |
3da825ce FW |
132 | free (threads); |
133 | ||
134 | return 0; | |
135 | } | |
c23de0aa FW |
136 | |
137 | #include <support/test-driver.c> |