1/* multi-threaded memory allocation/deallocation test.
2 Copyright (C) 2024 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 License as
7 published by the Free Software Foundation; either version 2.1 of the
8 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; see the file COPYING.LIB. If
17 not, see <https://www.gnu.org/licenses/>. */
18
19#include <stdio.h>
20#include <stdlib.h>
21#include <string.h>
22#include <support/check.h>
23#include <support/support.h>
24#include <support/xthread.h>
25#include <support/test-driver.h>
26#include <sys/sysinfo.h>
27#include <unistd.h>
28
29#ifndef ITERATIONS
30# define ITERATIONS 16
31#endif
32
33#ifndef NUM_THREADS
34# define NUM_THREADS 8
35#endif
36
37#ifndef NUM_ALLOCATIONS
38# define NUM_ALLOCATIONS 2048
39#endif
40
41static pthread_barrier_t barrier;
42
43__thread unsigned int seed;
44
45typedef struct
46{
47 int id;
48 pthread_t thread;
49} thread;
50
51thread threads[NUM_THREADS];
52
53void *allocations[NUM_THREADS][NUM_ALLOCATIONS];
54
55void
56run_thread_dealloc (int id)
57{
58 for (int i = 0; i < NUM_ALLOCATIONS; i++)
59 {
60 free (ptr: allocations[id][i]);
61 allocations[id][i] = NULL;
62 }
63}
64
65void
66run_thread_alloc (int id)
67{
68 size_t msb, size;
69 for (int i = 0; i < NUM_ALLOCATIONS; i++)
70 {
71 msb = 1 << rand_r (seed: &seed) % 16;
72 size = msb + rand_r (seed: &seed) % msb;
73 allocations[id][i] = malloc (size: size);
74 TEST_VERIFY_EXIT (allocations[id][i] != NULL);
75 }
76}
77
78void *
79run_allocations (void *arg)
80{
81 int id = *((int *) arg);
82 seed = time (NULL) + id;
83
84 /* Stage 1: First half o the threads allocating memory and the second
85 * half waiting for them to finish
86 */
87 if (id < NUM_THREADS / 2)
88 run_thread_alloc (id);
89
90 xpthread_barrier_wait (barrier: &barrier);
91
92 /* Stage 2: Half of the threads allocationg memory and the other
93 * half deallocating:
94 * - In the non cross-thread dealloc scenario the first half will be
95 * deallocating the memory allocated by themselves in stage 1 and the
96 * second half will be allocating memory.
97 * - In the cross-thread dealloc scenario the first half will continue
98 * to allocate memory and the second half will deallocate the memory
99 * allocated by the first half in stage 1.
100 */
101 if (id < NUM_THREADS / 2)
102#ifndef CROSS_THREAD_DEALLOC
103 run_thread_dealloc (id);
104#else
105 run_thread_alloc (id: id + NUM_THREADS / 2);
106#endif
107 else
108#ifndef CROSS_THREAD_DEALLOC
109 run_thread_alloc (id);
110#else
111 run_thread_dealloc (id: id - NUM_THREADS / 2);
112#endif
113
114 xpthread_barrier_wait (barrier: &barrier);
115
116 // Stage 3: Second half of the threads deallocating and the first half
117 // waiting for them to finish.
118 if (id >= NUM_THREADS / 2)
119 run_thread_dealloc (id);
120
121 return NULL;
122}
123
124static int
125do_test (void)
126{
127 xpthread_barrier_init (barrier: &barrier, NULL, NUM_THREADS);
128
129 for (int i = 0; i < ITERATIONS; i++)
130 {
131 for (int t = 0; t < NUM_THREADS; t++)
132 {
133 threads[t].id = t;
134 threads[t].thread
135 = xpthread_create (NULL, thread_func: run_allocations, closure: &threads[t].id);
136 }
137
138 for (int t = 0; t < NUM_THREADS; t++)
139 xpthread_join (thr: threads[t].thread);
140 }
141
142 return 0;
143}
144
145#include <support/test-driver.c>
146

source code of glibc/malloc/tst-aligned-alloc-random-thread.c