13
13
#include "base_alloc_global.h"
14
14
#include "utils_common.h"
15
15
#include "utils_concurrency.h"
16
+ #include "utils_load_library.h"
16
17
#include "utils_log.h"
17
18
#include "utils_sanitizers.h"
18
19
34
35
35
36
#define MALLOCX_ARENA_MAX (MALLCTL_ARENAS_ALL - 1)
36
37
38
+ typedef struct je_callbacks_t {
39
+ void * (* pool_mallocx )(size_t size , int flags );
40
+ void * (* pool_rallocx )(void * ptr , size_t size , int flags );
41
+ void (* pool_dallocx )(void * ptr , int flags );
42
+ int (* pool_mallctl )(const char * name , void * oldp , size_t * oldlenp ,
43
+ void * newp , size_t newlen );
44
+ #ifdef _WIN32
45
+ HMODULE lib_handle ;
46
+ #else
47
+ void * lib_handle ;
48
+ #endif
49
+ } je_callbacks_t ;
50
+
37
51
typedef struct jemalloc_memory_pool_t {
52
+ je_callbacks_t je_callbacks ; // jemalloc callbacks
38
53
umf_memory_provider_handle_t provider ;
39
54
unsigned int arena_index ; // index of jemalloc arena
40
55
// set to true if umfMemoryProviderFree() should never be called
@@ -51,6 +66,55 @@ static __TLS umf_result_t TLS_last_allocation_error;
51
66
52
67
static jemalloc_memory_pool_t * pool_by_arena_index [MALLCTL_ARENAS_ALL ];
53
68
69
+ typedef enum je_enums_t {
70
+ JE_LIB_NAME = 0 ,
71
+ JE_MALLOCX ,
72
+ JE_RALLOCX ,
73
+ JE_DALLOCX ,
74
+ JE_MALLCTL ,
75
+ JE_SYMBOLS_MAX // it has to be the last one
76
+ } je_enums_t ;
77
+
78
+ static const char * je_symbol [JE_SYMBOLS_MAX ] = {
79
+ #ifdef _WIN32
80
+ "libjemalloc.dll" , "je_mallocx" , "je_rallocx" , "je_dallocx" , "je_mallctl" ,
81
+ #else
82
+ "libjemalloc.so.2" , "mallocx" , "rallocx" , "dallocx" , "mallctl" ,
83
+ #endif
84
+ };
85
+
86
+ static int init_je_callbacks (je_callbacks_t * je_callbacks ) {
87
+ assert (je_callbacks );
88
+
89
+ const char * lib_name = je_symbol [JE_LIB_NAME ];
90
+ je_callbacks -> lib_handle = utils_open_library (lib_name , 0 );
91
+ if (!je_callbacks -> lib_handle ) {
92
+ LOG_FATAL (
93
+ "opening the %s library (required by jemalloc pool) failed - make "
94
+ "sure jemalloc is installed and it is in the default search paths" ,
95
+ lib_name );
96
+ return -1 ;
97
+ }
98
+
99
+ * (void * * )& je_callbacks -> pool_mallocx = utils_get_symbol_addr (
100
+ je_callbacks -> lib_handle , je_symbol [JE_MALLOCX ], lib_name );
101
+ * (void * * )& je_callbacks -> pool_rallocx = utils_get_symbol_addr (
102
+ je_callbacks -> lib_handle , je_symbol [JE_RALLOCX ], lib_name );
103
+ * (void * * )& je_callbacks -> pool_dallocx = utils_get_symbol_addr (
104
+ je_callbacks -> lib_handle , je_symbol [JE_DALLOCX ], lib_name );
105
+ * (void * * )& je_callbacks -> pool_mallctl = utils_get_symbol_addr (
106
+ je_callbacks -> lib_handle , je_symbol [JE_MALLCTL ], lib_name );
107
+
108
+ if (!je_callbacks -> pool_mallocx || !je_callbacks -> pool_rallocx ||
109
+ !je_callbacks -> pool_dallocx || !je_callbacks -> pool_mallctl ) {
110
+ LOG_ERR ("cannot find symbols in %s" , lib_name );
111
+ utils_close_library (je_callbacks -> lib_handle );
112
+ return -1 ;
113
+ }
114
+
115
+ return 0 ;
116
+ }
117
+
54
118
static jemalloc_memory_pool_t * get_pool_by_arena_index (unsigned arena_ind ) {
55
119
// there is no way to obtain MALLOCX_ARENA_MAX from jemalloc
56
120
// so this checks if arena_ind does not exceed assumed range
@@ -359,7 +423,7 @@ static void *op_malloc(void *pool, size_t size) {
359
423
// MALLOCX_TCACHE_NONE is set, because jemalloc can mix objects from different arenas inside
360
424
// the tcache, so we wouldn't be able to guarantee isolation of different providers.
361
425
int flags = MALLOCX_ARENA (je_pool -> arena_index ) | MALLOCX_TCACHE_NONE ;
362
- void * ptr = je_mallocx (size , flags );
426
+ void * ptr = ( * je_pool -> je_callbacks . pool_mallocx ) (size , flags );
363
427
if (ptr == NULL ) {
364
428
TLS_last_allocation_error = UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY ;
365
429
return NULL ;
@@ -371,12 +435,12 @@ static void *op_malloc(void *pool, size_t size) {
371
435
}
372
436
373
437
static umf_result_t op_free (void * pool , void * ptr ) {
374
- (void )pool ; // unused
375
438
assert (pool );
439
+ jemalloc_memory_pool_t * je_pool = (jemalloc_memory_pool_t * )pool ;
376
440
377
441
if (ptr != NULL ) {
378
442
VALGRIND_DO_MEMPOOL_FREE (pool , ptr );
379
- je_dallocx (ptr , MALLOCX_TCACHE_NONE );
443
+ ( * je_pool -> je_callbacks . pool_dallocx ) (ptr , MALLOCX_TCACHE_NONE );
380
444
}
381
445
382
446
return UMF_RESULT_SUCCESS ;
@@ -399,20 +463,21 @@ static void *op_calloc(void *pool, size_t num, size_t size) {
399
463
400
464
static void * op_realloc (void * pool , void * ptr , size_t size ) {
401
465
assert (pool );
466
+ jemalloc_memory_pool_t * je_pool = (jemalloc_memory_pool_t * )pool ;
467
+
402
468
if (size == 0 && ptr != NULL ) {
403
- je_dallocx (ptr , MALLOCX_TCACHE_NONE );
469
+ ( * je_pool -> je_callbacks . pool_dallocx ) (ptr , MALLOCX_TCACHE_NONE );
404
470
TLS_last_allocation_error = UMF_RESULT_SUCCESS ;
405
471
VALGRIND_DO_MEMPOOL_FREE (pool , ptr );
406
472
return NULL ;
407
473
} else if (ptr == NULL ) {
408
474
return op_malloc (pool , size );
409
475
}
410
476
411
- jemalloc_memory_pool_t * je_pool = (jemalloc_memory_pool_t * )pool ;
412
477
// MALLOCX_TCACHE_NONE is set, because jemalloc can mix objects from different arenas inside
413
478
// the tcache, so we wouldn't be able to guarantee isolation of different providers.
414
479
int flags = MALLOCX_ARENA (je_pool -> arena_index ) | MALLOCX_TCACHE_NONE ;
415
- void * new_ptr = je_rallocx (ptr , size , flags );
480
+ void * new_ptr = ( * je_pool -> je_callbacks . pool_rallocx ) (ptr , size , flags );
416
481
if (new_ptr == NULL ) {
417
482
TLS_last_allocation_error = UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY ;
418
483
return NULL ;
@@ -437,7 +502,7 @@ static void *op_aligned_alloc(void *pool, size_t size, size_t alignment) {
437
502
// the tcache, so we wouldn't be able to guarantee isolation of different providers.
438
503
int flags =
439
504
MALLOCX_ALIGN (alignment ) | MALLOCX_ARENA (arena ) | MALLOCX_TCACHE_NONE ;
440
- void * ptr = je_mallocx (size , flags );
505
+ void * ptr = ( * je_pool -> je_callbacks . pool_mallocx ) (size , flags );
441
506
if (ptr == NULL ) {
442
507
TLS_last_allocation_error = UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY ;
443
508
return NULL ;
@@ -453,6 +518,8 @@ static umf_result_t op_initialize(umf_memory_provider_handle_t provider,
453
518
assert (provider );
454
519
assert (out_pool );
455
520
521
+ umf_result_t umf_result = UMF_RESULT_ERROR_MEMORY_PROVIDER_SPECIFIC ;
522
+
456
523
umf_jemalloc_pool_params_handle_t je_params =
457
524
(umf_jemalloc_pool_params_handle_t )params ;
458
525
@@ -466,6 +533,13 @@ static umf_result_t op_initialize(umf_memory_provider_handle_t provider,
466
533
return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY ;
467
534
}
468
535
536
+ int ret = init_je_callbacks (& pool -> je_callbacks );
537
+ if (ret != 0 ) {
538
+ LOG_ERR ("loading jemalloc symbols failed" );
539
+ umf_result = UMF_RESULT_ERROR_UNKNOWN ;
540
+ goto err_free_pool ;
541
+ }
542
+
469
543
pool -> provider = provider ;
470
544
471
545
if (je_params ) {
@@ -475,8 +549,8 @@ static umf_result_t op_initialize(umf_memory_provider_handle_t provider,
475
549
}
476
550
477
551
unsigned arena_index ;
478
- err = je_mallctl ( "arenas.create" , ( void * ) & arena_index , & unsigned_size ,
479
- NULL , 0 );
552
+ err = ( * pool -> je_callbacks . pool_mallctl )(
553
+ "arenas.create" , ( void * ) & arena_index , & unsigned_size , NULL , 0 );
480
554
if (err ) {
481
555
LOG_ERR ("Could not create arena." );
482
556
goto err_free_pool ;
@@ -485,10 +559,11 @@ static umf_result_t op_initialize(umf_memory_provider_handle_t provider,
485
559
// setup extent_hooks for newly created arena
486
560
char cmd [64 ];
487
561
snprintf (cmd , sizeof (cmd ), "arena.%u.extent_hooks" , arena_index );
488
- err = je_mallctl (cmd , NULL , NULL , (void * )& pHooks , sizeof (void * ));
562
+ err = (* pool -> je_callbacks .pool_mallctl )(cmd , NULL , NULL , (void * )& pHooks ,
563
+ sizeof (void * ));
489
564
if (err ) {
490
565
snprintf (cmd , sizeof (cmd ), "arena.%u.destroy" , arena_index );
491
- je_mallctl (cmd , NULL , 0 , NULL , 0 );
566
+ ( * pool -> je_callbacks . pool_mallctl ) (cmd , NULL , 0 , NULL , 0 );
492
567
LOG_ERR ("Could not setup extent_hooks for newly created arena." );
493
568
goto err_free_pool ;
494
569
}
@@ -504,15 +579,15 @@ static umf_result_t op_initialize(umf_memory_provider_handle_t provider,
504
579
505
580
err_free_pool :
506
581
umf_ba_global_free (pool );
507
- return UMF_RESULT_ERROR_MEMORY_PROVIDER_SPECIFIC ;
582
+ return umf_result ;
508
583
}
509
584
510
585
static void op_finalize (void * pool ) {
511
586
assert (pool );
512
587
jemalloc_memory_pool_t * je_pool = (jemalloc_memory_pool_t * )pool ;
513
588
char cmd [64 ];
514
589
snprintf (cmd , sizeof (cmd ), "arena.%u.destroy" , je_pool -> arena_index );
515
- je_mallctl (cmd , NULL , 0 , NULL , 0 );
590
+ ( * je_pool -> je_callbacks . pool_mallctl ) (cmd , NULL , 0 , NULL , 0 );
516
591
pool_by_arena_index [je_pool -> arena_index ] = NULL ;
517
592
umf_ba_global_free (je_pool );
518
593
0 commit comments