mempool: Introduce rseq_mempool_attr_set_max_nr_ranges
[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
f2981623 33static void test_mempool_fill(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");
e11a02d7
MD
49 ret = rseq_mempool_attr_set_max_nr_ranges(attr, 1);
50 ok(ret == 0, "Setting mempool max_nr_ranges=1");
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
f2981623 73 ok(count * sizeof(struct test_data) == stride, "Allocated %" PRIu64 " objects in pool", count);
d273fd4b
MD
74
75 list_for_each_entry(iter, &list, node) {
76 ptr = iter->backref;
77 for (i = 0; i < CPU_SETSIZE; i++) {
06e0b1c0 78 struct test_data *cpuptr = rseq_percpu_ptr(ptr, i, stride);
d273fd4b
MD
79
80 if (cpuptr->value != 0)
81 abort();
82 cpuptr->value++;
83 }
84 }
85
86 ok(1, "Check for pool content corruption");
87
84a5a73a 88 list_for_each_entry_safe(iter, tmp, &list, node) {
d273fd4b 89 ptr = iter->backref;
15da5c27 90 rseq_mempool_percpu_free(ptr, stride);
d273fd4b 91 }
0ba2a93e 92 ret = rseq_mempool_destroy(mempool);
d273fd4b
MD
93 ok(ret == 0, "Destroy mempool");
94}
95
0ba2a93e 96static void test_robust_double_free(struct rseq_mempool *pool)
c15b99f6
OD
97{
98 struct test_data __rseq_percpu *ptr;
99
15da5c27 100 ptr = (struct test_data __rseq_percpu *) rseq_mempool_percpu_malloc(pool);
c15b99f6 101
15da5c27
MD
102 rseq_mempool_percpu_free(ptr);
103 rseq_mempool_percpu_free(ptr);
c15b99f6
OD
104}
105
0ba2a93e 106static void test_robust_corrupt_after_free(struct rseq_mempool *pool)
c15b99f6
OD
107{
108 struct test_data __rseq_percpu *ptr;
109 struct test_data *cpuptr;
110
15da5c27 111 ptr = (struct test_data __rseq_percpu *) rseq_mempool_percpu_malloc(pool);
c15b99f6
OD
112 cpuptr = (struct test_data *) rseq_percpu_ptr(ptr, 0);
113
15da5c27 114 rseq_mempool_percpu_free(ptr);
c15b99f6
OD
115 cpuptr->value = (uintptr_t) test_robust_corrupt_after_free;
116
0ba2a93e 117 rseq_mempool_destroy(pool);
c15b99f6
OD
118}
119
0ba2a93e 120static void test_robust_memory_leak(struct rseq_mempool *pool)
c15b99f6 121{
15da5c27 122 (void) rseq_mempool_percpu_malloc(pool);
c15b99f6 123
0ba2a93e 124 rseq_mempool_destroy(pool);
c15b99f6
OD
125}
126
0ba2a93e 127static void test_robust_free_list_corruption(struct rseq_mempool *pool)
c15b99f6
OD
128{
129 struct test_data __rseq_percpu *ptr;
130 struct test_data *cpuptr;
131
15da5c27 132 ptr = (struct test_data __rseq_percpu *) rseq_mempool_percpu_malloc(pool);
c15b99f6
OD
133 cpuptr = (struct test_data *) rseq_percpu_ptr(ptr, 0);
134
15da5c27 135 rseq_mempool_percpu_free(ptr);
c15b99f6
OD
136
137 cpuptr->value = (uintptr_t) cpuptr;
138
15da5c27
MD
139 (void) rseq_mempool_percpu_malloc(pool);
140 (void) rseq_mempool_percpu_malloc(pool);
c15b99f6
OD
141}
142
0ba2a93e
MD
143static int run_robust_test(void (*test)(struct rseq_mempool*),
144 struct rseq_mempool *pool)
c15b99f6
OD
145{
146 pid_t cpid;
147 int status;
148
149 cpid = fork();
150
151 switch (cpid) {
152 case -1:
153 return 0;
154 case 0:
155 test(pool);
156 _exit(EXIT_FAILURE);
157 default:
158 waitpid(cpid, &status, 0);
159 }
160
161 if (WIFSIGNALED(status) &&
162 (SIGABRT == WTERMSIG(status)))
163 return 1;
164
165 return 0;
166}
167
168static void run_robust_tests(void)
169{
0ba2a93e
MD
170 struct rseq_mempool_attr *attr;
171 struct rseq_mempool *pool;
cb475906 172 int ret;
c15b99f6 173
0ba2a93e 174 attr = rseq_mempool_attr_create();
cb475906
MD
175 ok(attr, "Create mempool attributes");
176
177 ret = rseq_mempool_attr_set_robust(attr);
178 ok(ret == 0, "Setting mempool robust attribute");
c15b99f6 179
cb475906
MD
180 ret = rseq_mempool_attr_set_percpu(attr, RSEQ_MEMPOOL_STRIDE, 1);
181 ok(ret == 0, "Setting mempool percpu type");
c15b99f6 182
0ba2a93e 183 pool = rseq_mempool_create("mempool-robust",
cb475906 184 sizeof(void*), attr);
c15b99f6 185
0ba2a93e 186 rseq_mempool_attr_destroy(attr);
c15b99f6
OD
187
188 ok(run_robust_test(test_robust_double_free, pool),
189 "robust-double-free");
190
191 ok(run_robust_test(test_robust_corrupt_after_free, pool),
192 "robust-corrupt-after-free");
193
194 ok(run_robust_test(test_robust_memory_leak, pool),
195 "robust-memory-leak");
196
197 ok(run_robust_test(test_robust_free_list_corruption, pool),
198 "robust-free-list-corruption");
199
0ba2a93e 200 rseq_mempool_destroy(pool);
c15b99f6
OD
201}
202
d273fd4b
MD
203int main(void)
204{
205 size_t len;
206
579badcb
MD
207 plan_no_plan();
208
c3fad074
MD
209 /* From page size to 4MB */
210 for (len = rseq_get_page_len(); len < 4096 * 1024; len <<= 1) {
d273fd4b
MD
211 test_mempool_fill(len);
212 }
213
c15b99f6
OD
214 run_robust_tests();
215
d273fd4b
MD
216 exit(exit_status());
217}
This page took 0.032494 seconds and 4 git commands to generate.