@@ -37,7 +37,7 @@ struct umf_memory_tracker_t {
37
37
// when one memory pool acts as a memory provider
38
38
// for another memory pool (nested memory pooling).
39
39
critnib * alloc_segments_map [MAX_LEVELS_OF_ALLOC_SEGMENT_MAP ];
40
- utils_mutex_t splitMergeMutex ;
40
+ utils_mutex_t mutex ;
41
41
};
42
42
43
43
typedef struct tracker_alloc_info_t {
@@ -49,53 +49,75 @@ typedef struct tracker_alloc_info_t {
49
49
size_t n_children ;
50
50
} tracker_alloc_info_t ;
51
51
52
- static umf_result_t umfMemoryTrackerAdd (umf_memory_tracker_handle_t hTracker ,
53
- umf_memory_pool_handle_t pool ,
54
- const void * ptr , size_t size ) {
52
+ // Get the most nested (on the highest level) allocation segment in the map with the `ptr` key.
53
+ // If `no_children` is set to 1, the function will return the entry
54
+ // only if it has no children on the higher level.
55
+ // The function returns the entry if found, otherwise NULL.
56
+ static tracker_alloc_info_t * get_most_nested_alloc_segment (
57
+ umf_memory_tracker_handle_t hTracker , const void * ptr , int * _level ,
58
+ uintptr_t * _parent_key , tracker_alloc_info_t * * _parent_value ,
59
+ int no_children ) {
55
60
assert (ptr );
56
61
57
62
tracker_alloc_info_t * parent_value = NULL ;
58
63
tracker_alloc_info_t * rvalue = NULL ;
59
64
uintptr_t parent_key = 0 ;
60
65
uintptr_t rkey = 0 ;
61
- int parent_level = 0 ;
62
66
int level = 0 ;
63
67
int found = 0 ;
64
68
65
- // Find the most nested (in the highest level) entry
66
- // in the critnib maps that contains the given 'ptr' pointer.
67
69
do {
68
70
assert (level < MAX_LEVELS_OF_ALLOC_SEGMENT_MAP );
69
71
found =
70
72
critnib_find (hTracker -> alloc_segments_map [level ], (uintptr_t )ptr ,
71
73
FIND_LE , (void * )& rkey , (void * * )& rvalue );
72
74
if (found && (uintptr_t )ptr < rkey + rvalue -> size ) {
73
- if (level == MAX_LEVELS_OF_ALLOC_SEGMENT_MAP - 1 ) {
74
- // TODO: we need to support an arbitrary amount of layers in the future
75
- LOG_ERR ("tracker level is too high, ptr=%p, size=%zu" , ptr ,
76
- size );
77
- return UMF_RESULT_ERROR_INTERNAL ;
78
- }
79
- if (((uintptr_t )ptr + size ) > (rkey + rvalue -> size )) {
80
- LOG_ERR (
81
- "cannot insert to the tracker value (pool=%p, ptr=%p, "
82
- "size=%zu) "
83
- "that exceeds the parent value (pool=%p, ptr=%p, size=%zu)" ,
84
- (void * )pool , ptr , size , (void * )rvalue -> pool , (void * )rkey ,
85
- rvalue -> size );
86
- return UMF_RESULT_ERROR_INVALID_ARGUMENT ;
75
+ if (rvalue -> n_children ) {
76
+ if (level == MAX_LEVELS_OF_ALLOC_SEGMENT_MAP - 1 ) {
77
+ break ;
78
+ }
79
+ level ++ ;
80
+ parent_key = rkey ;
81
+ parent_value = rvalue ;
87
82
}
88
- parent_key = rkey ;
89
- parent_value = rvalue ;
90
- parent_level = level ;
91
- level ++ ;
92
83
}
93
84
} while (found && ((uintptr_t )ptr < rkey + rvalue -> size ) &&
94
85
rvalue -> n_children );
95
86
87
+ if (!rvalue || rkey != (uintptr_t )ptr ) {
88
+ return NULL ;
89
+ }
90
+
91
+ if (no_children && (rvalue -> n_children > 0 )) {
92
+ return NULL ;
93
+ }
94
+
95
+ if (_level ) {
96
+ * _level = level ;
97
+ }
98
+ if (_parent_key ) {
99
+ * _parent_key = parent_key ;
100
+ }
101
+ if (_parent_value ) {
102
+ * _parent_value = parent_value ;
103
+ }
104
+
105
+ assert (!no_children || rvalue -> n_children == 0 );
106
+
107
+ return rvalue ;
108
+ }
109
+
110
+ static umf_result_t
111
+ umfMemoryTrackerAddAtLevel (umf_memory_tracker_handle_t hTracker , int level ,
112
+ umf_memory_pool_handle_t pool , const void * ptr ,
113
+ size_t size ) {
114
+ assert (ptr );
115
+
116
+ umf_result_t umf_result = UMF_RESULT_ERROR_UNKNOWN ;
117
+
96
118
tracker_alloc_info_t * value = umf_ba_alloc (hTracker -> alloc_info_allocator );
97
119
if (value == NULL ) {
98
- LOG_ERR ("failed to allocate tracker value, ptr=%p, size=%zu" , ptr ,
120
+ LOG_ERR ("failed to allocate a tracker value, ptr=%p, size=%zu" , ptr ,
99
121
size );
100
122
return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY ;
101
123
}
@@ -111,88 +133,93 @@ static umf_result_t umfMemoryTrackerAdd(umf_memory_tracker_handle_t hTracker,
111
133
LOG_DEBUG ("memory region is added, tracker=%p, level=%i, pool=%p, "
112
134
"ptr=%p, size=%zu" ,
113
135
(void * )hTracker , level , (void * )pool , ptr , size );
114
-
115
- if (parent_value ) {
116
- parent_value -> n_children ++ ;
117
- LOG_DEBUG (
118
- "child #%zu added to memory region: tracker=%p, level=%i, "
119
- "pool=%p, ptr=%p, size=%zu" ,
120
- parent_value -> n_children , (void * )hTracker , parent_level ,
121
- (void * )parent_value -> pool , (void * )parent_key ,
122
- parent_value -> size );
123
- }
124
-
125
136
return UMF_RESULT_SUCCESS ;
126
137
}
138
+ if (ret == ENOMEM ) {
139
+ umf_result = UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY ;
140
+ }
127
141
128
- LOG_ERR ("failed to insert tracker value, ret=%d, pool=%p, ptr=%p size=%zu" ,
129
- ret , (void * )pool , ptr , size );
142
+ LOG_ERR (
143
+ "failed to insert the tracker value: pool=%p, ptr=%p, size=%zu, ret=%d" ,
144
+ (void * )pool , ptr , size , ret );
130
145
131
146
umf_ba_free (hTracker -> alloc_info_allocator , value );
132
147
133
- if (ret == ENOMEM ) {
134
- return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY ;
135
- }
136
-
137
- return UMF_RESULT_ERROR_UNKNOWN ;
148
+ return umf_result ;
138
149
}
139
150
140
- // Get the most nested (on the highest level) allocation segment in the map with the `ptr` key.
141
- // If `no_children` is set to 1, the function will return the entry
142
- // only if it has no children on the higher level.
143
- // The function returns the entry if found, otherwise NULL.
144
- static tracker_alloc_info_t * get_most_nested_alloc_segment (
145
- umf_memory_tracker_handle_t hTracker , const void * ptr , int * _level ,
146
- uintptr_t * _parent_key , tracker_alloc_info_t * * _parent_value ,
147
- int no_children ) {
151
+ static umf_result_t umfMemoryTrackerAdd (umf_memory_tracker_handle_t hTracker ,
152
+ umf_memory_pool_handle_t pool ,
153
+ const void * ptr , size_t size ) {
148
154
assert (ptr );
149
155
156
+ umf_result_t umf_result = UMF_RESULT_ERROR_UNKNOWN ;
150
157
tracker_alloc_info_t * parent_value = NULL ;
151
158
tracker_alloc_info_t * rvalue = NULL ;
152
159
uintptr_t parent_key = 0 ;
153
160
uintptr_t rkey = 0 ;
161
+ int parent_level = 0 ;
154
162
int level = 0 ;
155
163
int found = 0 ;
156
164
165
+ int ret = utils_mutex_lock (& hTracker -> mutex );
166
+ if (ret ) {
167
+ return UMF_RESULT_ERROR_UNKNOWN ;
168
+ }
169
+
170
+ // Find the most nested (in the highest level) entry
171
+ // in the critnib maps that contains the given 'ptr' pointer.
157
172
do {
158
173
assert (level < MAX_LEVELS_OF_ALLOC_SEGMENT_MAP );
159
174
found =
160
175
critnib_find (hTracker -> alloc_segments_map [level ], (uintptr_t )ptr ,
161
176
FIND_LE , (void * )& rkey , (void * * )& rvalue );
162
177
if (found && (uintptr_t )ptr < rkey + rvalue -> size ) {
163
- if (rvalue -> n_children ) {
164
- if (level == MAX_LEVELS_OF_ALLOC_SEGMENT_MAP - 1 ) {
165
- break ;
166
- }
167
- level ++ ;
168
- parent_key = rkey ;
169
- parent_value = rvalue ;
178
+ if (level == MAX_LEVELS_OF_ALLOC_SEGMENT_MAP - 1 ) {
179
+ // TODO: we need to support an arbitrary amount of layers in the future
180
+ LOG_ERR ("tracker level is too high, ptr=%p, size=%zu" , ptr ,
181
+ size );
182
+ umf_result = UMF_RESULT_ERROR_INTERNAL ;
183
+ goto err_unlock ;
184
+ }
185
+ if (((uintptr_t )ptr + size ) > (rkey + rvalue -> size )) {
186
+ LOG_ERR (
187
+ "cannot insert to the tracker value (pool=%p, ptr=%p, "
188
+ "size=%zu) "
189
+ "that exceeds the parent value (pool=%p, ptr=%p, size=%zu)" ,
190
+ (void * )pool , ptr , size , (void * )rvalue -> pool , (void * )rkey ,
191
+ rvalue -> size );
192
+ umf_result = UMF_RESULT_ERROR_INVALID_ARGUMENT ;
193
+ goto err_unlock ;
170
194
}
195
+ parent_key = rkey ;
196
+ parent_value = rvalue ;
197
+ parent_level = level ;
198
+ level ++ ;
171
199
}
172
200
} while (found && ((uintptr_t )ptr < rkey + rvalue -> size ) &&
173
201
rvalue -> n_children );
174
202
175
- if (!rvalue || rkey != (uintptr_t )ptr ) {
176
- return NULL ;
203
+ umf_result = umfMemoryTrackerAddAtLevel (hTracker , level , pool , ptr , size );
204
+ if (umf_result != UMF_RESULT_SUCCESS ) {
205
+ goto err_unlock ;
177
206
}
178
207
179
- if (no_children && (rvalue -> n_children > 0 )) {
180
- return NULL ;
208
+ if (parent_value ) {
209
+ parent_value -> n_children ++ ;
210
+ LOG_DEBUG ("child #%zu added to memory region: tracker=%p, level=%i, "
211
+ "pool=%p, ptr=%p, size=%zu" ,
212
+ parent_value -> n_children , (void * )hTracker , parent_level ,
213
+ (void * )parent_value -> pool , (void * )parent_key ,
214
+ parent_value -> size );
181
215
}
182
216
183
- if (_level ) {
184
- * _level = level ;
185
- }
186
- if (_parent_key ) {
187
- * _parent_key = parent_key ;
188
- }
189
- if (_parent_value ) {
190
- * _parent_value = parent_value ;
191
- }
217
+ umf_result = UMF_RESULT_SUCCESS ;
192
218
193
- assert (!no_children || rvalue -> n_children == 0 );
219
+ err_unlock :
220
+ utils_mutex_unlock (& hTracker -> mutex );
194
221
195
- return rvalue ;
222
+ return umf_result ;
196
223
}
197
224
198
225
static umf_result_t umfMemoryTrackerRemove (umf_memory_tracker_handle_t hTracker ,
@@ -204,17 +231,23 @@ static umf_result_t umfMemoryTrackerRemove(umf_memory_tracker_handle_t hTracker,
204
231
// Every umfMemoryTrackerAdd(..., ptr, ...) should have a corresponding
205
232
// umfMemoryTrackerRemove call with the same ptr value.
206
233
234
+ umf_result_t umf_result = UMF_RESULT_ERROR_UNKNOWN ;
207
235
tracker_alloc_info_t * parent_value = NULL ;
208
236
uintptr_t parent_key = 0 ;
209
237
int level = 0 ;
210
238
239
+ int ret = utils_mutex_lock (& hTracker -> mutex );
240
+ if (ret ) {
241
+ return UMF_RESULT_ERROR_UNKNOWN ;
242
+ }
243
+
211
244
// Find the most nested (on the highest level) entry in the map
212
245
// with the `ptr` key and with no children - only such entry can be removed.
213
246
tracker_alloc_info_t * value = get_most_nested_alloc_segment (
214
247
hTracker , ptr , & level , & parent_key , & parent_value , 1 /* no_children */ );
215
248
if (!value ) {
216
249
LOG_ERR ("pointer %p not found in the alloc_segments_map" , ptr );
217
- return UMF_RESULT_ERROR_UNKNOWN ;
250
+ goto err_unlock ;
218
251
}
219
252
220
253
assert (level < MAX_LEVELS_OF_ALLOC_SEGMENT_MAP );
@@ -236,7 +269,12 @@ static umf_result_t umfMemoryTrackerRemove(umf_memory_tracker_handle_t hTracker,
236
269
237
270
umf_ba_free (hTracker -> alloc_info_allocator , value );
238
271
239
- return UMF_RESULT_SUCCESS ;
272
+ umf_result = UMF_RESULT_SUCCESS ;
273
+
274
+ err_unlock :
275
+ utils_mutex_unlock (& hTracker -> mutex );
276
+
277
+ return umf_result ;
240
278
}
241
279
242
280
umf_memory_pool_handle_t umfMemoryTrackerGetPool (const void * ptr ) {
@@ -376,7 +414,7 @@ static umf_result_t trackingAllocationSplit(void *hProvider, void *ptr,
376
414
splitValue -> size = firstSize ;
377
415
splitValue -> n_children = 0 ;
378
416
379
- int r = utils_mutex_lock (& provider -> hTracker -> splitMergeMutex );
417
+ int r = utils_mutex_lock (& provider -> hTracker -> mutex );
380
418
if (r ) {
381
419
goto err_lock ;
382
420
}
@@ -419,11 +457,11 @@ static umf_result_t trackingAllocationSplit(void *hProvider, void *ptr,
419
457
420
458
// We'll have a duplicate entry for the range [highPtr, highValue->size] but this is fine,
421
459
// the value is the same anyway and we forbid removing that range concurrently
422
- ret = umfMemoryTrackerAdd (provider -> hTracker , provider -> pool , highPtr ,
423
- secondSize );
460
+ ret = umfMemoryTrackerAddAtLevel (provider -> hTracker , level , provider -> pool ,
461
+ highPtr , secondSize );
424
462
if (ret != UMF_RESULT_SUCCESS ) {
425
- LOG_ERR ("failed to add split region to the tracker, ptr=%p, size=%zu , "
426
- "ret=%d" ,
463
+ LOG_ERR ("failed to add the split region to the tracker, ptr=%p, "
464
+ "size=%zu, ret=%d" ,
427
465
highPtr , secondSize , ret );
428
466
// revert the split
429
467
assert (level < MAX_LEVELS_OF_ALLOC_SEGMENT_MAP );
@@ -440,7 +478,7 @@ static umf_result_t trackingAllocationSplit(void *hProvider, void *ptr,
440
478
441
479
// free the original value
442
480
umf_ba_free (provider -> hTracker -> alloc_info_allocator , value );
443
- utils_mutex_unlock (& provider -> hTracker -> splitMergeMutex );
481
+ utils_mutex_unlock (& provider -> hTracker -> mutex );
444
482
445
483
LOG_DEBUG (
446
484
"split memory region (level=%i): ptr=%p, totalSize=%zu, firstSize=%zu" ,
@@ -449,7 +487,7 @@ static umf_result_t trackingAllocationSplit(void *hProvider, void *ptr,
449
487
return UMF_RESULT_SUCCESS ;
450
488
451
489
err :
452
- utils_mutex_unlock (& provider -> hTracker -> splitMergeMutex );
490
+ utils_mutex_unlock (& provider -> hTracker -> mutex );
453
491
err_lock :
454
492
umf_ba_free (provider -> hTracker -> alloc_info_allocator , splitValue );
455
493
@@ -481,7 +519,7 @@ static umf_result_t trackingAllocationMerge(void *hProvider, void *lowPtr,
481
519
int lowLevel = -2 ;
482
520
int highLevel = -1 ;
483
521
484
- int r = utils_mutex_lock (& provider -> hTracker -> splitMergeMutex );
522
+ int r = utils_mutex_lock (& provider -> hTracker -> mutex );
485
523
if (r ) {
486
524
goto err_lock ;
487
525
}
@@ -548,7 +586,7 @@ static umf_result_t trackingAllocationMerge(void *hProvider, void *lowPtr,
548
586
549
587
umf_ba_free (provider -> hTracker -> alloc_info_allocator , erasedhighValue );
550
588
551
- utils_mutex_unlock (& provider -> hTracker -> splitMergeMutex );
589
+ utils_mutex_unlock (& provider -> hTracker -> mutex );
552
590
553
591
LOG_DEBUG ("merged memory regions (level=%i): lowPtr=%p (child=%zu), "
554
592
"highPtr=%p (child=%zu), totalSize=%zu" ,
@@ -563,7 +601,7 @@ static umf_result_t trackingAllocationMerge(void *hProvider, void *lowPtr,
563
601
assert (0 );
564
602
565
603
not_merged :
566
- utils_mutex_unlock (& provider -> hTracker -> splitMergeMutex );
604
+ utils_mutex_unlock (& provider -> hTracker -> mutex );
567
605
568
606
err_lock :
569
607
umf_ba_free (provider -> hTracker -> alloc_info_allocator , mergedValue );
@@ -1045,7 +1083,7 @@ umf_memory_tracker_handle_t umfMemoryTrackerCreate(void) {
1045
1083
1046
1084
handle -> alloc_info_allocator = alloc_info_allocator ;
1047
1085
1048
- void * mutex_ptr = utils_mutex_init (& handle -> splitMergeMutex );
1086
+ void * mutex_ptr = utils_mutex_init (& handle -> mutex );
1049
1087
if (!mutex_ptr ) {
1050
1088
goto err_destroy_alloc_info_allocator ;
1051
1089
}
@@ -1069,7 +1107,7 @@ umf_memory_tracker_handle_t umfMemoryTrackerCreate(void) {
1069
1107
critnib_delete (handle -> alloc_segments_map [j ]);
1070
1108
}
1071
1109
}
1072
- utils_mutex_destroy_not_free (& handle -> splitMergeMutex );
1110
+ utils_mutex_destroy_not_free (& handle -> mutex );
1073
1111
err_destroy_alloc_info_allocator :
1074
1112
umf_ba_destroy (alloc_info_allocator );
1075
1113
err_free_handle :
@@ -1102,7 +1140,7 @@ void umfMemoryTrackerDestroy(umf_memory_tracker_handle_t handle) {
1102
1140
handle -> alloc_segments_map [i ] = NULL ;
1103
1141
}
1104
1142
}
1105
- utils_mutex_destroy_not_free (& handle -> splitMergeMutex );
1143
+ utils_mutex_destroy_not_free (& handle -> mutex );
1106
1144
umf_ba_destroy (handle -> alloc_info_allocator );
1107
1145
handle -> alloc_info_allocator = NULL ;
1108
1146
umf_ba_global_free (handle );
0 commit comments