Skip to content

Commit b1770dd

Browse files
committed
Fix concurrency issue in tracking provider on n_children variable
1 parent d429dc4 commit b1770dd

File tree

2 files changed

+30
-13
lines changed

2 files changed

+30
-13
lines changed

src/provider/provider_tracking.c

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ static tracker_alloc_info_t *get_most_nested_alloc_segment(
8181
uintptr_t parent_key = 0;
8282
uintptr_t rkey = 0;
8383
uint64_t rsize = 0;
84+
size_t n_children = 0;
8485
int level = 0;
8586
int found = 0;
8687

@@ -113,8 +114,8 @@ static tracker_alloc_info_t *get_most_nested_alloc_segment(
113114
}
114115

115116
utils_atomic_load_acquire_u64((uint64_t *)&rvalue->size, &rsize);
116-
117-
if (found && ((uintptr_t)ptr < rkey + rsize) && rvalue->n_children) {
117+
utils_atomic_load_acquire_size_t(&rvalue->n_children, &n_children);
118+
if (found && ((uintptr_t)ptr < rkey + rsize) && n_children) {
118119
if (level == MAX_LEVELS_OF_ALLOC_SEGMENT_MAP - 1) {
119120
break;
120121
}
@@ -146,13 +147,13 @@ static tracker_alloc_info_t *get_most_nested_alloc_segment(
146147
ref_value = NULL;
147148
}
148149
}
149-
} while (found && ((uintptr_t)ptr < rkey + rsize) && rvalue->n_children);
150+
} while (found && ((uintptr_t)ptr < rkey + rsize) && n_children);
150151

151152
if (!rvalue || rkey != (uintptr_t)ptr) {
152153
return NULL;
153154
}
154155

155-
if (no_children && (rvalue->n_children > 0)) {
156+
if (no_children && (n_children > 0)) {
156157
return NULL;
157158
}
158159

@@ -207,11 +208,12 @@ umfMemoryTrackerAddAtLevel(umf_memory_tracker_handle_t hTracker, int level,
207208
(void *)hTracker, level, (void *)pool, ptr, size);
208209

209210
if (parent_value) {
210-
parent_value->n_children++;
211+
size_t n_children =
212+
utils_atomic_increment_size_t(&parent_value->n_children) + 1;
211213
LOG_DEBUG(
212214
"child #%zu added to memory region: tracker=%p, level=%i, "
213215
"pool=%p, ptr=%p, size=%zu",
214-
parent_value->n_children, (void *)hTracker, level - 1,
216+
n_children, (void *)hTracker, level - 1,
215217
(void *)parent_value->pool, (void *)parent_key,
216218
parent_value->size);
217219
assert(ref_parent_value);
@@ -243,6 +245,7 @@ static umf_result_t umfMemoryTrackerAdd(umf_memory_tracker_handle_t hTracker,
243245
uintptr_t parent_key = 0;
244246
uintptr_t rkey = 0;
245247
uint64_t rsize = 0;
248+
size_t n_children = 0;
246249
int level = 0;
247250
int found = 0;
248251

@@ -311,7 +314,8 @@ static umf_result_t umfMemoryTrackerAdd(umf_memory_tracker_handle_t hTracker,
311314
ref_parent_value = ref_value;
312315
level++;
313316
}
314-
} while (found && ((uintptr_t)ptr < rkey + rsize) && rvalue->n_children);
317+
utils_atomic_load_acquire_size_t(&rvalue->n_children, &n_children);
318+
} while (found && ((uintptr_t)ptr < rkey + rsize) && n_children);
315319

316320
if (ref_value && ref_value != ref_parent_value) {
317321
critnib_release(hTracker->alloc_segments_map[level], ref_value);
@@ -366,12 +370,14 @@ static umf_result_t umfMemoryTrackerRemove(umf_memory_tracker_handle_t hTracker,
366370
critnib_release(hTracker->alloc_segments_map[level], ref_value);
367371

368372
if (parent_value) {
373+
size_t n_children =
374+
utils_atomic_decrement_size_t(&parent_value->n_children);
369375
LOG_DEBUG(
370376
"child #%zu removed from memory region: tracker=%p, level=%i, "
371377
"pool=%p, ptr=%p, size=%zu",
372-
parent_value->n_children, (void *)hTracker, level - 1,
373-
(void *)parent_value->pool, (void *)parent_key, parent_value->size);
374-
parent_value->n_children--;
378+
n_children, (void *)hTracker, level - 1, (void *)parent_value->pool,
379+
(void *)parent_key, parent_value->size);
380+
375381
assert(ref_parent_value);
376382
assert(level >= 1);
377383
// release the ref_parent_value got from get_most_nested_alloc_segment()
@@ -485,6 +491,7 @@ umf_result_t umfMemoryTrackerGetAllocInfo(const void *ptr,
485491
uintptr_t top_most_key = 0;
486492
uintptr_t rkey = 0;
487493
uint64_t rsize = 0;
494+
size_t n_children = 0;
488495
int level = 0;
489496
int found = 0;
490497

@@ -519,7 +526,7 @@ umf_result_t umfMemoryTrackerGetAllocInfo(const void *ptr,
519526
}
520527

521528
utils_atomic_load_acquire_u64((uint64_t *)&rvalue->size, &rsize);
522-
529+
utils_atomic_load_acquire_size_t(&rvalue->n_children, &n_children);
523530
if (found && (uintptr_t)ptr < rkey + rsize) {
524531
top_most_key = rkey;
525532
top_most_value = rvalue;
@@ -530,13 +537,13 @@ umf_result_t umfMemoryTrackerGetAllocInfo(const void *ptr,
530537
}
531538
ref_top_most_value = ref_value;
532539
ref_level = level;
533-
if (rvalue->n_children == 0 ||
540+
if (n_children == 0 ||
534541
level == MAX_LEVELS_OF_ALLOC_SEGMENT_MAP - 1) {
535542
break;
536543
}
537544
level++;
538545
}
539-
} while (found && (uintptr_t)ptr < rkey + rsize && rvalue->n_children);
546+
} while (found && (uintptr_t)ptr < rkey + rsize && n_children);
540547

541548
if (!top_most_value) {
542549
if (ref_value) {

src/utils/utils_concurrency.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,16 @@ static inline bool utils_compare_exchange_size_t(size_t *ptr, size_t *expected,
270270
(uint64_t *)desired);
271271
}
272272

273+
static inline size_t utils_atomic_increment_size_t(size_t *val) {
274+
COMPILE_ERROR_ON(sizeof(size_t) != sizeof(uint64_t));
275+
return utils_atomic_increment_u64((uint64_t *)val);
276+
}
277+
278+
static inline size_t utils_atomic_decrement_size_t(size_t *val) {
279+
COMPILE_ERROR_ON(sizeof(size_t) != sizeof(uint64_t));
280+
return utils_atomic_decrement_u64((uint64_t *)val);
281+
}
282+
273283
#ifdef __cplusplus
274284
}
275285
#endif

0 commit comments

Comments
 (0)