Skip to content

Commit 8f255c1

Browse files
committed
Simplify and improve trackingAllocationMerge()
We do not need to allocate a new mergedValue, update critnib using critnib_insert() in the update mode and free the old value. It is enough to just update atomically the size of the first part: utils_atomic_store_release_u64((uint64_t *)&lowValue->size, totalSize); The tracker entries cannot be merged if they are used (if they have children). Signed-off-by: Lukasz Dorau <[email protected]>
1 parent 52668c3 commit 8f255c1

File tree

1 file changed

+31
-46
lines changed

1 file changed

+31
-46
lines changed

src/provider/provider_tracking.c

Lines changed: 31 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -608,17 +608,6 @@ static umf_result_t trackingAllocationMerge(void *hProvider, void *lowPtr,
608608
umf_tracking_memory_provider_t *provider =
609609
(umf_tracking_memory_provider_t *)hProvider;
610610

611-
tracker_alloc_info_t *mergedValue =
612-
umf_ba_alloc(provider->hTracker->alloc_info_allocator);
613-
614-
if (!mergedValue) {
615-
return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY;
616-
}
617-
618-
mergedValue->pool = provider->pool;
619-
mergedValue->size = totalSize;
620-
mergedValue->n_children = 0;
621-
622611
// any different negative values
623612
int lowLevel = -2;
624613
int highLevel = -1;
@@ -629,87 +618,83 @@ static umf_result_t trackingAllocationMerge(void *hProvider, void *lowPtr,
629618
}
630619

631620
tracker_alloc_info_t *lowValue = get_most_nested_alloc_segment(
632-
provider->hTracker, lowPtr, &lowLevel, NULL, NULL,
633-
0 /* no_children */); // can have children
621+
provider->hTracker, lowPtr, &lowLevel, NULL, NULL, 0 /* no_children */);
634622
if (!lowValue) {
635623
LOG_FATAL("no left value");
636624
ret = UMF_RESULT_ERROR_INVALID_ARGUMENT;
637-
goto err_assert;
625+
goto err_fatal;
638626
}
639-
tracker_alloc_info_t *highValue = get_most_nested_alloc_segment(
640-
provider->hTracker, highPtr, &highLevel, NULL, NULL,
641-
0 /* no_children */); // can have children
627+
if (lowValue->n_children) {
628+
LOG_FATAL("left value is used (has children)");
629+
ret = UMF_RESULT_ERROR_INVALID_ARGUMENT;
630+
goto err_fatal;
631+
}
632+
633+
tracker_alloc_info_t *highValue =
634+
get_most_nested_alloc_segment(provider->hTracker, highPtr, &highLevel,
635+
NULL, NULL, 0 /* no_children */);
642636
if (!highValue) {
643637
LOG_FATAL("no right value");
644638
ret = UMF_RESULT_ERROR_INVALID_ARGUMENT;
645-
goto err_assert;
639+
goto err_fatal;
646640
}
641+
if (highValue->n_children) {
642+
LOG_FATAL("right value is used (has children)");
643+
ret = UMF_RESULT_ERROR_INVALID_ARGUMENT;
644+
goto err_fatal;
645+
}
646+
647647
if (lowLevel != highLevel) {
648648
LOG_FATAL("tracker level mismatch");
649649
ret = UMF_RESULT_ERROR_INVALID_ARGUMENT;
650-
goto err_assert;
650+
goto err_fatal;
651651
}
652652
if (lowValue->pool != highValue->pool) {
653653
LOG_FATAL("pool mismatch");
654654
ret = UMF_RESULT_ERROR_INVALID_ARGUMENT;
655-
goto err_assert;
655+
goto err_fatal;
656656
}
657657
if (lowValue->size + highValue->size != totalSize) {
658658
LOG_FATAL("lowValue->size + highValue->size != totalSize");
659659
ret = UMF_RESULT_ERROR_INVALID_ARGUMENT;
660-
goto err_assert;
660+
goto err_fatal;
661661
}
662662

663-
mergedValue->n_children = lowValue->n_children + highValue->n_children;
664-
665663
ret = umfMemoryProviderAllocationMerge(provider->hUpstream, lowPtr, highPtr,
666664
totalSize);
667665
if (ret != UMF_RESULT_SUCCESS) {
668666
LOG_WARN("upstream provider failed to merge regions");
669-
goto not_merged;
667+
goto cannot_merge;
670668
}
671669

672-
size_t lno = lowValue->n_children;
673-
size_t hno = highValue->n_children;
674-
675-
// We'll have a duplicate entry for the range [highPtr, highValue->size] but this is fine,
676-
// the value is the same anyway and we forbid removing that range concurrently
677-
int cret =
678-
critnib_insert(provider->hTracker->alloc_segments_map[lowLevel],
679-
(uintptr_t)lowPtr, (void *)mergedValue, 1 /* update */);
680-
// this cannot fail since we know the element exists (nothing to allocate)
681-
assert(cret == 0);
682-
(void)cret;
683-
684-
// free old value that we just replaced with mergedValue
685-
umf_ba_free(provider->hTracker->alloc_info_allocator, lowValue);
670+
// we only need to update the size of the first part
671+
utils_atomic_store_release_u64((uint64_t *)&lowValue->size, totalSize);
686672

687673
void *erasedhighValue = critnib_remove(
688674
provider->hTracker->alloc_segments_map[highLevel], (uintptr_t)highPtr);
689675
assert(erasedhighValue == highValue);
690-
691-
umf_ba_free(provider->hTracker->alloc_info_allocator, erasedhighValue);
676+
(void)erasedhighValue; // unused in the Release build
692677

693678
utils_mutex_unlock(&provider->hTracker->splitMergeMutex);
694679

695680
LOG_DEBUG("merged memory regions (level=%i): lowPtr=%p (child=%zu), "
696681
"highPtr=%p (child=%zu), totalSize=%zu",
697-
lowLevel, lowPtr, lno, highPtr, hno, totalSize);
682+
lowLevel, lowPtr, lowValue->n_children, highPtr,
683+
highValue->n_children, totalSize);
684+
685+
umf_ba_free(provider->hTracker->alloc_info_allocator, highValue);
698686

699687
return UMF_RESULT_SUCCESS;
700688

701-
err_assert:
689+
err_fatal:
702690
LOG_FATAL("failed to merge memory regions: lowPtr=%p (level=%i), "
703691
"highPtr=%p (level=%i), totalSize=%zu",
704692
lowPtr, lowLevel, highPtr, highLevel, totalSize);
705-
assert(0);
706693

707-
not_merged:
694+
cannot_merge:
708695
utils_mutex_unlock(&provider->hTracker->splitMergeMutex);
709696

710697
err_lock:
711-
umf_ba_free(provider->hTracker->alloc_info_allocator, mergedValue);
712-
713698
LOG_ERR("failed to merge memory regions: lowPtr=%p (level=%i), highPtr=%p "
714699
"(level=%i), totalSize=%zu",
715700
lowPtr, lowLevel, highPtr, highLevel, totalSize);

0 commit comments

Comments
 (0)