Skip to content

Commit a41417c

Browse files
committed
Add lock to umfMemoryTrackerAdd() and umfMemoryTrackerRemove()
Signed-off-by: Lukasz Dorau <[email protected]>
1 parent 3ba7b88 commit a41417c

File tree

1 file changed

+127
-89
lines changed

1 file changed

+127
-89
lines changed

src/provider/provider_tracking.c

Lines changed: 127 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -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

4343
typedef 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

198225
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,
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

242280
umf_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

451489
err:
452-
utils_mutex_unlock(&provider->hTracker->splitMergeMutex);
490+
utils_mutex_unlock(&provider->hTracker->mutex);
453491
err_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

565603
not_merged:
566-
utils_mutex_unlock(&provider->hTracker->splitMergeMutex);
604+
utils_mutex_unlock(&provider->hTracker->mutex);
567605

568606
err_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);
10731111
err_destroy_alloc_info_allocator:
10741112
umf_ba_destroy(alloc_info_allocator);
10751113
err_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

Comments
 (0)