3
3
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4
4
// This file contains tests for UMF pool API
5
5
6
- #include " multithread_helpers .hpp"
7
- # include " pool.hpp "
6
+ #include " ipcFixtures .hpp"
7
+
8
8
#include " provider.hpp"
9
- #include " test_helpers.h"
10
9
11
- #include < umf/ipc.h>
12
- #include < umf/memory_pool.h>
13
- #include < umf/pools/pool_proxy.h>
10
+ #include < umf/pools/pool_disjoint.h>
14
11
15
- #include < array>
16
- #include < atomic>
17
- #include < cstdlib>
18
- #include < cstring>
19
- #include < mutex>
20
- #include < numeric>
21
12
#include < shared_mutex>
22
- #include < thread>
23
13
#include < unordered_map>
24
- #include < vector>
25
14
26
15
struct provider_mock_ipc : public umf_test ::provider_base_t {
27
16
using allocations_map_type = std::unordered_map<const void *, size_t >;
@@ -39,7 +28,6 @@ struct provider_mock_ipc : public umf_test::provider_base_t {
39
28
allocations_mutex_type alloc_mutex;
40
29
allocations_map_type allocations;
41
30
42
- umf_result_t initialize (void *) noexcept { return UMF_RESULT_SUCCESS; }
43
31
enum umf_result_t alloc (size_t size, size_t align, void **ptr) noexcept {
44
32
auto ret = helper_prov.alloc (size, align, ptr);
45
33
if (ret == UMF_RESULT_SUCCESS) {
@@ -78,7 +66,7 @@ struct provider_mock_ipc : public umf_test::provider_base_t {
78
66
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
79
67
}
80
68
ipcData->ptr = ptr;
81
- ipcData->size = it-> second ; // size of the base allocation
69
+ ipcData->size = size ; // size of the base allocation
82
70
return UMF_RESULT_SUCCESS;
83
71
}
84
72
enum umf_result_t put_ipc_handle (void *providerIpcData) noexcept {
@@ -118,220 +106,10 @@ struct provider_mock_ipc : public umf_test::provider_base_t {
118
106
}
119
107
};
120
108
121
- struct umfIpcTest : umf_test::test {
122
- umfIpcTest () : pool(nullptr , nullptr ) {}
123
- void SetUp () override {
124
- test::SetUp ();
125
- this ->pool = makePool ();
126
- }
127
-
128
- void TearDown () override { test::TearDown (); }
129
-
130
- umf::pool_unique_handle_t makePool () {
131
- // TODO: The function is similar to poolCreateExt function
132
- // from memoryPool.hpp
133
- umf_memory_provider_handle_t hProvider;
134
- umf_memory_pool_handle_t hPool;
135
-
136
- auto ret =
137
- umfMemoryProviderCreate (&IPC_MOCK_PROVIDER_OPS, &stat, &hProvider);
138
- EXPECT_EQ (ret, UMF_RESULT_SUCCESS);
139
-
140
- auto trace = [](void *trace_context, const char *name) {
141
- stats_type *stat = static_cast <stats_type *>(trace_context);
142
- if (std::strcmp (name, " get_ipc_handle" ) == 0 ) {
143
- ++stat->getCount ;
144
- } else if (std::strcmp (name, " put_ipc_handle" ) == 0 ) {
145
- ++stat->putCount ;
146
- } else if (std::strcmp (name, " open_ipc_handle" ) == 0 ) {
147
- ++stat->openCount ;
148
- } else if (std::strcmp (name, " close_ipc_handle" ) == 0 ) {
149
- ++stat->closeCount ;
150
- }
151
- };
152
-
153
- umf_memory_provider_handle_t hTraceProvider =
154
- traceProviderCreate (hProvider, true , (void *)&stat, trace);
155
-
156
- ret = umfPoolCreate (umfProxyPoolOps (), hTraceProvider, nullptr ,
157
- UMF_POOL_CREATE_FLAG_OWN_PROVIDER, &hPool);
158
- EXPECT_EQ (ret, UMF_RESULT_SUCCESS);
159
-
160
- return umf::pool_unique_handle_t (hPool, &umfPoolDestroy);
161
- }
162
-
163
- struct stats_type {
164
- std::atomic<size_t > getCount;
165
- std::atomic<size_t > putCount;
166
- std::atomic<size_t > openCount;
167
- std::atomic<size_t > closeCount;
168
-
169
- stats_type () : getCount(0 ), putCount(0 ), openCount(0 ), closeCount(0 ) {}
170
- };
171
-
172
- umf_memory_provider_ops_t IPC_MOCK_PROVIDER_OPS =
173
- umf::providerMakeCOps<provider_mock_ipc, stats_type>();
174
- umf::pool_unique_handle_t pool;
175
- static constexpr int NTHREADS = 10 ;
176
- stats_type stat;
177
- };
178
-
179
- TEST_F (umfIpcTest, BasicFlow) {
180
- constexpr size_t SIZE = 100 ;
181
- int *ptr = (int *)umfPoolMalloc (pool.get (), SIZE * sizeof (int ));
182
- EXPECT_NE (ptr, nullptr );
183
-
184
- std::iota (ptr, ptr + SIZE, 0 );
185
-
186
- umf_ipc_handle_t ipcHandleFull = nullptr ;
187
- size_t handleFullSize = 0 ;
188
- umf_result_t ret = umfGetIPCHandle (ptr, &ipcHandleFull, &handleFullSize);
189
- ASSERT_EQ (ret, UMF_RESULT_SUCCESS);
190
- umf_ipc_handle_t ipcHandleHalf = nullptr ;
191
- size_t handleHalfSize = 0 ;
192
- ret = umfGetIPCHandle (ptr + SIZE / 2 , &ipcHandleHalf, &handleHalfSize);
193
- ASSERT_EQ (ret, UMF_RESULT_SUCCESS);
194
- ASSERT_EQ (handleFullSize, handleHalfSize);
195
-
196
- void *fullArray = nullptr ;
197
- ret = umfOpenIPCHandle (pool.get (), ipcHandleFull, &fullArray);
198
- ASSERT_EQ (ret, UMF_RESULT_SUCCESS);
199
-
200
- void *halfArray = nullptr ;
201
- ret = umfOpenIPCHandle (pool.get (), ipcHandleHalf, &halfArray);
202
- ASSERT_EQ (ret, UMF_RESULT_SUCCESS);
203
-
204
- for (int i = 0 ; i < (int )SIZE; ++i) {
205
- ASSERT_EQ (reinterpret_cast <int *>(fullArray)[i], i);
206
- }
207
- // Close fullArray before reading halfArray
208
- ret = umfCloseIPCHandle (fullArray);
209
- EXPECT_EQ (ret, UMF_RESULT_SUCCESS);
210
-
211
- for (int i = 0 ; i < (int )SIZE / 2 ; ++i) {
212
- ASSERT_EQ (reinterpret_cast <int *>(halfArray)[i], i + SIZE / 2 );
213
- }
214
- ret = umfCloseIPCHandle (halfArray);
215
- EXPECT_EQ (ret, UMF_RESULT_SUCCESS);
216
-
217
- ret = umfPutIPCHandle (ipcHandleFull);
218
- EXPECT_EQ (ret, UMF_RESULT_SUCCESS);
219
-
220
- ret = umfPutIPCHandle (ipcHandleHalf);
221
- EXPECT_EQ (ret, UMF_RESULT_SUCCESS);
222
-
223
- ret = umfPoolFree (pool.get (), ptr);
224
- EXPECT_EQ (ret, UMF_RESULT_SUCCESS);
225
-
226
- EXPECT_EQ (stat.getCount , 1 );
227
- EXPECT_EQ (stat.putCount , stat.getCount );
228
- // TODO: enale check below once cache for open IPC handles is implemented
229
- // EXPECT_EQ(stat.openCount, 1);
230
- EXPECT_EQ (stat.closeCount , stat.openCount );
231
- }
232
-
233
- TEST_F (umfIpcTest, ConcurrentGetPutHandles) {
234
- std::vector<void *> ptrs;
235
- constexpr size_t ALLOC_SIZE = 100 ;
236
- constexpr size_t NUM_POINTERS = 100 ;
237
- for (size_t i = 0 ; i < NUM_POINTERS; ++i) {
238
- void *ptr = umfPoolMalloc (pool.get (), ALLOC_SIZE);
239
- EXPECT_NE (ptr, nullptr );
240
- ptrs.push_back (ptr);
241
- }
242
-
243
- std::array<std::vector<umf_ipc_handle_t >, NTHREADS> ipcHandles;
244
-
245
- umf_test::syncthreads_barrier syncthreads (NTHREADS);
246
-
247
- auto getHandlesFn = [&ipcHandles, &ptrs, &syncthreads](size_t tid) {
248
- syncthreads ();
249
- for (void *ptr : ptrs) {
250
- umf_ipc_handle_t ipcHandle;
251
- size_t handleSize;
252
- umf_result_t ret = umfGetIPCHandle (ptr, &ipcHandle, &handleSize);
253
- ASSERT_EQ (ret, UMF_RESULT_SUCCESS);
254
- ipcHandles[tid].push_back (ipcHandle);
255
- }
256
- };
257
-
258
- umf_test::parallel_exec (NTHREADS, getHandlesFn);
259
-
260
- auto putHandlesFn = [&ipcHandles, &syncthreads](size_t tid) {
261
- syncthreads ();
262
- for (umf_ipc_handle_t ipcHandle : ipcHandles[tid]) {
263
- umf_result_t ret = umfPutIPCHandle (ipcHandle);
264
- EXPECT_EQ (ret, UMF_RESULT_SUCCESS);
265
- }
266
- };
267
-
268
- umf_test::parallel_exec (NTHREADS, putHandlesFn);
269
-
270
- for (void *ptr : ptrs) {
271
- umf_result_t ret = umfPoolFree (pool.get (), ptr);
272
- EXPECT_EQ (ret, UMF_RESULT_SUCCESS);
273
- }
274
-
275
- EXPECT_GE (stat.getCount , NUM_POINTERS);
276
- EXPECT_LE (stat.getCount , NUM_POINTERS * NTHREADS);
277
- EXPECT_EQ (stat.putCount , stat.getCount );
278
- }
279
-
280
- TEST_F (umfIpcTest, ConcurrentOpenCloseHandles) {
281
- std::vector<void *> ptrs;
282
- constexpr size_t ALLOC_SIZE = 100 ;
283
- constexpr size_t NUM_POINTERS = 100 ;
284
- for (size_t i = 0 ; i < NUM_POINTERS; ++i) {
285
- void *ptr = umfPoolMalloc (pool.get (), ALLOC_SIZE);
286
- EXPECT_NE (ptr, nullptr );
287
- ptrs.push_back (ptr);
288
- }
289
-
290
- std::array<umf_ipc_handle_t , NUM_POINTERS> ipcHandles;
291
- for (size_t i = 0 ; i < NUM_POINTERS; ++i) {
292
- umf_ipc_handle_t ipcHandle;
293
- size_t handleSize;
294
- umf_result_t ret = umfGetIPCHandle (ptrs[i], &ipcHandle, &handleSize);
295
- ASSERT_EQ (ret, UMF_RESULT_SUCCESS);
296
- ipcHandles[i] = ipcHandle;
297
- }
298
-
299
- std::array<std::vector<void *>, NTHREADS> openedIpcHandles;
300
-
301
- umf_test::syncthreads_barrier syncthreads (NTHREADS);
302
-
303
- auto openHandlesFn = [this , &ipcHandles, &openedIpcHandles,
304
- &syncthreads](size_t tid) {
305
- syncthreads ();
306
- for (auto ipcHandle : ipcHandles) {
307
- void *ptr;
308
- umf_result_t ret = umfOpenIPCHandle (pool.get (), ipcHandle, &ptr);
309
- ASSERT_EQ (ret, UMF_RESULT_SUCCESS);
310
- openedIpcHandles[tid].push_back (ptr);
311
- }
312
- };
313
-
314
- umf_test::parallel_exec (NTHREADS, openHandlesFn);
315
-
316
- auto closeHandlesFn = [&openedIpcHandles, &syncthreads](size_t tid) {
317
- syncthreads ();
318
- for (void *ptr : openedIpcHandles[tid]) {
319
- umf_result_t ret = umfCloseIPCHandle (ptr);
320
- EXPECT_EQ (ret, UMF_RESULT_SUCCESS);
321
- }
322
- };
323
-
324
- umf_test::parallel_exec (NTHREADS, closeHandlesFn);
325
-
326
- for (auto ipcHandle : ipcHandles) {
327
- umf_result_t ret = umfPutIPCHandle (ipcHandle);
328
- EXPECT_EQ (ret, UMF_RESULT_SUCCESS);
329
- }
330
-
331
- for (void *ptr : ptrs) {
332
- umf_result_t ret = umfPoolFree (pool.get (), ptr);
333
- EXPECT_EQ (ret, UMF_RESULT_SUCCESS);
334
- }
109
+ static umf_memory_provider_ops_t IPC_MOCK_PROVIDER_OPS =
110
+ umf::providerMakeCOps<provider_mock_ipc, void >();
335
111
336
- EXPECT_EQ (stat.openCount , stat.closeCount );
337
- }
112
+ INSTANTIATE_TEST_SUITE_P (umfIpcTestSuite, umfIpcTest,
113
+ ::testing::Values (testParams{
114
+ umfProxyPoolOps (), nullptr , &IPC_MOCK_PROVIDER_OPS,
115
+ nullptr }));
0 commit comments