| 774 | ----------------------------------------------------------- */ |
| 775 | |
| 776 | static mi_segment_t* mi_segment_os_alloc( size_t required, size_t page_alignment, bool eager_delay, mi_arena_id_t req_arena_id, |
| 777 | size_t* psegment_slices, size_t* ppre_size, size_t* pinfo_slices, |
| 778 | mi_commit_mask_t* pcommit_mask, mi_commit_mask_t* pdecommit_mask, |
| 779 | bool* is_zero, bool* pcommit, mi_segments_tld_t* tld, mi_os_tld_t* os_tld) |
| 780 | |
| 781 | { |
| 782 | // Allocate the segment from the OS |
| 783 | bool mem_large = (!eager_delay && (MI_SECURE==0)); // only allow large OS pages once we are no longer lazy |
| 784 | bool is_pinned = false; |
| 785 | size_t memid = 0; |
| 786 | size_t align_offset = 0; |
| 787 | size_t alignment = MI_SEGMENT_ALIGN; |
| 788 | |
| 789 | if (page_alignment > 0) { |
| 790 | // mi_assert_internal(huge_page != NULL); |
| 791 | mi_assert_internal(page_alignment >= MI_SEGMENT_ALIGN); |
| 792 | alignment = page_alignment; |
| 793 | const size_t info_size = (*pinfo_slices) * MI_SEGMENT_SLICE_SIZE; |
| 794 | align_offset = _mi_align_up( info_size, MI_SEGMENT_ALIGN ); |
| 795 | const size_t extra = align_offset - info_size; |
| 796 | // recalculate due to potential guard pages |
| 797 | *psegment_slices = mi_segment_calculate_slices(required + extra, ppre_size, pinfo_slices); |
| 798 | //segment_size += _mi_align_up(align_offset - info_size, MI_SEGMENT_SLICE_SIZE); |
| 799 | //segment_slices = segment_size / MI_SEGMENT_SLICE_SIZE; |
| 800 | } |
| 801 | const size_t segment_size = (*psegment_slices) * MI_SEGMENT_SLICE_SIZE; |
| 802 | mi_segment_t* segment = NULL; |
| 803 | |
| 804 | // get from cache? |
| 805 | if (page_alignment == 0) { |
| 806 | segment = (mi_segment_t*)_mi_segment_cache_pop(segment_size, pcommit_mask, pdecommit_mask, &mem_large, &is_pinned, is_zero, req_arena_id, &memid, os_tld); |
| 807 | } |
| 808 | |
| 809 | // get from OS |
| 810 | if (segment==NULL) { |
| 811 | 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); |
| 812 | if (segment == NULL) return NULL; // failed to allocate |
| 813 | if (*pcommit) { |
| 814 | mi_commit_mask_create_full(pcommit_mask); |
| 815 | } |
| 816 | else { |
| 817 | mi_commit_mask_create_empty(pcommit_mask); |
| 818 | } |
| 819 | } |
| 820 | mi_assert_internal(segment != NULL && (uintptr_t)segment % MI_SEGMENT_SIZE == 0); |
| 821 | |
| 822 | const size_t commit_needed = _mi_divide_up((*pinfo_slices)*MI_SEGMENT_SLICE_SIZE, MI_COMMIT_SIZE); |
| 823 | mi_assert_internal(commit_needed>0); |
| 824 | mi_commit_mask_t commit_needed_mask; |
| 825 | mi_commit_mask_create(0, commit_needed, &commit_needed_mask); |
| 826 | if (!mi_commit_mask_all_set(pcommit_mask, &commit_needed_mask)) { |
| 827 | // at least commit the info slices |
| 828 | mi_assert_internal(commit_needed*MI_COMMIT_SIZE >= (*pinfo_slices)*MI_SEGMENT_SLICE_SIZE); |
| 829 | bool ok = _mi_os_commit(segment, commit_needed*MI_COMMIT_SIZE, is_zero, tld->stats); |
| 830 | if (!ok) return NULL; // failed to commit |
| 831 | mi_commit_mask_set(pcommit_mask, &commit_needed_mask); |
| 832 | } |
| 833 | mi_track_mem_undefined(segment,commit_needed); |
no test coverage detected