@@ -37,68 +37,143 @@ struct umf_memory_tracker_t {
37
37
typedef struct tracker_alloc_info_t {
38
38
umf_memory_pool_handle_t pool ;
39
39
size_t size ;
40
+ // list of previous entries with the same address (LIFO)
41
+ struct tracker_alloc_info_t * prev ;
40
42
} tracker_alloc_info_t ;
41
43
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 ) {
45
47
assert (ptr );
48
+ assert (new_value );
46
49
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 ;
59
51
52
+ int ret = critnib_insert (hTracker -> alloc_segments_map , (uintptr_t )ptr ,
53
+ new_value , 0 );
60
54
if (ret == 0 ) {
61
55
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 );
64
58
return UMF_RESULT_SUCCESS ;
65
59
}
66
60
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
69
62
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 );
71
102
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 );
73
126
return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY ;
74
127
}
75
128
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 ;
77
141
}
78
142
79
143
static umf_result_t umfMemoryTrackerRemove (umf_memory_tracker_handle_t hTracker ,
80
144
const void * ptr ) {
81
145
assert (ptr );
82
146
147
+ umf_result_t umf_result = UMF_RESULT_SUCCESS ;
148
+
83
149
// TODO: there is no support for removing partial ranges (or multiple entries
84
150
// in a single remove call) yet.
85
151
// Every umfMemoryTrackerAdd(..., ptr, ...) should have a corresponding
86
152
// umfMemoryTrackerRemove call with the same ptr value.
87
153
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 );
89
156
if (!value ) {
90
157
LOG_ERR ("pointer %p not found in the alloc_segments_map" , ptr );
91
158
return UMF_RESULT_ERROR_UNKNOWN ;
92
159
}
93
160
94
- tracker_alloc_info_t * v = value ;
95
-
96
161
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
+ }
98
173
99
174
umf_ba_free (hTracker -> alloc_info_allocator , value );
100
175
101
- return UMF_RESULT_SUCCESS ;
176
+ return umf_result ;
102
177
}
103
178
104
179
umf_memory_pool_handle_t umfMemoryTrackerGetPool (const void * ptr ) {
@@ -247,6 +322,7 @@ static umf_result_t trackingAllocationSplit(void *hProvider, void *ptr,
247
322
goto err ;
248
323
}
249
324
325
+ splitValue -> prev = value -> prev ;
250
326
int cret =
251
327
critnib_insert (provider -> hTracker -> alloc_segments_map , (uintptr_t )ptr ,
252
328
(void * )splitValue , 1 /* update */ );
@@ -322,6 +398,7 @@ static umf_result_t trackingAllocationMerge(void *hProvider, void *lowPtr,
322
398
323
399
// We'll have a duplicate entry for the range [highPtr, highValue->size] but this is fine,
324
400
// the value is the same anyway and we forbid removing that range concurrently
401
+ mergedValue -> prev = lowValue -> prev ;
325
402
int cret =
326
403
critnib_insert (provider -> hTracker -> alloc_segments_map ,
327
404
(uintptr_t )lowPtr , (void * )mergedValue , 1 /* update */ );
0 commit comments