mempool test: Only use a single range for large stride
[librseq.git] / tests / mempool_test.c
CommitLineData
d273fd4b
MD
1// SPDX-License-Identifier: MIT
2// SPDX-FileCopyrightText: 2024 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
3/*
4 * rseq memory pool test.
5 */
6
7#ifndef _GNU_SOURCE
8#define _GNU_SOURCE
9#endif
10#include <assert.h>
11#include <sched.h>
12#include <signal.h>
13#include <stdio.h>
14#include <string.h>
15#include <sys/time.h>
16#include <inttypes.h>
17#include <stdlib.h>
c15b99f6
OD
18#include <sys/wait.h>
19#include <unistd.h>
d273fd4b
MD
20
21#include <rseq/mempool.h>
c3fad074 22#include "../src/rseq-utils.h"
d273fd4b
MD
23
24#include "list.h"
25#include "tap.h"
26
27struct test_data {
28 uintptr_t value;
29 struct test_data __rseq_percpu *backref;
30 struct list_head node;
31};
32
dcb59d50 33static void test_mempool_fill(unsigned long max_nr_ranges, size_t stride)
d273fd4b
MD
34{
35 struct test_data __rseq_percpu *ptr;
84a5a73a 36 struct test_data *iter, *tmp;
0ba2a93e
MD
37 struct rseq_mempool *mempool;
38 struct rseq_mempool_attr *attr;
d273fd4b
MD
39 uint64_t count = 0;
40 LIST_HEAD(list);
41 int ret, i;
42
0ba2a93e 43 attr = rseq_mempool_attr_create();
a8ad787a 44 ok(attr, "Create pool attribute");
0ba2a93e 45 ret = rseq_mempool_attr_set_robust(attr);
d273fd4b 46 ok(ret == 0, "Setting mempool robust attribute");
cb475906
MD
47 ret = rseq_mempool_attr_set_percpu(attr, stride, CPU_SETSIZE);
48 ok(ret == 0, "Setting mempool percpu type");
dcb59d50
MD
49 ret = rseq_mempool_attr_set_max_nr_ranges(attr, max_nr_ranges);
50 ok(ret == 0, "Setting mempool max_nr_ranges=%lu", max_nr_ranges);
0ba2a93e 51 mempool = rseq_mempool_create("test_data",
cb475906 52 sizeof(struct test_data), attr);
f2981623 53 ok(mempool, "Create mempool of size %zu", stride);
0ba2a93e 54 rseq_mempool_attr_destroy(attr);
d273fd4b
MD
55
56 for (;;) {
57 struct test_data *cpuptr;
58
15da5c27 59 ptr = (struct test_data __rseq_percpu *) rseq_mempool_percpu_zmalloc(mempool);
d273fd4b
MD
60 if (!ptr)
61 break;
62 /* Link items in cpu 0. */
06e0b1c0 63 cpuptr = rseq_percpu_ptr(ptr, 0, stride);
d273fd4b
MD
64 cpuptr->backref = ptr;
65 /* Randomize items in list. */
66 if (count & 1)
67 list_add(&cpuptr->node, &list);
68 else
69 list_add_tail(&cpuptr->node, &list);
70 count++;
71 }
72
dcb59d50
MD
73 ok(count * sizeof(struct test_data) == stride * max_nr_ranges,
74 "Allocated %" PRIu64 " objects in pool", count);
d273fd4b
MD
75
76 list_for_each_entry(iter, &list, node) {
77 ptr = iter->backref;
78 for (i = 0; i < CPU_SETSIZE; i++) {
06e0b1c0 79 struct test_data *cpuptr = rseq_percpu_ptr(ptr, i, stride);
d273fd4b
MD
80
81 if (cpuptr->value != 0)
82 abort();
83 cpuptr->value++;
84 }
85 }
86
87 ok(1, "Check for pool content corruption");
88
84a5a73a 89 list_for_each_entry_safe(iter, tmp, &list, node) {
d273fd4b 90 ptr = iter->backref;
15da5c27 91 rseq_mempool_percpu_free(ptr, stride);
d273fd4b 92 }
0ba2a93e 93 ret = rseq_mempool_destroy(mempool);
d273fd4b
MD
94 ok(ret == 0, "Destroy mempool");
95}
96
0ba2a93e 97static void test_robust_double_free(struct rseq_mempool *pool)
c15b99f6
OD
98{
99 struct test_data __rseq_percpu *ptr;
100
15da5c27 101 ptr = (struct test_data __rseq_percpu *) rseq_mempool_percpu_malloc(pool);
c15b99f6 102
15da5c27
MD
103 rseq_mempool_percpu_free(ptr);
104 rseq_mempool_percpu_free(ptr);
c15b99f6
OD
105}
106
0ba2a93e 107static void test_robust_corrupt_after_free(struct rseq_mempool *pool)
c15b99f6
OD
108{
109 struct test_data __rseq_percpu *ptr;
110 struct test_data *cpuptr;
111
15da5c27 112 ptr = (struct test_data __rseq_percpu *) rseq_mempool_percpu_malloc(pool);
c15b99f6
OD
113 cpuptr = (struct test_data *) rseq_percpu_ptr(ptr, 0);
114
15da5c27 115 rseq_mempool_percpu_free(ptr);
c15b99f6
OD
116 cpuptr->value = (uintptr_t) test_robust_corrupt_after_free;
117
0ba2a93e 118 rseq_mempool_destroy(pool);
c15b99f6
OD
119}
120
0ba2a93e 121static void test_robust_memory_leak(struct rseq_mempool *pool)
c15b99f6 122{
15da5c27 123 (void) rseq_mempool_percpu_malloc(pool);
c15b99f6 124
0ba2a93e 125 rseq_mempool_destroy(pool);
c15b99f6
OD
126}
127
0ba2a93e 128static void test_robust_free_list_corruption(struct rseq_mempool *pool)
c15b99f6
OD
129{
130 struct test_data __rseq_percpu *ptr;
131 struct test_data *cpuptr;
132
15da5c27 133 ptr = (struct test_data __rseq_percpu *) rseq_mempool_percpu_malloc(pool);
c15b99f6
OD
134 cpuptr = (struct test_data *) rseq_percpu_ptr(ptr, 0);
135
15da5c27 136 rseq_mempool_percpu_free(ptr);
c15b99f6
OD
137
138 cpuptr->value = (uintptr_t) cpuptr;
139
15da5c27
MD
140 (void) rseq_mempool_percpu_malloc(pool);
141 (void) rseq_mempool_percpu_malloc(pool);
c15b99f6
OD
142}
143
0ba2a93e
MD
144static int run_robust_test(void (*test)(struct rseq_mempool*),
145 struct rseq_mempool *pool)
c15b99f6
OD
146{
147 pid_t cpid;
148 int status;
149
150 cpid = fork();
151
152 switch (cpid) {
153 case -1:
154 return 0;
155 case 0:
156 test(pool);
157 _exit(EXIT_FAILURE);
158 default:
159 waitpid(cpid, &status, 0);
160 }
161
162 if (WIFSIGNALED(status) &&
163 (SIGABRT == WTERMSIG(status)))
164 return 1;
165
166 return 0;
167}
168
169static void run_robust_tests(void)
170{
0ba2a93e
MD
171 struct rseq_mempool_attr *attr;
172 struct rseq_mempool *pool;
cb475906 173 int ret;
c15b99f6 174
0ba2a93e 175 attr = rseq_mempool_attr_create();
cb475906
MD
176 ok(attr, "Create mempool attributes");
177
178 ret = rseq_mempool_attr_set_robust(attr);
179 ok(ret == 0, "Setting mempool robust attribute");
c15b99f6 180
cb475906
MD
181 ret = rseq_mempool_attr_set_percpu(attr, RSEQ_MEMPOOL_STRIDE, 1);
182 ok(ret == 0, "Setting mempool percpu type");
c15b99f6 183
0ba2a93e 184 pool = rseq_mempool_create("mempool-robust",
cb475906 185 sizeof(void*), attr);
c15b99f6 186
0ba2a93e 187 rseq_mempool_attr_destroy(attr);
c15b99f6
OD
188
189 ok(run_robust_test(test_robust_double_free, pool),
190 "robust-double-free");
191
192 ok(run_robust_test(test_robust_corrupt_after_free, pool),
193 "robust-corrupt-after-free");
194
195 ok(run_robust_test(test_robust_memory_leak, pool),
196 "robust-memory-leak");
197
198 ok(run_robust_test(test_robust_free_list_corruption, pool),
199 "robust-free-list-corruption");
200
0ba2a93e 201 rseq_mempool_destroy(pool);
c15b99f6
OD
202}
203
d273fd4b
MD
204int main(void)
205{
206 size_t len;
dcb59d50 207 unsigned long nr_ranges;
d273fd4b 208
579badcb
MD
209 plan_no_plan();
210
dcb59d50
MD
211 for (nr_ranges = 1; nr_ranges < 32; nr_ranges <<= 1) {
212 /* From page size to 64kB */
213 for (len = rseq_get_page_len(); len < 65536; len <<= 1) {
214 test_mempool_fill(nr_ranges, len);
215 }
d273fd4b
MD
216 }
217
dcb59d50
MD
218 len = rseq_get_page_len();
219 if (len < 65536)
220 len = 65536;
221 /* From min(page size, 64kB) to 4MB */
222 for (; len < 4096 * 1024; len <<= 1)
7747a267 223 test_mempool_fill(1, len);
dcb59d50 224
c15b99f6
OD
225 run_robust_tests();
226
d273fd4b
MD
227 exit(exit_status());
228}
This page took 0.033624 seconds and 4 git commands to generate.