summaryrefslogtreecommitdiff
path: root/include/mimalloc-internal.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/mimalloc-internal.h')
-rw-r--r--include/mimalloc-internal.h45
1 files changed, 32 insertions, 13 deletions
diff --git a/include/mimalloc-internal.h b/include/mimalloc-internal.h
index 4c47af9..7bffb6a 100644
--- a/include/mimalloc-internal.h
+++ b/include/mimalloc-internal.h
@@ -20,6 +20,18 @@ terms of the MIT license. A copy of the license can be found in the file
#define mi_trace_message(...)
#endif
+#if defined(_MSC_VER)
+#define mi_decl_noinline __declspec(noinline)
+#define mi_attr_noreturn
+#elif defined(__GNUC__) || defined(__clang__)
+#define mi_decl_noinline __attribute__((noinline))
+#define mi_attr_noreturn __attribute__((noreturn))
+#else
+#define mi_decl_noinline
+#define mi_attr_noreturn
+#endif
+
+
// "options.c"
void _mi_fputs(mi_output_fun* out, const char* prefix, const char* message);
void _mi_fprintf(mi_output_fun* out, const char* fmt, ...);
@@ -28,6 +40,7 @@ void _mi_warning_message(const char* fmt, ...);
void _mi_verbose_message(const char* fmt, ...);
void _mi_trace_message(const char* fmt, ...);
void _mi_options_init(void);
+void _mi_fatal_error(const char* fmt, ...) mi_attr_noreturn;
// "init.c"
extern mi_stats_t _mi_stats_main;
@@ -124,13 +137,6 @@ bool _mi_page_is_valid(mi_page_t* page);
#define __has_builtin(x) 0
#endif
-#if defined(_MSC_VER)
-#define mi_decl_noinline __declspec(noinline)
-#elif defined(__GNUC__) || defined(__clang__)
-#define mi_decl_noinline __attribute__((noinline))
-#else
-#define mi_decl_noinline
-#endif
/* -----------------------------------------------------------
@@ -365,8 +371,12 @@ static inline void mi_page_set_has_aligned(mi_page_t* page, bool has_aligned) {
// Encoding/Decoding the free list next pointers
// -------------------------------------------------------------------
-static inline mi_block_t* mi_block_nextx( uintptr_t cookie, mi_block_t* block ) {
- #if MI_SECURE
+static inline bool mi_is_in_same_segment(const void* p, const void* q) {
+ return (_mi_ptr_segment(p) == _mi_ptr_segment(q));
+}
+
+static inline mi_block_t* mi_block_nextx( uintptr_t cookie, const mi_block_t* block ) {
+ #if MI_SECURE
return (mi_block_t*)(block->next ^ cookie);
#else
UNUSED(cookie);
@@ -374,7 +384,7 @@ static inline mi_block_t* mi_block_nextx( uintptr_t cookie, mi_block_t* block )
#endif
}
-static inline void mi_block_set_nextx(uintptr_t cookie, mi_block_t* block, mi_block_t* next) {
+static inline void mi_block_set_nextx(uintptr_t cookie, mi_block_t* block, const mi_block_t* next) {
#if MI_SECURE
block->next = (mi_encoded_t)next ^ cookie;
#else
@@ -383,16 +393,25 @@ static inline void mi_block_set_nextx(uintptr_t cookie, mi_block_t* block, mi_bl
#endif
}
-static inline mi_block_t* mi_block_next(mi_page_t* page, mi_block_t* block) {
+static inline mi_block_t* mi_block_next(const mi_page_t* page, const mi_block_t* block) {
#if MI_SECURE
- return mi_block_nextx(page->cookie,block);
+ mi_block_t* next = mi_block_nextx(page->cookie,block);
+ #if MI_SECURE >= 4
+ // check if next is at least in our segment range
+ // TODO: it is better to check if it is actually inside our page but that is more expensive
+ // to calculate. Perhaps with a relative free list this becomes feasible?
+ if (next!=NULL && !mi_is_in_same_segment(block, next)) {
+ _mi_fatal_error("corrupted free list entry at %p: %zx\n", block, (uintptr_t)next);
+ }
+ #endif
+ return next;
#else
UNUSED(page);
return mi_block_nextx(0, block);
#endif
}
-static inline void mi_block_set_next(mi_page_t* page, mi_block_t* block, mi_block_t* next) {
+static inline void mi_block_set_next(const mi_page_t* page, mi_block_t* block, const mi_block_t* next) {
#if MI_SECURE
mi_block_set_nextx(page->cookie,block,next);
#else