15
15
#include <string.h>
16
16
17
17
#include "base_alloc_global.h"
18
+ #include "critnib.h"
18
19
#include "provider_os_memory_internal.h"
19
20
#include "utils_log.h"
20
21
24
25
25
26
#define NODESET_STR_BUF_LEN 1024
26
27
28
+ // maximum size of file used for memory mapping
29
+ #define MAX_SIZE_FD (1ULL << 40)
30
+
27
31
typedef struct os_memory_provider_t {
28
32
unsigned protection ; // combination of OS-specific protection flags
33
+ unsigned flag ; // memory mapping flag
34
+ int fd ; // file descriptor for memory mapping
35
+ size_t size_fd ; // size of file used for memory mapping
36
+ critnib * ptr_off ; // a critnib storing (ptr, fd_offset) pairs
29
37
30
38
// NUMA config
31
39
hwloc_bitmap_t nodeset ;
@@ -191,6 +199,25 @@ static umf_result_t translate_params(umf_os_memory_provider_params_t *in_params,
191
199
return result ;
192
200
}
193
201
202
+ result = os_translate_memory_flag (in_params -> flag , & provider -> flag );
203
+ if (result != UMF_RESULT_SUCCESS ) {
204
+ LOG_ERR ("incorrect memory flag: %u" , in_params -> flag );
205
+ return result ;
206
+ }
207
+
208
+ provider -> fd = os_create_memory_fd (provider -> flag );
209
+ if (provider -> fd == -1 ) {
210
+ LOG_PERR ("creating a file descriptor for memory mapping failed" );
211
+ return UMF_RESULT_ERROR_UNKNOWN ;
212
+ }
213
+
214
+ provider -> size_fd = 0 ; // will be increased during each allocation
215
+
216
+ if (provider -> fd > 0 && os_set_file_size (provider -> fd , MAX_SIZE_FD )) {
217
+ LOG_PDEBUG ("growing file size failed" );
218
+ return UMF_RESULT_ERROR_INVALID_ARGUMENT ;
219
+ }
220
+
194
221
// NUMA config
195
222
int emptyNodeset = in_params -> numa_list_len == 0 ;
196
223
result = translate_numa_mode (in_params -> numa_mode , emptyNodeset ,
@@ -258,10 +285,19 @@ static umf_result_t os_initialize(void *params, void **provider) {
258
285
}
259
286
}
260
287
288
+ os_provider -> ptr_off = critnib_new ();
289
+ if (!os_provider -> ptr_off ) {
290
+ LOG_ERR ("creating IPC cache failed" );
291
+ ret = UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY ;
292
+ goto err_free_nodeset_str_buf ;
293
+ }
294
+
261
295
* provider = os_provider ;
262
296
263
297
return UMF_RESULT_SUCCESS ;
264
298
299
+ err_free_nodeset_str_buf :
300
+ umf_ba_global_free (os_provider -> nodeset_str_buf );
265
301
err_destroy_hwloc_topology :
266
302
hwloc_topology_destroy (os_provider -> topo );
267
303
err_free_os_provider :
@@ -276,6 +312,9 @@ static void os_finalize(void *provider) {
276
312
}
277
313
278
314
os_memory_provider_t * os_provider = provider ;
315
+
316
+ critnib_delete (os_provider -> ptr_off );
317
+
279
318
if (os_provider -> nodeset_str_buf ) {
280
319
umf_ba_global_free (os_provider -> nodeset_str_buf );
281
320
}
@@ -331,7 +370,8 @@ static inline void assert_is_page_aligned(uintptr_t ptr, size_t page_size) {
331
370
}
332
371
333
372
static int os_mmap_aligned (void * hint_addr , size_t length , size_t alignment ,
334
- size_t page_size , int prot , void * * out_addr ) {
373
+ size_t page_size , int prot , int flag , int fd ,
374
+ void * * out_addr , size_t * fd_size ) {
335
375
assert (out_addr );
336
376
337
377
size_t extended_length = length ;
@@ -344,8 +384,20 @@ static int os_mmap_aligned(void *hint_addr, size_t length, size_t alignment,
344
384
extended_length += alignment ;
345
385
}
346
386
347
- void * ptr = os_mmap (hint_addr , extended_length , prot );
387
+ size_t fd_offset = 0 ;
388
+
389
+ if (fd > 0 ) {
390
+ fd_offset = * fd_size ;
391
+ * fd_size += extended_length ;
392
+ if (* fd_size > MAX_SIZE_FD ) {
393
+ LOG_PDEBUG ("growing file size failed" );
394
+ return -1 ;
395
+ }
396
+ }
397
+
398
+ void * ptr = os_mmap (hint_addr , extended_length , prot , flag , fd , fd_offset );
348
399
if (ptr == NULL ) {
400
+ LOG_PDEBUG ("memory mapping failed" );
349
401
return -1 ;
350
402
}
351
403
@@ -411,15 +463,16 @@ static umf_result_t os_alloc(void *provider, size_t size, size_t alignment,
411
463
return UMF_RESULT_ERROR_INVALID_ARGUMENT ;
412
464
}
413
465
414
- int protection = os_provider -> protection ;
466
+ size_t fd_offset = os_provider -> size_fd ; // needed for critnib_insert()
415
467
416
468
void * addr = NULL ;
417
469
errno = 0 ;
418
- ret = os_mmap_aligned (NULL , size , alignment , page_size , protection , & addr );
470
+ ret = os_mmap_aligned (NULL , size , alignment , page_size ,
471
+ os_provider -> protection , os_provider -> flag ,
472
+ os_provider -> fd , & addr , & os_provider -> size_fd );
419
473
if (ret ) {
420
474
os_store_last_native_error (UMF_OS_RESULT_ERROR_ALLOC_FAILED , errno );
421
475
LOG_PERR ("memory allocation failed" );
422
-
423
476
return UMF_RESULT_ERROR_MEMORY_PROVIDER_SPECIFIC ;
424
477
}
425
478
@@ -429,7 +482,6 @@ static umf_result_t os_alloc(void *provider, size_t size, size_t alignment,
429
482
LOG_ERR ("allocated address 0x%llx is not aligned to %zu (0x%zx) "
430
483
"bytes" ,
431
484
(unsigned long long )addr , alignment , alignment );
432
-
433
485
goto err_unmap ;
434
486
}
435
487
@@ -460,6 +512,16 @@ static umf_result_t os_alloc(void *provider, size_t size, size_t alignment,
460
512
}
461
513
}
462
514
515
+ if (os_provider -> fd > 0 ) {
516
+ ret = critnib_insert (os_provider -> ptr_off , (uintptr_t )addr ,
517
+ (void * )(uintptr_t )fd_offset , 0 /* update */ );
518
+ if (ret ) {
519
+ LOG_DEBUG ("inserting a value to the IPC cache failed (addr=%p, "
520
+ "offset=%zu)" ,
521
+ addr , fd_offset );
522
+ }
523
+ }
524
+
463
525
* resultPtr = addr ;
464
526
465
527
return UMF_RESULT_SUCCESS ;
@@ -474,6 +536,12 @@ static umf_result_t os_free(void *provider, void *ptr, size_t size) {
474
536
return UMF_RESULT_ERROR_INVALID_ARGUMENT ;
475
537
}
476
538
539
+ os_memory_provider_t * os_provider = (os_memory_provider_t * )provider ;
540
+
541
+ if (os_provider -> fd > 0 ) {
542
+ critnib_remove (os_provider -> ptr_off , (uintptr_t )ptr );
543
+ }
544
+
477
545
errno = 0 ;
478
546
int ret = os_munmap (ptr , size );
479
547
// ignore error when size == 0
0 commit comments