mirror of
https://github.com/microsoft/mimalloc.git
synced 2025-07-12 22:24:58 +03:00
merge from dev
This commit is contained in:
commit
b0104ef4fd
6 changed files with 207 additions and 204 deletions
114
src/segment.c
114
src/segment.c
|
@ -396,7 +396,7 @@ static void mi_segment_os_free(mi_segment_t* segment, mi_segments_tld_t* tld) {
|
|||
const size_t csize = _mi_commit_mask_committed_size(&segment->commit_mask, size);
|
||||
|
||||
_mi_abandoned_await_readers(); // wait until safe to free
|
||||
_mi_arena_free(segment, mi_segment_size(segment), segment->mem_alignment, segment->mem_align_offset, segment->memid, csize, tld->stats);
|
||||
_mi_arena_free(segment, mi_segment_size(segment), csize, segment->memid, tld->stats);
|
||||
}
|
||||
|
||||
// called by threads that are terminating
|
||||
|
@ -797,14 +797,11 @@ static mi_page_t* mi_segments_page_find_and_allocate(size_t slice_count, mi_aren
|
|||
|
||||
static mi_segment_t* mi_segment_os_alloc( size_t required, size_t page_alignment, bool eager_delayed, mi_arena_id_t req_arena_id,
|
||||
size_t* psegment_slices, size_t* ppre_size, size_t* pinfo_slices,
|
||||
mi_commit_mask_t* pcommit_mask, mi_commit_mask_t* ppurge_mask,
|
||||
bool* is_zero, bool* pcommit, mi_segments_tld_t* tld, mi_os_tld_t* os_tld)
|
||||
bool commit, mi_segments_tld_t* tld, mi_os_tld_t* os_tld)
|
||||
|
||||
{
|
||||
MI_UNUSED(ppurge_mask);
|
||||
mi_memid_t memid;
|
||||
bool mem_large = (!eager_delayed && (MI_SECURE == 0)); // only allow large OS pages once we are no longer lazy
|
||||
bool is_pinned = false;
|
||||
bool allow_large = (!eager_delayed && (MI_SECURE == 0)); // only allow large OS pages once we are no longer lazy
|
||||
size_t align_offset = 0;
|
||||
size_t alignment = MI_SEGMENT_ALIGN;
|
||||
|
||||
|
@ -818,43 +815,41 @@ static mi_segment_t* mi_segment_os_alloc( size_t required, size_t page_alignment
|
|||
// recalculate due to potential guard pages
|
||||
*psegment_slices = mi_segment_calculate_slices(required + extra, ppre_size, pinfo_slices);
|
||||
}
|
||||
|
||||
const size_t segment_size = (*psegment_slices) * MI_SEGMENT_SLICE_SIZE;
|
||||
mi_segment_t* segment = NULL;
|
||||
|
||||
// get from OS
|
||||
if (segment==NULL) {
|
||||
segment = (mi_segment_t*)_mi_arena_alloc_aligned(segment_size, alignment, align_offset, pcommit, &mem_large, &is_pinned, is_zero, req_arena_id, &memid, os_tld);
|
||||
if (segment == NULL) return NULL; // failed to allocate
|
||||
if (*pcommit) {
|
||||
mi_commit_mask_create_full(pcommit_mask);
|
||||
}
|
||||
else {
|
||||
mi_commit_mask_create_empty(pcommit_mask);
|
||||
}
|
||||
}
|
||||
mi_segment_t* segment = (mi_segment_t*)_mi_arena_alloc_aligned(segment_size, alignment, align_offset, commit, allow_large, req_arena_id, &memid, os_tld);
|
||||
if (segment == NULL) {
|
||||
return NULL; // failed to allocate
|
||||
}
|
||||
|
||||
// ensure metadata part of the segment is committed
|
||||
mi_commit_mask_t commit_mask;
|
||||
if (memid.was_committed) {
|
||||
mi_commit_mask_create_full(&commit_mask);
|
||||
}
|
||||
else {
|
||||
// at least commit the info slices
|
||||
const size_t commit_needed = _mi_divide_up((*pinfo_slices)*MI_SEGMENT_SLICE_SIZE, MI_COMMIT_SIZE);
|
||||
mi_assert_internal(commit_needed>0);
|
||||
mi_commit_mask_create(0, commit_needed, &commit_mask);
|
||||
mi_assert_internal(commit_needed*MI_COMMIT_SIZE >= (*pinfo_slices)*MI_SEGMENT_SLICE_SIZE);
|
||||
if (!_mi_os_commit(segment, commit_needed*MI_COMMIT_SIZE, NULL, tld->stats)) {
|
||||
_mi_arena_free(segment,segment_size,0,memid,tld->stats);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
mi_assert_internal(segment != NULL && (uintptr_t)segment % MI_SEGMENT_SIZE == 0);
|
||||
|
||||
const size_t commit_needed = _mi_divide_up((*pinfo_slices)*MI_SEGMENT_SLICE_SIZE, MI_COMMIT_SIZE);
|
||||
mi_assert_internal(commit_needed>0);
|
||||
mi_commit_mask_t commit_needed_mask;
|
||||
mi_commit_mask_create(0, commit_needed, &commit_needed_mask);
|
||||
if (!mi_commit_mask_all_set(pcommit_mask, &commit_needed_mask)) {
|
||||
// at least commit the info slices
|
||||
mi_assert_internal(commit_needed*MI_COMMIT_SIZE >= (*pinfo_slices)*MI_SEGMENT_SLICE_SIZE);
|
||||
bool ok = _mi_os_commit(segment, commit_needed*MI_COMMIT_SIZE, is_zero, tld->stats);
|
||||
if (!ok) return NULL; // failed to commit
|
||||
mi_commit_mask_set(pcommit_mask, &commit_needed_mask);
|
||||
}
|
||||
else if (*is_zero) {
|
||||
// track zero initialization for valgrind
|
||||
mi_track_mem_defined(segment, commit_needed * MI_COMMIT_SIZE);
|
||||
}
|
||||
mi_track_mem_undefined(segment, (*pinfo_slices) * MI_SEGMENT_SLICE_SIZE); // todo: should not be necessary?
|
||||
segment->memid = memid;
|
||||
segment->mem_is_pinned = is_pinned;
|
||||
segment->mem_is_large = mem_large;
|
||||
segment->mem_is_committed = mi_commit_mask_is_full(pcommit_mask);
|
||||
segment->mem_alignment = alignment;
|
||||
segment->mem_align_offset = align_offset;
|
||||
segment->allow_decommit = !memid.is_pinned && !memid.is_large;
|
||||
segment->allow_purge = segment->allow_decommit && mi_option_is_enabled(mi_option_allow_purge);
|
||||
segment->segment_size = segment_size;
|
||||
segment->commit_mask = commit_mask;
|
||||
segment->purge_expire = 0;
|
||||
mi_commit_mask_create_empty(&segment->purge_mask);
|
||||
mi_atomic_store_ptr_release(mi_segment_t, &segment->abandoned_next, NULL); // tsan
|
||||
|
||||
mi_segments_track_size((long)(segment_size), tld);
|
||||
_mi_segment_map_allocated_at(segment);
|
||||
return segment;
|
||||
|
@ -877,50 +872,21 @@ static mi_segment_t* mi_segment_alloc(size_t required, size_t page_alignment, mi
|
|||
tld->count < (size_t)mi_option_get(mi_option_eager_commit_delay));
|
||||
const bool eager = !eager_delay && mi_option_is_enabled(mi_option_eager_commit);
|
||||
bool commit = eager || (required > 0);
|
||||
bool is_zero = false;
|
||||
|
||||
mi_commit_mask_t commit_mask;
|
||||
mi_commit_mask_t purge_mask;
|
||||
mi_commit_mask_create_empty(&commit_mask);
|
||||
mi_commit_mask_create_empty(&purge_mask);
|
||||
|
||||
|
||||
// Allocate the segment from the OS
|
||||
mi_segment_t* segment = mi_segment_os_alloc(required, page_alignment, eager_delay, req_arena_id,
|
||||
&segment_slices, &pre_size, &info_slices, &commit_mask, &purge_mask,
|
||||
&is_zero, &commit, tld, os_tld);
|
||||
&segment_slices, &pre_size, &info_slices, commit, tld, os_tld);
|
||||
if (segment == NULL) return NULL;
|
||||
|
||||
// zero the segment info? -- not always needed as it may be zero initialized from the OS
|
||||
mi_atomic_store_ptr_release(mi_segment_t, &segment->abandoned_next, NULL); // tsan
|
||||
{
|
||||
if (!segment->memid.was_zero) {
|
||||
ptrdiff_t ofs = offsetof(mi_segment_t, next);
|
||||
size_t prefix = offsetof(mi_segment_t, slices) - ofs;
|
||||
size_t zsize = prefix + (sizeof(mi_slice_t) * (segment_slices + 1)); // one more
|
||||
if (!is_zero) {
|
||||
memset((uint8_t*)segment + ofs, 0, zsize);
|
||||
}
|
||||
_mi_memzero((uint8_t*)segment + ofs, zsize);
|
||||
}
|
||||
|
||||
segment->commit_mask = commit_mask; // on lazy commit, the initial part is always committed
|
||||
segment->allow_decommit = !segment->mem_is_pinned && !segment->mem_is_large;
|
||||
segment->allow_purge = segment->allow_decommit && mi_option_is_enabled(mi_option_allow_purge);
|
||||
if (segment->allow_purge) {
|
||||
segment->purge_expire = 0; // don't decommit just committed memory // _mi_clock_now() + mi_option_get(mi_option_purge_delay);
|
||||
segment->purge_mask = purge_mask;
|
||||
mi_assert_internal(mi_commit_mask_all_set(&segment->commit_mask, &segment->purge_mask));
|
||||
#if MI_DEBUG>2
|
||||
const size_t commit_needed = _mi_divide_up(info_slices*MI_SEGMENT_SLICE_SIZE, MI_COMMIT_SIZE);
|
||||
mi_commit_mask_t commit_needed_mask;
|
||||
mi_commit_mask_create(0, commit_needed, &commit_needed_mask);
|
||||
mi_assert_internal(!mi_commit_mask_any_set(&segment->purge_mask, &commit_needed_mask));
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
segment->purge_expire = 0;
|
||||
mi_commit_mask_create_empty( &segment->purge_mask );
|
||||
}
|
||||
|
||||
// initialize segment info
|
||||
// initialize the rest of the segment info
|
||||
const size_t slice_entries = (segment_slices > MI_SLICES_PER_SEGMENT ? MI_SLICES_PER_SEGMENT : segment_slices);
|
||||
segment->segment_slices = segment_slices;
|
||||
segment->segment_info_slices = info_slices;
|
||||
|
@ -929,7 +895,7 @@ static mi_segment_t* mi_segment_alloc(size_t required, size_t page_alignment, mi
|
|||
segment->slice_entries = slice_entries;
|
||||
segment->kind = (required == 0 ? MI_SEGMENT_NORMAL : MI_SEGMENT_HUGE);
|
||||
|
||||
// memset(segment->slices, 0, sizeof(mi_slice_t)*(info_slices+1));
|
||||
// _mi_memzero(segment->slices, sizeof(mi_slice_t)*(info_slices+1));
|
||||
_mi_stat_increase(&tld->stats->page_committed, mi_segment_info_size(segment));
|
||||
|
||||
// set up guard pages
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue