Skip to content

Commit 4883040

Browse files
committed
merge from dev; check all os_commit calls
2 parents 550b628 + a0072ba commit 4883040

File tree

5 files changed

+64
-29
lines changed

5 files changed

+64
-29
lines changed

include/mimalloc/internal.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -145,13 +145,13 @@ bool _mi_os_has_virtual_reserve(void);
145145
size_t _mi_os_virtual_address_bits(void);
146146

147147
bool _mi_os_reset(void* addr, size_t size);
148-
bool _mi_os_commit(void* p, size_t size, bool* is_zero);
149148
bool _mi_os_decommit(void* addr, size_t size);
150-
bool _mi_os_protect(void* addr, size_t size);
149+
mi_decl_nodiscard bool _mi_os_commit(void* p, size_t size, bool* is_zero);
150+
mi_decl_nodiscard bool _mi_os_commit_ex(void* addr, size_t size, bool* is_zero, size_t stat_size);
151+
mi_decl_nodiscard bool _mi_os_protect(void* addr, size_t size);
151152
bool _mi_os_unprotect(void* addr, size_t size);
152153
bool _mi_os_purge(void* p, size_t size);
153154
bool _mi_os_purge_ex(void* p, size_t size, bool allow_reset, size_t stats_size, mi_commit_fun_t* commit_fun, void* commit_fun_arg);
154-
bool _mi_os_commit_ex(void* addr, size_t size, bool* is_zero, size_t stat_size);
155155

156156
size_t _mi_os_secure_guard_page_size(void);
157157
bool _mi_os_secure_guard_page_set_at(void* addr, mi_memid_t memid);
@@ -216,7 +216,7 @@ void _mi_deferred_free(mi_heap_t* heap, bool force);
216216

217217
void _mi_page_free_collect(mi_page_t* page, bool force);
218218
void _mi_page_free_collect_partly(mi_page_t* page, mi_block_t* head);
219-
void _mi_page_init(mi_heap_t* heap, mi_page_t* page);
219+
mi_decl_nodiscard bool _mi_page_init(mi_heap_t* heap, mi_page_t* page);
220220
bool _mi_page_queue_is_valid(mi_heap_t* heap, const mi_page_queue_t* pq);
221221

222222
size_t _mi_page_bin(const mi_page_t* page); // for stats

src/arena.c

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -711,6 +711,7 @@ static mi_page_t* mi_arenas_page_alloc_fresh(size_t slice_count, size_t block_si
711711
mi_assert_internal(mi_page_block_size(page) == block_size);
712712
mi_assert_internal(mi_page_is_abandoned(page));
713713
mi_assert_internal(mi_page_is_owned(page));
714+
714715
return page;
715716
}
716717

@@ -730,13 +731,15 @@ static mi_page_t* mi_arenas_page_regular_alloc(mi_heap_t* heap, size_t slice_cou
730731
const bool commit = (slice_count <= mi_slice_count_of_size(MI_PAGE_MIN_COMMIT_SIZE) || // always commit small pages
731732
(commit_on_demand == 2 && _mi_os_has_overcommit()) || (commit_on_demand == 0));
732733
page = mi_arenas_page_alloc_fresh(slice_count, block_size, 1, req_arena, heap->numa_node, commit, tld);
733-
if (page != NULL) {
734-
mi_assert_internal(page->memid.memkind != MI_MEM_ARENA || page->memid.mem.arena.slice_count == slice_count);
735-
_mi_page_init(heap, page);
736-
return page;
737-
}
734+
if (page == NULL) return NULL;
738735

739-
return NULL;
736+
mi_assert_internal(page->memid.memkind != MI_MEM_ARENA || page->memid.mem.arena.slice_count == slice_count);
737+
if (!_mi_page_init(heap, page)) {
738+
_mi_arenas_free( page, mi_page_full_size(page), page->memid);
739+
return NULL;
740+
}
741+
742+
return page;
740743
}
741744

742745
// Allocate a page containing one block (very large, or with large alignment)
@@ -755,7 +758,10 @@ static mi_page_t* mi_arenas_page_singleton_alloc(mi_heap_t* heap, size_t block_s
755758
if (page == NULL) return NULL;
756759

757760
mi_assert(page->reserved == 1);
758-
_mi_page_init(heap, page);
761+
if (!_mi_page_init(heap, page)) {
762+
_mi_arenas_free( page, mi_page_full_size(page), page->memid);
763+
return NULL;
764+
}
759765

760766
return page;
761767
}
@@ -1204,11 +1210,16 @@ static bool mi_manage_os_memory_ex2(mi_subproc_t* subproc, void* start, size_t s
12041210
size_t commit_size = mi_size_of_slices(info_slices);
12051211
// leave a guard OS page decommitted at the end?
12061212
if (!memid.is_pinned) { commit_size -= _mi_os_secure_guard_page_size(); }
1213+
bool ok = false;
12071214
if (commit_fun != NULL) {
1208-
(*commit_fun)(true /* commit */, arena, commit_size, NULL, commit_fun_arg);
1215+
ok = (*commit_fun)(true /* commit */, arena, commit_size, NULL, commit_fun_arg);
12091216
}
12101217
else {
1211-
_mi_os_commit(arena, commit_size, NULL);
1218+
ok = _mi_os_commit(arena, commit_size, NULL);
1219+
}
1220+
if (!ok) {
1221+
_mi_warning_message("unable to commit meta-data for OS memory");
1222+
return false;
12121223
}
12131224
}
12141225
else if (!memid.is_pinned) {

src/os.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ static void mi_os_prim_free(void* addr, size_t size, size_t commit_size) {
186186
void _mi_os_free_ex(void* addr, size_t size, bool still_committed, mi_memid_t memid) {
187187
if (mi_memkind_is_os(memid.memkind)) {
188188
size_t csize = memid.mem.os.size;
189-
if (csize==0) { _mi_os_good_alloc_size(size); }
189+
if (csize==0) { csize = _mi_os_good_alloc_size(size); }
190190
size_t commit_size = (still_committed ? csize : 0);
191191
void* base = addr;
192192
// different base? (due to alignment)
@@ -309,7 +309,10 @@ static void* mi_os_prim_alloc_aligned(size_t size, size_t alignment, bool commit
309309

310310
// explicitly commit only the aligned part
311311
if (commit) {
312-
_mi_os_commit(p, size, NULL);
312+
if (!_mi_os_commit(p, size, NULL)) {
313+
mi_os_prim_free(*base, over_size, 0);
314+
return NULL;
315+
}
313316
}
314317
}
315318
else { // mmap can free inside an allocation

src/page-map.c

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ terms of the MIT license. A copy of the license can be found in the file
99
#include "mimalloc/internal.h"
1010
#include "bitmap.h"
1111

12+
static void mi_page_map_cannot_commit(void) {
13+
_mi_error_message(EFAULT,"unable to commit memory for the page address map\n");
14+
}
15+
1216
#if MI_PAGE_MAP_FLAT
1317

1418
// The page-map contains a byte for each 64kb slice in the address space.
@@ -57,7 +61,10 @@ bool _mi_page_map_init(void) {
5761
}
5862
if (bitmap_size > 0) {
5963
mi_page_map_commit = (mi_bitmap_t*)base;
60-
_mi_os_commit(mi_page_map_commit, bitmap_size, NULL);
64+
if (!_mi_os_commit(mi_page_map_commit, bitmap_size, NULL)) {
65+
mi_page_map_cannot_commit();
66+
return false;
67+
}
6168
mi_bitmap_init(mi_page_map_commit, commit_bits, true);
6269
}
6370
_mi_page_map = base + bitmap_size;
@@ -95,7 +102,7 @@ static void mi_page_map_ensure_committed(size_t idx, size_t slice_count) {
95102
bool is_zero;
96103
uint8_t* const start = _mi_page_map + (i * MI_PAGE_MAP_ENTRIES_PER_COMMIT_BIT);
97104
const size_t size = MI_PAGE_MAP_ENTRIES_PER_COMMIT_BIT;
98-
_mi_os_commit(start, size, &is_zero);
105+
if (!_mi_os_commit(start, size, &is_zero)) return;
99106
if (!is_zero && !mi_page_map_memid.initially_zero) { _mi_memzero(start, size); }
100107
mi_bitmap_set(mi_page_map_commit, i);
101108
}
@@ -221,11 +228,17 @@ bool _mi_page_map_init(void) {
221228

222229
// note: for the NULL range we only commit one OS page (in the map and sub)
223230
if (!mi_page_map_memid.initially_committed) {
224-
_mi_os_commit(&_mi_page_map[0], os_page_size, NULL); // commit first part of the map
231+
if (!_mi_os_commit(&_mi_page_map[0], os_page_size, NULL)) { // commit first part of the map
232+
mi_page_map_cannot_commit();
233+
return false;
234+
}
225235
}
226236
_mi_page_map[0] = (mi_page_t**)((uint8_t*)_mi_page_map + page_map_size); // we reserved a submap part at the end already
227237
if (!mi_page_map_memid.initially_committed) {
228-
_mi_os_commit(_mi_page_map[0], submap_size, NULL); // commit full submap (issue #1087)
238+
if (!_mi_os_commit(_mi_page_map[0], submap_size, NULL)) { // commit full submap (issue #1087)
239+
mi_page_map_cannot_commit();
240+
return false;
241+
}
229242
}
230243
if (!mi_page_map_memid.initially_zero) { // initialize low addresses with NULL
231244
_mi_memzero_aligned(_mi_page_map[0], submap_size);
@@ -272,7 +285,9 @@ static mi_page_t** mi_page_map_ensure_committed(size_t idx) {
272285
size_t bit_idx;
273286
if mi_unlikely(!mi_page_map_is_committed(idx, &bit_idx)) {
274287
uint8_t* start = (uint8_t*)&_mi_page_map[bit_idx * MI_PAGE_MAP_ENTRIES_PER_CBIT];
275-
_mi_os_commit(start, MI_PAGE_MAP_ENTRIES_PER_CBIT * sizeof(mi_page_t**), NULL);
288+
if (!_mi_os_commit(start, MI_PAGE_MAP_ENTRIES_PER_CBIT * sizeof(mi_page_t**), NULL)) {
289+
return NULL;
290+
}
276291
mi_atomic_or_acq_rel(&mi_page_map_commit, MI_ZU(1) << bit_idx);
277292
}
278293
return mi_atomic_load_ptr_acquire(mi_page_t*, &_mi_page_map[idx]); // _mi_page_map_at(idx);

src/page.c

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ static inline mi_block_t* mi_page_block_at(const mi_page_t* page, void* page_sta
3737
}
3838

3939
//static void mi_page_init(mi_heap_t* heap, mi_page_t* page, size_t size, mi_tld_t* tld);
40-
static void mi_page_extend_free(mi_heap_t* heap, mi_page_t* page);
40+
static bool mi_page_extend_free(mi_heap_t* heap, mi_page_t* page);
4141

4242
#if (MI_DEBUG>=3)
4343
static size_t mi_page_list_count(mi_page_t* page, mi_block_t* head) {
@@ -605,14 +605,14 @@ static mi_decl_noinline void mi_page_free_list_extend( mi_page_t* const page, co
605605
// Note: we also experimented with "bump" allocation on the first
606606
// allocations but this did not speed up any benchmark (due to an
607607
// extra test in malloc? or cache effects?)
608-
static void mi_page_extend_free(mi_heap_t* heap, mi_page_t* page) {
608+
static bool mi_page_extend_free(mi_heap_t* heap, mi_page_t* page) {
609609
mi_assert_expensive(mi_page_is_valid_init(page));
610610
#if (MI_SECURE<3)
611611
mi_assert(page->free == NULL);
612612
mi_assert(page->local_free == NULL);
613-
if (page->free != NULL) return;
613+
if (page->free != NULL) return true;
614614
#endif
615-
if (page->capacity >= page->reserved) return;
615+
if (page->capacity >= page->reserved) return true;
616616

617617
size_t page_size;
618618
//uint8_t* page_start =
@@ -645,7 +645,9 @@ static void mi_page_extend_free(mi_heap_t* heap, mi_page_t* page) {
645645
const size_t needed_commit = _mi_align_up( mi_page_slice_offset_of(page, needed_size), MI_PAGE_MIN_COMMIT_SIZE );
646646
if (needed_commit > page->slice_committed) {
647647
mi_assert_internal(((needed_commit - page->slice_committed) % _mi_os_page_size()) == 0);
648-
_mi_os_commit(mi_page_slice_start(page) + page->slice_committed, needed_commit - page->slice_committed, NULL);
648+
if (!_mi_os_commit(mi_page_slice_start(page) + page->slice_committed, needed_commit - page->slice_committed, NULL)) {
649+
return false;
650+
}
649651
page->slice_committed = needed_commit;
650652
}
651653
}
@@ -663,10 +665,11 @@ static void mi_page_extend_free(mi_heap_t* heap, mi_page_t* page) {
663665
mi_heap_stat_increase(heap, page_committed, extend * bsize);
664666
#endif
665667
mi_assert_expensive(mi_page_is_valid_init(page));
668+
return true;
666669
}
667670

668671
// Initialize a fresh page (that is already partially initialized)
669-
void _mi_page_init(mi_heap_t* heap, mi_page_t* page) {
672+
mi_decl_nodiscard bool _mi_page_init(mi_heap_t* heap, mi_page_t* page) {
670673
mi_assert(page != NULL);
671674
mi_page_set_heap(page, heap);
672675

@@ -703,8 +706,9 @@ void _mi_page_init(mi_heap_t* heap, mi_page_t* page) {
703706
mi_assert_expensive(mi_page_is_valid_init(page));
704707

705708
// initialize an initial free list
706-
mi_page_extend_free(heap,page);
709+
if (!mi_page_extend_free(heap,page)) return false;
707710
mi_assert(mi_page_immediate_available(page));
711+
return true;
708712
}
709713

710714

@@ -794,9 +798,11 @@ static mi_decl_noinline mi_page_t* mi_page_queue_find_free_ex(mi_heap_t* heap, m
794798
if (page != NULL) {
795799
if (!mi_page_immediate_available(page)) {
796800
mi_assert_internal(mi_page_is_expandable(page));
797-
mi_page_extend_free(heap, page);
801+
if (!mi_page_extend_free(heap, page)) {
802+
page = NULL; // failed to extend
803+
}
798804
}
799-
mi_assert_internal(mi_page_immediate_available(page));
805+
mi_assert_internal(page == NULL || mi_page_immediate_available(page));
800806
}
801807

802808
if (page == NULL) {

0 commit comments

Comments
 (0)