MCPcopy Create free account
hub / github.com/CppCXY/EmmyLuaCodeStyle / mi_os_mem_alloc_aligned

Function mi_os_mem_alloc_aligned

3rd/mimalloc-2.0.9/src/os.c:748–800  ·  view source on GitHub ↗

Primitive aligned allocation from the OS. This function guarantees the allocated memory is aligned.

Source from the content-addressed store, hash-verified

746// Primitive aligned allocation from the OS.
747// This function guarantees the allocated memory is aligned.
748static void* mi_os_mem_alloc_aligned(size_t size, size_t alignment, bool commit, bool allow_large, bool* is_large, mi_stats_t* stats) {
749 mi_assert_internal(alignment >= _mi_os_page_size() && ((alignment & (alignment - 1)) == 0));
750 mi_assert_internal(size > 0 && (size % _mi_os_page_size()) == 0);
751 mi_assert_internal(is_large != NULL);
752 if (!commit) allow_large = false;
753 if (!(alignment >= _mi_os_page_size() && ((alignment & (alignment - 1)) == 0))) return NULL;
754 size = _mi_align_up(size, _mi_os_page_size());
755
756 // try first with a hint (this will be aligned directly on Win 10+ or BSD)
757 void* p = mi_os_mem_alloc(size, alignment, commit, allow_large, is_large, stats);
758 if (p == NULL) return NULL;
759
760 // if not aligned, free it, overallocate, and unmap around it
761 if (((uintptr_t)p % alignment != 0)) {
762 mi_os_mem_free(p, size, commit, stats);
763 _mi_warning_message("unable to allocate aligned OS memory directly, fall back to over-allocation (%zu bytes, address: %p, alignment: %zu, commit: %d)\n", size, p, alignment, commit);
764 if (size >= (SIZE_MAX - alignment)) return NULL; // overflow
765 const size_t over_size = size + alignment;
766
767#if _WIN32
768 // over-allocate uncommitted (virtual) memory
769 p = mi_os_mem_alloc(over_size, 0 /*alignment*/, false /* commit? */, false /* allow_large */, is_large, stats);
770 if (p == NULL) return NULL;
771
772 // set p to the aligned part in the full region
773 // note: this is dangerous on Windows as VirtualFree needs the actual region pointer
774 // but in mi_os_mem_free we handle this (hopefully exceptional) situation.
775 p = mi_align_up_ptr(p, alignment);
776
777 // explicitly commit only the aligned part
778 if (commit) {
779 _mi_os_commit(p, size, NULL, stats);
780 }
781#else
782 // overallocate...
783 p = mi_os_mem_alloc(over_size, 1, commit, false, is_large, stats);
784 if (p == NULL) return NULL;
785 // and selectively unmap parts around the over-allocated area. (noop on sbrk)
786 void* aligned_p = mi_align_up_ptr(p, alignment);
787 size_t pre_size = (uint8_t*)aligned_p - (uint8_t*)p;
788 size_t mid_size = _mi_align_up(size, _mi_os_page_size());
789 size_t post_size = over_size - pre_size - mid_size;
790 mi_assert_internal(pre_size < over_size && post_size < over_size && mid_size >= size);
791 if (pre_size > 0) mi_os_mem_free(p, pre_size, commit, stats);
792 if (post_size > 0) mi_os_mem_free((uint8_t*)aligned_p + mid_size, post_size, commit, stats);
793 // we can return the aligned pointer on `mmap` (and sbrk) systems
794 p = aligned_p;
795#endif
796 }
797
798 mi_assert_internal(p == NULL || (p != NULL && ((uintptr_t)p % alignment) == 0));
799 return p;
800}
801
802
803/* -----------------------------------------------------------

Callers 1

_mi_os_alloc_alignedFunction · 0.85

Calls 7

_mi_os_page_sizeFunction · 0.85
_mi_align_upFunction · 0.85
mi_os_mem_allocFunction · 0.85
mi_os_mem_freeFunction · 0.85
_mi_warning_messageFunction · 0.85
mi_align_up_ptrFunction · 0.85
_mi_os_commitFunction · 0.85

Tested by

no test coverage detected