Large and huge page allocation. Huge pages are allocated directly without being in a queue. Because huge pages contain just one block, and the segment contains just that page, we always treat them as abandoned and any thread that frees the block can free the whole page and segment directly. Huge pages are also use if the requested alignment is very large (> MI_ALIGNMENT_MAX).
| 814 | // that frees the block can free the whole page and segment directly. |
| 815 | // Huge pages are also use if the requested alignment is very large (> MI_ALIGNMENT_MAX). |
| 816 | static mi_page_t* mi_large_huge_page_alloc(mi_heap_t* heap, size_t size, size_t page_alignment) { |
| 817 | size_t block_size = _mi_os_good_alloc_size(size); |
| 818 | mi_assert_internal(mi_bin(block_size) == MI_BIN_HUGE || page_alignment > 0); |
| 819 | bool is_huge = (block_size > MI_LARGE_OBJ_SIZE_MAX || page_alignment > 0); |
| 820 | #if MI_HUGE_PAGE_ABANDON |
| 821 | mi_page_queue_t* pq = (is_huge ? NULL : mi_page_queue(heap, block_size)); |
| 822 | #else |
| 823 | mi_page_queue_t* pq = mi_page_queue(heap, is_huge ? MI_HUGE_BLOCK_SIZE : block_size); // not block_size as that can be low if the page_alignment > 0 |
| 824 | mi_assert_internal(!is_huge || mi_page_queue_is_huge(pq)); |
| 825 | #endif |
| 826 | mi_page_t* page = mi_page_fresh_alloc(heap, pq, block_size, page_alignment); |
| 827 | if (page != NULL) { |
| 828 | mi_assert_internal(mi_page_immediate_available(page)); |
| 829 | |
| 830 | if (is_huge) { |
| 831 | mi_assert_internal(_mi_page_segment(page)->kind == MI_SEGMENT_HUGE); |
| 832 | mi_assert_internal(_mi_page_segment(page)->used==1); |
| 833 | #if MI_HUGE_PAGE_ABANDON |
| 834 | mi_assert_internal(_mi_page_segment(page)->thread_id==0); // abandoned, not in the huge queue |
| 835 | mi_page_set_heap(page, NULL); |
| 836 | #endif |
| 837 | } |
| 838 | else { |
| 839 | mi_assert_internal(_mi_page_segment(page)->kind != MI_SEGMENT_HUGE); |
| 840 | } |
| 841 | |
| 842 | const size_t bsize = mi_page_usable_block_size(page); // note: not `mi_page_block_size` to account for padding |
| 843 | if (bsize <= MI_LARGE_OBJ_SIZE_MAX) { |
| 844 | mi_heap_stat_increase(heap, large, bsize); |
| 845 | mi_heap_stat_counter_increase(heap, large_count, 1); |
| 846 | } |
| 847 | else { |
| 848 | mi_heap_stat_increase(heap, huge, bsize); |
| 849 | mi_heap_stat_counter_increase(heap, huge_count, 1); |
| 850 | } |
| 851 | } |
| 852 | return page; |
| 853 | } |
| 854 | |
| 855 | |
| 856 | // Allocate a page |
no test coverage detected