mempool: namespacing, add global alloc/free
[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>
22
23#include "list.h"
24#include "tap.h"
25
26struct test_data {
27 uintptr_t value;
28 struct test_data __rseq_percpu *backref;
29 struct list_head node;
30};
31
f2981623 32static void test_mempool_fill(size_t stride)
d273fd4b
MD
33{
34 struct test_data __rseq_percpu *ptr;
84a5a73a 35 struct test_data *iter, *tmp;
0ba2a93e
MD
36 struct rseq_mempool *mempool;
37 struct rseq_mempool_attr *attr;
d273fd4b
MD
38 uint64_t count = 0;
39 LIST_HEAD(list);
40 int ret, i;
41
0ba2a93e 42 attr = rseq_mempool_attr_create();
a8ad787a 43 ok(attr, "Create pool attribute");
0ba2a93e 44 ret = rseq_mempool_attr_set_robust(attr);
d273fd4b
MD
45 ok(ret == 0, "Setting mempool robust attribute");
46
0ba2a93e 47 mempool = rseq_mempool_create("test_data",
d273fd4b 48 sizeof(struct test_data),
f2981623
MD
49 stride, CPU_SETSIZE, attr);
50 ok(mempool, "Create mempool of size %zu", stride);
0ba2a93e 51 rseq_mempool_attr_destroy(attr);
d273fd4b
MD
52
53 for (;;) {
54 struct test_data *cpuptr;
55
15da5c27 56 ptr = (struct test_data __rseq_percpu *) rseq_mempool_percpu_zmalloc(mempool);
d273fd4b
MD
57 if (!ptr)
58 break;
59 /* Link items in cpu 0. */
06e0b1c0 60 cpuptr = rseq_percpu_ptr(ptr, 0, stride);
d273fd4b
MD
61 cpuptr->backref = ptr;
62 /* Randomize items in list. */
63 if (count & 1)
64 list_add(&cpuptr->node, &list);
65 else
66 list_add_tail(&cpuptr->node, &list);
67 count++;
68 }
69
f2981623 70 ok(count * sizeof(struct test_data) == stride, "Allocated %" PRIu64 " objects in pool", count);
d273fd4b
MD
71
72 list_for_each_entry(iter, &list, node) {
73 ptr = iter->backref;
74 for (i = 0; i < CPU_SETSIZE; i++) {
06e0b1c0 75 struct test_data *cpuptr = rseq_percpu_ptr(ptr, i, stride);
d273fd4b
MD
76
77 if (cpuptr->value != 0)
78 abort();
79 cpuptr->value++;
80 }
81 }
82
83 ok(1, "Check for pool content corruption");
84
84a5a73a 85 list_for_each_entry_safe(iter, tmp, &list, node) {
d273fd4b 86 ptr = iter->backref;
15da5c27 87 rseq_mempool_percpu_free(ptr, stride);
d273fd4b 88 }
0ba2a93e 89 ret = rseq_mempool_destroy(mempool);
d273fd4b
MD
90 ok(ret == 0, "Destroy mempool");
91}
92
0ba2a93e 93static void test_robust_double_free(struct rseq_mempool *pool)
c15b99f6
OD
94{
95 struct test_data __rseq_percpu *ptr;
96
15da5c27 97 ptr = (struct test_data __rseq_percpu *) rseq_mempool_percpu_malloc(pool);
c15b99f6 98
15da5c27
MD
99 rseq_mempool_percpu_free(ptr);
100 rseq_mempool_percpu_free(ptr);
c15b99f6
OD
101}
102
0ba2a93e 103static void test_robust_corrupt_after_free(struct rseq_mempool *pool)
c15b99f6
OD
104{
105 struct test_data __rseq_percpu *ptr;
106 struct test_data *cpuptr;
107
15da5c27 108 ptr = (struct test_data __rseq_percpu *) rseq_mempool_percpu_malloc(pool);
c15b99f6
OD
109 cpuptr = (struct test_data *) rseq_percpu_ptr(ptr, 0);
110
15da5c27 111 rseq_mempool_percpu_free(ptr);
c15b99f6
OD
112 cpuptr->value = (uintptr_t) test_robust_corrupt_after_free;
113
0ba2a93e 114 rseq_mempool_destroy(pool);
c15b99f6
OD
115}
116
0ba2a93e 117static void test_robust_memory_leak(struct rseq_mempool *pool)
c15b99f6 118{
15da5c27 119 (void) rseq_mempool_percpu_malloc(pool);
c15b99f6 120
0ba2a93e 121 rseq_mempool_destroy(pool);
c15b99f6
OD
122}
123
0ba2a93e 124static void test_robust_free_list_corruption(struct rseq_mempool *pool)
c15b99f6
OD
125{
126 struct test_data __rseq_percpu *ptr;
127 struct test_data *cpuptr;
128
15da5c27 129 ptr = (struct test_data __rseq_percpu *) rseq_mempool_percpu_malloc(pool);
c15b99f6
OD
130 cpuptr = (struct test_data *) rseq_percpu_ptr(ptr, 0);
131
15da5c27 132 rseq_mempool_percpu_free(ptr);
c15b99f6
OD
133
134 cpuptr->value = (uintptr_t) cpuptr;
135
15da5c27
MD
136 (void) rseq_mempool_percpu_malloc(pool);
137 (void) rseq_mempool_percpu_malloc(pool);
c15b99f6
OD
138}
139
0ba2a93e
MD
140static int run_robust_test(void (*test)(struct rseq_mempool*),
141 struct rseq_mempool *pool)
c15b99f6
OD
142{
143 pid_t cpid;
144 int status;
145
146 cpid = fork();
147
148 switch (cpid) {
149 case -1:
150 return 0;
151 case 0:
152 test(pool);
153 _exit(EXIT_FAILURE);
154 default:
155 waitpid(cpid, &status, 0);
156 }
157
158 if (WIFSIGNALED(status) &&
159 (SIGABRT == WTERMSIG(status)))
160 return 1;
161
162 return 0;
163}
164
165static void run_robust_tests(void)
166{
0ba2a93e
MD
167 struct rseq_mempool_attr *attr;
168 struct rseq_mempool *pool;
c15b99f6 169
0ba2a93e 170 attr = rseq_mempool_attr_create();
c15b99f6 171
0ba2a93e 172 rseq_mempool_attr_set_robust(attr);
c15b99f6 173
0ba2a93e 174 pool = rseq_mempool_create("mempool-robust",
c15b99f6
OD
175 sizeof(void*), RSEQ_PERCPU_STRIDE, 1,
176 attr);
177
0ba2a93e 178 rseq_mempool_attr_destroy(attr);
c15b99f6
OD
179
180 ok(run_robust_test(test_robust_double_free, pool),
181 "robust-double-free");
182
183 ok(run_robust_test(test_robust_corrupt_after_free, pool),
184 "robust-corrupt-after-free");
185
186 ok(run_robust_test(test_robust_memory_leak, pool),
187 "robust-memory-leak");
188
189 ok(run_robust_test(test_robust_free_list_corruption, pool),
190 "robust-free-list-corruption");
191
0ba2a93e 192 rseq_mempool_destroy(pool);
c15b99f6
OD
193}
194
d273fd4b
MD
195int main(void)
196{
197 size_t len;
198
579badcb
MD
199 plan_no_plan();
200
d273fd4b
MD
201 /* From 4kB to 4MB */
202 for (len = 4096; len < 4096 * 1024; len <<= 1) {
203 test_mempool_fill(len);
204 }
205
c15b99f6
OD
206 run_robust_tests();
207
d273fd4b
MD
208 exit(exit_status());
209}
This page took 0.034402 seconds and 4 git commands to generate.