@@ -37,68 +37,143 @@ struct umf_memory_tracker_t {
3737typedef struct tracker_alloc_info_t {
3838 umf_memory_pool_handle_t pool ;
3939 size_t size ;
40+ // list of previous entries with the same address (LIFO)
41+ struct tracker_alloc_info_t * prev ;
4042} tracker_alloc_info_t ;
4143
42- static umf_result_t umfMemoryTrackerAdd ( umf_memory_tracker_handle_t hTracker ,
43- umf_memory_pool_handle_t pool ,
44- const void * ptr , size_t size ) {
44+ static umf_result_t
45+ umfMemoryTrackerAddValue ( umf_memory_tracker_handle_t hTracker , const void * ptr ,
46+ tracker_alloc_info_t * new_value ) {
4547 assert (ptr );
48+ assert (new_value );
4649
47- tracker_alloc_info_t * value = umf_ba_alloc (hTracker -> alloc_info_allocator );
48- if (value == NULL ) {
49- LOG_ERR ("failed to allocate tracker value, ptr=%p, size=%zu" , ptr ,
50- size );
51- return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY ;
52- }
53-
54- value -> pool = pool ;
55- value -> size = size ;
56-
57- int ret =
58- critnib_insert (hTracker -> alloc_segments_map , (uintptr_t )ptr , value , 0 );
50+ umf_result_t umf_result = UMF_RESULT_ERROR_UNKNOWN ;
5951
52+ int ret = critnib_insert (hTracker -> alloc_segments_map , (uintptr_t )ptr ,
53+ new_value , 0 );
6054 if (ret == 0 ) {
6155 LOG_DEBUG (
62- "memory region is added, tracker=%p, ptr=%p, pool=%p, size=%zu" ,
63- (void * )hTracker , ptr , (void * )pool , size );
56+ "memory region added to the tracker=%p, ptr=%p, pool=%p, size=%zu" ,
57+ (void * )hTracker , ptr , (void * )new_value -> pool , new_value -> size );
6458 return UMF_RESULT_SUCCESS ;
6559 }
6660
67- LOG_ERR ("failed to insert tracker value, ret=%d, ptr=%p, pool=%p, size=%zu" ,
68- ret , ptr , (void * )pool , size );
61+ // failed to insert to the tracker a new value
6962
70- umf_ba_free (hTracker -> alloc_info_allocator , value );
63+ if (ret != EEXIST ) {
64+ if (ret == ENOMEM ) {
65+ umf_result = UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY ;
66+ }
67+ goto err_message ;
68+ }
69+
70+ // there already is an entry with the same address in the tracker
71+
72+ ret = utils_mutex_lock (& hTracker -> splitMergeMutex );
73+ if (ret ) {
74+ goto err_message ;
75+ }
76+
77+ tracker_alloc_info_t * prev_value = (tracker_alloc_info_t * )critnib_get (
78+ hTracker -> alloc_segments_map , (uintptr_t )ptr );
79+ if (!prev_value ) {
80+ LOG_ERR ("the previous entry not found in the tracker" );
81+ goto err_unlock ;
82+ }
83+ if (new_value -> pool == prev_value -> pool ) {
84+ LOG_ERR ("cannot add the next entry with the same address for the same "
85+ "pool" );
86+ goto err_unlock ;
87+ }
88+
89+ new_value -> prev = prev_value ;
90+
91+ ret = critnib_insert (hTracker -> alloc_segments_map , (uintptr_t )ptr ,
92+ new_value , 1 ); // update existing entry
93+ if (ret ) {
94+ goto err_unlock ;
95+ }
96+
97+ utils_mutex_unlock (& hTracker -> splitMergeMutex );
98+
99+ LOG_DEBUG (
100+ "memory region added to the tracker=%p, ptr=%p, pool=%p, size=%zu" ,
101+ (void * )hTracker , ptr , (void * )new_value -> pool , new_value -> size );
71102
72- if (ret == ENOMEM ) {
103+ return UMF_RESULT_SUCCESS ;
104+
105+ err_unlock :
106+ utils_mutex_unlock (& hTracker -> splitMergeMutex );
107+
108+ err_message :
109+ LOG_ERR ("failed to insert a new value to the tracker, ret=%d, ptr=%p, "
110+ "pool=%p, size=%zu" ,
111+ ret , ptr , (void * )new_value -> pool , new_value -> size );
112+
113+ return umf_result ;
114+ }
115+
116+ static umf_result_t umfMemoryTrackerAdd (umf_memory_tracker_handle_t hTracker ,
117+ umf_memory_pool_handle_t pool ,
118+ const void * ptr , size_t size ) {
119+ assert (ptr );
120+
121+ tracker_alloc_info_t * new_value =
122+ umf_ba_alloc (hTracker -> alloc_info_allocator );
123+ if (new_value == NULL ) {
124+ LOG_ERR ("failed to allocate a tracker value, ptr=%p, size=%zu" , ptr ,
125+ size );
73126 return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY ;
74127 }
75128
76- return UMF_RESULT_ERROR_UNKNOWN ;
129+ new_value -> pool = pool ;
130+ new_value -> size = size ;
131+ new_value -> prev = NULL ;
132+
133+ umf_result_t umf_result =
134+ umfMemoryTrackerAddValue (hTracker , ptr , new_value );
135+ if (umf_result != UMF_RESULT_SUCCESS ) {
136+ umf_ba_free (hTracker -> alloc_info_allocator , new_value );
137+ return umf_result ;
138+ }
139+
140+ return UMF_RESULT_SUCCESS ;
77141}
78142
79143static umf_result_t umfMemoryTrackerRemove (umf_memory_tracker_handle_t hTracker ,
80144 const void * ptr ) {
81145 assert (ptr );
82146
147+ umf_result_t umf_result = UMF_RESULT_SUCCESS ;
148+
83149 // TODO: there is no support for removing partial ranges (or multiple entries
84150 // in a single remove call) yet.
85151 // Every umfMemoryTrackerAdd(..., ptr, ...) should have a corresponding
86152 // umfMemoryTrackerRemove call with the same ptr value.
87153
88- void * value = critnib_remove (hTracker -> alloc_segments_map , (uintptr_t )ptr );
154+ tracker_alloc_info_t * value =
155+ critnib_remove (hTracker -> alloc_segments_map , (uintptr_t )ptr );
89156 if (!value ) {
90157 LOG_ERR ("pointer %p not found in the alloc_segments_map" , ptr );
91158 return UMF_RESULT_ERROR_UNKNOWN ;
92159 }
93160
94- tracker_alloc_info_t * v = value ;
95-
96161 LOG_DEBUG ("memory region removed: tracker=%p, ptr=%p, size=%zu" ,
97- (void * )hTracker , ptr , v -> size );
162+ (void * )hTracker , ptr , value -> size );
163+
164+ if (value -> prev ) {
165+ tracker_alloc_info_t * prev_value = value -> prev ;
166+ umf_result = umfMemoryTrackerAddValue (hTracker , ptr , prev_value );
167+ if (umf_result != UMF_RESULT_SUCCESS ) {
168+ LOG_ERR ("failed to add the previous entry to the tracker, ptr = "
169+ "%p, size = %zu, umf_result = %d" ,
170+ ptr , prev_value -> size , umf_result );
171+ }
172+ }
98173
99174 umf_ba_free (hTracker -> alloc_info_allocator , value );
100175
101- return UMF_RESULT_SUCCESS ;
176+ return umf_result ;
102177}
103178
104179umf_memory_pool_handle_t umfMemoryTrackerGetPool (const void * ptr ) {
@@ -247,6 +322,7 @@ static umf_result_t trackingAllocationSplit(void *hProvider, void *ptr,
247322 goto err ;
248323 }
249324
325+ splitValue -> prev = value -> prev ;
250326 int cret =
251327 critnib_insert (provider -> hTracker -> alloc_segments_map , (uintptr_t )ptr ,
252328 (void * )splitValue , 1 /* update */ );
@@ -322,6 +398,7 @@ static umf_result_t trackingAllocationMerge(void *hProvider, void *lowPtr,
322398
323399 // We'll have a duplicate entry for the range [highPtr, highValue->size] but this is fine,
324400 // the value is the same anyway and we forbid removing that range concurrently
401+ mergedValue -> prev = lowValue -> prev ;
325402 int cret =
326403 critnib_insert (provider -> hTracker -> alloc_segments_map ,
327404 (uintptr_t )lowPtr , (void * )mergedValue , 1 /* update */ );
0 commit comments