@@ -37,7 +37,7 @@ struct umf_memory_tracker_t {
3737 // when one memory pool acts as a memory provider
3838 // for another memory pool (nested memory pooling).
3939 critnib * alloc_segments_map [MAX_LEVELS_OF_ALLOC_SEGMENT_MAP ];
40- utils_mutex_t splitMergeMutex ;
40+ utils_mutex_t mutex ;
4141};
4242
4343typedef struct tracker_alloc_info_t {
@@ -49,53 +49,75 @@ typedef struct tracker_alloc_info_t {
4949 size_t n_children ;
5050} tracker_alloc_info_t ;
5151
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 ) {
5560 assert (ptr );
5661
5762 tracker_alloc_info_t * parent_value = NULL ;
5863 tracker_alloc_info_t * rvalue = NULL ;
5964 uintptr_t parent_key = 0 ;
6065 uintptr_t rkey = 0 ;
61- int parent_level = 0 ;
6266 int level = 0 ;
6367 int found = 0 ;
6468
65- // Find the most nested (in the highest level) entry
66- // in the critnib maps that contains the given 'ptr' pointer.
6769 do {
6870 assert (level < MAX_LEVELS_OF_ALLOC_SEGMENT_MAP );
6971 found =
7072 critnib_find (hTracker -> alloc_segments_map [level ], (uintptr_t )ptr ,
7173 FIND_LE , (void * )& rkey , (void * * )& rvalue );
7274 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 ;
8782 }
88- parent_key = rkey ;
89- parent_value = rvalue ;
90- parent_level = level ;
91- level ++ ;
9283 }
9384 } while (found && ((uintptr_t )ptr < rkey + rvalue -> size ) &&
9485 rvalue -> n_children );
9586
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+
96118 tracker_alloc_info_t * value = umf_ba_alloc (hTracker -> alloc_info_allocator );
97119 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 ,
99121 size );
100122 return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY ;
101123 }
@@ -111,88 +133,93 @@ static umf_result_t umfMemoryTrackerAdd(umf_memory_tracker_handle_t hTracker,
111133 LOG_DEBUG ("memory region is added, tracker=%p, level=%i, pool=%p, "
112134 "ptr=%p, size=%zu" ,
113135 (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-
125136 return UMF_RESULT_SUCCESS ;
126137 }
138+ if (ret == ENOMEM ) {
139+ umf_result = UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY ;
140+ }
127141
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 );
130145
131146 umf_ba_free (hTracker -> alloc_info_allocator , value );
132147
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 ;
138149}
139150
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 ) {
148154 assert (ptr );
149155
156+ umf_result_t umf_result = UMF_RESULT_ERROR_UNKNOWN ;
150157 tracker_alloc_info_t * parent_value = NULL ;
151158 tracker_alloc_info_t * rvalue = NULL ;
152159 uintptr_t parent_key = 0 ;
153160 uintptr_t rkey = 0 ;
161+ int parent_level = 0 ;
154162 int level = 0 ;
155163 int found = 0 ;
156164
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.
157172 do {
158173 assert (level < MAX_LEVELS_OF_ALLOC_SEGMENT_MAP );
159174 found =
160175 critnib_find (hTracker -> alloc_segments_map [level ], (uintptr_t )ptr ,
161176 FIND_LE , (void * )& rkey , (void * * )& rvalue );
162177 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 ;
170194 }
195+ parent_key = rkey ;
196+ parent_value = rvalue ;
197+ parent_level = level ;
198+ level ++ ;
171199 }
172200 } while (found && ((uintptr_t )ptr < rkey + rvalue -> size ) &&
173201 rvalue -> n_children );
174202
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 ;
177206 }
178207
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 );
181215 }
182216
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 ;
192218
193- assert (!no_children || rvalue -> n_children == 0 );
219+ err_unlock :
220+ utils_mutex_unlock (& hTracker -> mutex );
194221
195- return rvalue ;
222+ return umf_result ;
196223}
197224
198225static 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,
204231 // Every umfMemoryTrackerAdd(..., ptr, ...) should have a corresponding
205232 // umfMemoryTrackerRemove call with the same ptr value.
206233
234+ umf_result_t umf_result = UMF_RESULT_ERROR_UNKNOWN ;
207235 tracker_alloc_info_t * parent_value = NULL ;
208236 uintptr_t parent_key = 0 ;
209237 int level = 0 ;
210238
239+ int ret = utils_mutex_lock (& hTracker -> mutex );
240+ if (ret ) {
241+ return UMF_RESULT_ERROR_UNKNOWN ;
242+ }
243+
211244 // Find the most nested (on the highest level) entry in the map
212245 // with the `ptr` key and with no children - only such entry can be removed.
213246 tracker_alloc_info_t * value = get_most_nested_alloc_segment (
214247 hTracker , ptr , & level , & parent_key , & parent_value , 1 /* no_children */ );
215248 if (!value ) {
216249 LOG_ERR ("pointer %p not found in the alloc_segments_map" , ptr );
217- return UMF_RESULT_ERROR_UNKNOWN ;
250+ goto err_unlock ;
218251 }
219252
220253 assert (level < MAX_LEVELS_OF_ALLOC_SEGMENT_MAP );
@@ -236,7 +269,12 @@ static umf_result_t umfMemoryTrackerRemove(umf_memory_tracker_handle_t hTracker,
236269
237270 umf_ba_free (hTracker -> alloc_info_allocator , value );
238271
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 ;
240278}
241279
242280umf_memory_pool_handle_t umfMemoryTrackerGetPool (const void * ptr ) {
@@ -376,7 +414,7 @@ static umf_result_t trackingAllocationSplit(void *hProvider, void *ptr,
376414 splitValue -> size = firstSize ;
377415 splitValue -> n_children = 0 ;
378416
379- int r = utils_mutex_lock (& provider -> hTracker -> splitMergeMutex );
417+ int r = utils_mutex_lock (& provider -> hTracker -> mutex );
380418 if (r ) {
381419 goto err_lock ;
382420 }
@@ -419,11 +457,11 @@ static umf_result_t trackingAllocationSplit(void *hProvider, void *ptr,
419457
420458 // We'll have a duplicate entry for the range [highPtr, highValue->size] but this is fine,
421459 // 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 );
424462 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" ,
427465 highPtr , secondSize , ret );
428466 // revert the split
429467 assert (level < MAX_LEVELS_OF_ALLOC_SEGMENT_MAP );
@@ -440,7 +478,7 @@ static umf_result_t trackingAllocationSplit(void *hProvider, void *ptr,
440478
441479 // free the original value
442480 umf_ba_free (provider -> hTracker -> alloc_info_allocator , value );
443- utils_mutex_unlock (& provider -> hTracker -> splitMergeMutex );
481+ utils_mutex_unlock (& provider -> hTracker -> mutex );
444482
445483 LOG_DEBUG (
446484 "split memory region (level=%i): ptr=%p, totalSize=%zu, firstSize=%zu" ,
@@ -449,7 +487,7 @@ static umf_result_t trackingAllocationSplit(void *hProvider, void *ptr,
449487 return UMF_RESULT_SUCCESS ;
450488
451489err :
452- utils_mutex_unlock (& provider -> hTracker -> splitMergeMutex );
490+ utils_mutex_unlock (& provider -> hTracker -> mutex );
453491err_lock :
454492 umf_ba_free (provider -> hTracker -> alloc_info_allocator , splitValue );
455493
@@ -481,7 +519,7 @@ static umf_result_t trackingAllocationMerge(void *hProvider, void *lowPtr,
481519 int lowLevel = -2 ;
482520 int highLevel = -1 ;
483521
484- int r = utils_mutex_lock (& provider -> hTracker -> splitMergeMutex );
522+ int r = utils_mutex_lock (& provider -> hTracker -> mutex );
485523 if (r ) {
486524 goto err_lock ;
487525 }
@@ -548,7 +586,7 @@ static umf_result_t trackingAllocationMerge(void *hProvider, void *lowPtr,
548586
549587 umf_ba_free (provider -> hTracker -> alloc_info_allocator , erasedhighValue );
550588
551- utils_mutex_unlock (& provider -> hTracker -> splitMergeMutex );
589+ utils_mutex_unlock (& provider -> hTracker -> mutex );
552590
553591 LOG_DEBUG ("merged memory regions (level=%i): lowPtr=%p (child=%zu), "
554592 "highPtr=%p (child=%zu), totalSize=%zu" ,
@@ -563,7 +601,7 @@ static umf_result_t trackingAllocationMerge(void *hProvider, void *lowPtr,
563601 assert (0 );
564602
565603not_merged :
566- utils_mutex_unlock (& provider -> hTracker -> splitMergeMutex );
604+ utils_mutex_unlock (& provider -> hTracker -> mutex );
567605
568606err_lock :
569607 umf_ba_free (provider -> hTracker -> alloc_info_allocator , mergedValue );
@@ -1045,7 +1083,7 @@ umf_memory_tracker_handle_t umfMemoryTrackerCreate(void) {
10451083
10461084 handle -> alloc_info_allocator = alloc_info_allocator ;
10471085
1048- void * mutex_ptr = utils_mutex_init (& handle -> splitMergeMutex );
1086+ void * mutex_ptr = utils_mutex_init (& handle -> mutex );
10491087 if (!mutex_ptr ) {
10501088 goto err_destroy_alloc_info_allocator ;
10511089 }
@@ -1069,7 +1107,7 @@ umf_memory_tracker_handle_t umfMemoryTrackerCreate(void) {
10691107 critnib_delete (handle -> alloc_segments_map [j ]);
10701108 }
10711109 }
1072- utils_mutex_destroy_not_free (& handle -> splitMergeMutex );
1110+ utils_mutex_destroy_not_free (& handle -> mutex );
10731111err_destroy_alloc_info_allocator :
10741112 umf_ba_destroy (alloc_info_allocator );
10751113err_free_handle :
@@ -1102,7 +1140,7 @@ void umfMemoryTrackerDestroy(umf_memory_tracker_handle_t handle) {
11021140 handle -> alloc_segments_map [i ] = NULL ;
11031141 }
11041142 }
1105- utils_mutex_destroy_not_free (& handle -> splitMergeMutex );
1143+ utils_mutex_destroy_not_free (& handle -> mutex );
11061144 umf_ba_destroy (handle -> alloc_info_allocator );
11071145 handle -> alloc_info_allocator = NULL ;
11081146 umf_ba_global_free (handle );
0 commit comments