diff --git a/cores/esp8266/abi.cpp b/cores/esp8266/abi.cpp index 19feda4362..6ee4878e5d 100644 --- a/cores/esp8266/abi.cpp +++ b/cores/esp8266/abi.cpp @@ -35,6 +35,12 @@ extern "C" void __cxa_pure_virtual(void) __attribute__ ((__noreturn__)); extern "C" void __cxa_deleted_virtual(void) __attribute__ ((__noreturn__)); +#if DEV_DEBUG_ABI_CPP +extern "C" void _dbg_abi_print_pstr(const char* op, const char *function_name, const void* caller); +#define DEBUG_NEW_OP_PRINTF() _dbg_abi_print_pstr("new_op", __PRETTY_FUNCTION__, NULL) +#else +#define DEBUG_NEW_OP_PRINTF() do { } while (false) +#endif /* This is what I perceived to be the intent of the original code. @@ -79,10 +85,12 @@ static void* _heap_new_align(std::size_t size, std::size_t alignment, const void "alignment - specifies the alignment. Must be a valid alignment supported by the implementation." - I leave the validation to the umm_malloc library. See umm_memalign() for - details. Generally speaking, zero is handled as default and the default - is sizeof(umm_block), 8-bytes. - */ + I left the validation to the umm_malloc library. See umm_memalign() for + details. Generally speaking, zero is handled as default, and the default + is sizeof(umm_block), 8 bytes. Since the default is 8 bytes, the + umm_malloc library is less strict about checking alignments less than 8 + bytes. + */ void* p; @@ -101,18 +109,24 @@ static void* _heap_new_align(std::size_t size, std::size_t alignment, const void // new_opa void* operator new (std::size_t size, std::align_val_t alignment) { + DEBUG_NEW_OP_PRINTF(); + return _heap_new_align(size, std::size_t(alignment), __builtin_return_address(0)); } // new_opva void* operator new[] (std::size_t size, std::align_val_t alignment) { + DEBUG_NEW_OP_PRINTF(); + return _heap_new_align(size, std::size_t(alignment), __builtin_return_address(0)); } // new_opant void* operator new (std::size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept { + DEBUG_NEW_OP_PRINTF(); + __try { return _heap_new_align(size, std::size_t(alignment), __builtin_return_address(0)); } @@ -124,6 +138,8 @@ void* operator new (std::size_t size, std::align_val_t alignment, const std::not // new_opvant void* operator new[] (std::size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept { + DEBUG_NEW_OP_PRINTF(); + __try { return _heap_new_align(size, std::size_t(alignment), __builtin_return_address(0)); } @@ -135,18 +151,24 @@ void* operator new[] (std::size_t size, std::align_val_t alignment, const std::n // new_op void* operator new (std::size_t size) { + DEBUG_NEW_OP_PRINTF(); + return _heap_new_align(size, __STDCPP_DEFAULT_NEW_ALIGNMENT__, __builtin_return_address(0)); } // new_opv void* operator new[] (std::size_t size) { + DEBUG_NEW_OP_PRINTF(); + return _heap_new_align(size, __STDCPP_DEFAULT_NEW_ALIGNMENT__, __builtin_return_address(0)); } // new_opnt void* operator new (size_t size, const std::nothrow_t&) noexcept { + DEBUG_NEW_OP_PRINTF(); + __try { return _heap_new_align(size, __STDCPP_DEFAULT_NEW_ALIGNMENT__, __builtin_return_address(0)); } @@ -158,6 +180,8 @@ void* operator new (size_t size, const std::nothrow_t&) noexcept // new_opvnt void* operator new[] (size_t size, const std::nothrow_t&) noexcept { + DEBUG_NEW_OP_PRINTF(); + __try { return _heap_new_align(size, __STDCPP_DEFAULT_NEW_ALIGNMENT__, __builtin_return_address(0)); } @@ -188,16 +212,22 @@ static void* _heap_new(std::size_t size, const void* caller) void* operator new (std::size_t size) { + DEBUG_NEW_OP_PRINTF(); + return _heap_new(size, __builtin_return_address(0)); } void* operator new[] (std::size_t size) { + DEBUG_NEW_OP_PRINTF(); + return _heap_new(size, __builtin_return_address(0)); } void* operator new (size_t size, const std::nothrow_t&) noexcept { + DEBUG_NEW_OP_PRINTF(); + __try { return _heap_new(size, __builtin_return_address(0)); } @@ -208,6 +238,8 @@ void* operator new (size_t size, const std::nothrow_t&) noexcept void* operator new[] (size_t size, const std::nothrow_t&) noexcept { + DEBUG_NEW_OP_PRINTF(); + __try { return _heap_new(size, __builtin_return_address(0)); } @@ -230,41 +262,57 @@ void* operator new[] (size_t size, const std::nothrow_t&) noexcept void* operator new (size_t size, std::align_val_t alignment) { + DEBUG_NEW_OP_PRINTF(); + return _heap_abi_memalign(std::size_t(alignment), size, true, __builtin_return_address(0)); } void* operator new[] (size_t size, std::align_val_t alignment) { + DEBUG_NEW_OP_PRINTF(); + return _heap_abi_memalign(std::size_t(alignment), size, true, __builtin_return_address(0)); } void* operator new (size_t size, std::align_val_t alignment, const std::nothrow_t&) { + DEBUG_NEW_OP_PRINTF(); + return _heap_abi_memalign(std::size_t(alignment), size, false, __builtin_return_address(0)); } void* operator new[] (size_t size, std::align_val_t alignment, const std::nothrow_t&) { + DEBUG_NEW_OP_PRINTF(); + return _heap_abi_memalign(std::size_t(alignment), size, false, __builtin_return_address(0)); } void* operator new (size_t size) { + DEBUG_NEW_OP_PRINTF(); + return _heap_abi_memalign(__STDCPP_DEFAULT_NEW_ALIGNMENT__, size, true, __builtin_return_address(0)); } void* operator new[] (size_t size) { + DEBUG_NEW_OP_PRINTF(); + return _heap_abi_memalign(__STDCPP_DEFAULT_NEW_ALIGNMENT__, size, true, __builtin_return_address(0)); } void* operator new (size_t size, const std::nothrow_t&) { + DEBUG_NEW_OP_PRINTF(); + return _heap_abi_memalign(__STDCPP_DEFAULT_NEW_ALIGNMENT__, size, false, __builtin_return_address(0)); } void* operator new[] (size_t size, const std::nothrow_t&) { + DEBUG_NEW_OP_PRINTF(); + return _heap_abi_memalign(__STDCPP_DEFAULT_NEW_ALIGNMENT__, size, false, __builtin_return_address(0)); } @@ -275,32 +323,43 @@ void* operator new[] (size_t size, const std::nothrow_t&) void* operator new (size_t size) { + DEBUG_NEW_OP_PRINTF(); + return _heap_abi_malloc(size, true, __builtin_return_address(0)); } void* operator new[] (size_t size) { + DEBUG_NEW_OP_PRINTF(); + return _heap_abi_malloc(size, true, __builtin_return_address(0)); } void* operator new (size_t size, const std::nothrow_t&) { + DEBUG_NEW_OP_PRINTF(); + return _heap_abi_malloc(size, false, __builtin_return_address(0)); } void* operator new[] (size_t size, const std::nothrow_t&) { + DEBUG_NEW_OP_PRINTF(); + return _heap_abi_malloc(size, false, __builtin_return_address(0)); } #endif // #elif !defined(__cpp_exceptions) #if defined(UMM_ENABLE_MEMALIGN) #else /* - Using weaklink C++ Exception handlers in libstdc - The "new" operators that express alignment should work through libstdc via - memalign() in the umm_malloc library. + Using weaklink C++ Exception handlers in libstdc. The "new" operators that + express alignment should work through libstdc via memalign() in the umm_malloc + library. + + Note that libstdc will fail errors in alignment value early. Thus, the + UMM_STATS_FULL alignment error count will be zero. - This saves 20 bytes in the UMM_ENABLE_MEMALIGN=1 case and 32 bytes when - UMM_ENABLE_MEMALIGN=0. + This saves about 20 bytes in the UMM_ENABLE_MEMALIGN=1 case and 32 bytes when + UMM_ENABLE_MEMALIGN=0. */ //D << diff --git a/cores/esp8266/heap.cpp b/cores/esp8266/heap.cpp index dbd6a0aa95..19349caa3c 100644 --- a/cores/esp8266/heap.cpp +++ b/cores/esp8266/heap.cpp @@ -105,6 +105,11 @@ * UMM_POISON_CHECK_LITE should reveal most heap corruptions with lower * overhead. * + * DEV_DEBUG_ABI_CPP - Not normally needed. Its intended use is for module + * code maintenance. Use DEV_DEBUG_ABI_CPP when debugging the new/delete + * overload wrappers in abi.cpp and heap.cpp. In the test Sketch, add "extern + * bool abi_new_print;" and set abi_new_print=true/false around test function + * calls. Also, set '-DDEV_DEBUG_ABI_CPP=1' in Sketch.ino.globals.h. */ #include @@ -130,6 +135,12 @@ extern "C" void z2EapFree(void *ptr, const char* file, int line) __attribute__(( extern "C" { +#define DEBUG_HEAP_PRINTF ets_uart_printf + +inline bool withinISR(uint32_t ps) { + return ((ps & 0x0f) != 0); +} + /////////////////////////////////////////////////////////////////////////////// // Select from various heap function renames that facilitate inserting debug // wrappers, and tradditional names for the non-debug case. @@ -272,7 +283,6 @@ struct umm_last_fail_alloc { } _umm_last_fail_alloc; #endif - /////////////////////////////////////////////////////////////////////////////// // OOM - DEBUG_ESP_OOM extends monitoring for OOM to capture caller information // across various Heap entry points and their aliases. @@ -288,11 +298,6 @@ struct umm_last_fail_alloc { // of system_get_os_print(). Also, being in an IRQ may prevent the printing of // file names stored in PROGMEM. The PROGMEM address to the string is printed in // its place. -#define DEBUG_HEAP_PRINTF ets_uart_printf -inline bool withinISR(uint32_t ps) { - return ((ps & 0x0f) != 0); -} - static void IRAM_ATTR print_loc(bool inISR, size_t size, const char* file, int line, const void* caller) { if (system_get_os_print()) { DEBUG_HEAP_PRINTF(":oom %p(%d), File: ", caller, (int)size); @@ -369,7 +374,6 @@ static bool oom_check__log_last_fail_psc(void *ptr, size_t size, const void* cal // Monitor Heap APIs in flash for calls from ISRs // #if DEBUG_ESP_WITHINISR -#define DEBUG_HEAP_PRINTF ets_uart_printf static void isr_check__flash_not_safe(const void *caller) { if (ETS_INTR_WITHINISR()) { // Assumes, non-zero INTLEVEL means in ISR DEBUG_HEAP_PRINTF("\nIn-flash, Heap API call from %p with Interrupts Disabled.\n", caller); @@ -710,6 +714,35 @@ void system_show_malloc(void) /////////////////////////////////////////////////////////////////////////////// // heap allocator for "new" (ABI) - To support collecting OOM info, always defined +#if DEV_DEBUG_ABI_CPP +// In test Sketch, set abi_new_print=true/false around test function calls. +bool abi_new_print = false; + +// _dbg_abi_print_pstr is shared (private) between abi.cpp and heap.cpp +extern "C" void _dbg_abi_print_pstr(const char* op, const char *function_name, const void* caller) { + if (abi_new_print) { + uint32_t saved_ps = xt_rsil(DEFAULT_CRITICAL_SECTION_INTLEVEL); + DEBUG_HEAP_PRINTF("\nTrace %s: ", op); + if (caller) DEBUG_HEAP_PRINTF("caller(%p), ", caller); + if (withinISR(saved_ps)) { + DEBUG_HEAP_PRINTF("FN(%p)", function_name); + } else { + size_t sz = strlen_P(function_name); + char buf[sz + 1]; + strcpy_P(buf, function_name); + DEBUG_HEAP_PRINTF("'%s'", buf); + } + if (caller) DEBUG_HEAP_PRINTF("\n"); + xt_wsr_ps(saved_ps); + } +} +#define DEBUG_DELETE_OP_PRINTF() do { _dbg_abi_print_pstr("delete_op", __PRETTY_FUNCTION__, __builtin_return_address(0)); } while (false) + +#else +#define DEBUG_DELETE_OP_PRINTF(...) do { } while (false) +#endif + + #undef USE_HEAP_ABI_MEMALIGN #undef USE_HEAP_ABI_MALLOC @@ -734,6 +767,7 @@ void system_show_malloc(void) // "memalign" in the name will have the "alignment" argument before the "size". void* _heap_abi_memalign(size_t alignment, size_t size, bool unhandled, const void* const caller) { + DEBUG_HEAP_PRINTF(" _heap_abi_memalign(alignment(%u), size(%u), unhandled(%s), caller(%p))\n", alignment, size, (unhandled) ? "true" : "false", caller); // A comment from libstdc new_op.cc says: "malloc (0) is unpredictable; // avoid it." This behavoir is only done for the new operator. Our malloc is // happy to return a null pointer for a zero size allocation; however, the @@ -760,8 +794,10 @@ void* _heap_abi_memalign(size_t alignment, size_t size, bool unhandled, const vo return ret; } #elif USE_HEAP_ABI_MALLOC -void* _heap_abi_malloc(size_t size, bool unhandled, const void* caller) +void* _heap_abi_malloc(size_t size, bool unhandled, const void* const caller) { + DEBUG_HEAP_PRINTF(" _heap_abi_malloc(size(%u), unhandled(%s), caller(%p))\n", size, (unhandled) ? "true" : "false", caller); + /* malloc (0) is unpredictable; avoid it. */ if (__builtin_expect(0 == size, false)) { size = 1; @@ -879,14 +915,9 @@ uint32 IRAM_ATTR user_iram_memory_is_enabled(void) return CONFIG_IRAM_MEMORY; } #endif // #if (NONOSDK >= (0x30000)) -}; +}; // extern "C" { #if defined(ENABLE_THICK_DEBUG_WRAPPERS) -/////////////////////////////////////////////////////////////////////////////// -//C Note I just threw this together from files from the Internet -//C Is this the proper way to supply replacement "delete" operator? -// - /////////////////////////////////////////////////////////////////////////////// // Replacement C++ delete operator to capture callers address // @@ -905,37 +936,49 @@ void _heap_delete(void* ptr, const void* caller) noexcept // del_op void operator delete (void* ptr) noexcept { + DEBUG_DELETE_OP_PRINTF(); + _heap_delete(ptr, __builtin_return_address(0)); } // del_opnt void operator delete (void *ptr, const std::nothrow_t&) noexcept { - _heap_delete(ptr, __builtin_return_address(0)); + DEBUG_DELETE_OP_PRINTF(); + + _heap_delete(ptr, __builtin_return_address(0)); } // del_ops -void operator delete(void* ptr, std::size_t) noexcept +void operator delete (void* ptr, std::size_t) noexcept { - _heap_delete(ptr, __builtin_return_address(0)); + DEBUG_DELETE_OP_PRINTF(); + + _heap_delete(ptr, __builtin_return_address(0)); } // del_opv void operator delete[] (void *ptr) noexcept { - _heap_delete(ptr, __builtin_return_address(0)); + DEBUG_DELETE_OP_PRINTF(); + + _heap_delete(ptr, __builtin_return_address(0)); } // del_opvnt void operator delete[] (void *ptr, const std::nothrow_t&) noexcept { + DEBUG_DELETE_OP_PRINTF(); + _heap_delete(ptr, __builtin_return_address(0)); } // del_opvs void operator delete[] (void *ptr, std::size_t) noexcept { - _heap_delete(ptr, __builtin_return_address(0)); + DEBUG_DELETE_OP_PRINTF(); + + _heap_delete(ptr, __builtin_return_address(0)); } #if defined(__cpp_exceptions) @@ -943,37 +986,49 @@ void operator delete[] (void *ptr, std::size_t) noexcept // del_opa void operator delete (void* ptr, std::align_val_t) noexcept { + DEBUG_DELETE_OP_PRINTF(); + _heap_delete(ptr, __builtin_return_address(0)); } // del_opant void operator delete (void *ptr, std::align_val_t, const std::nothrow_t&) noexcept { + DEBUG_DELETE_OP_PRINTF(); + _heap_delete(ptr, __builtin_return_address(0)); } // del_opsa -void operator delete(void* ptr, std::size_t, std::align_val_t) noexcept +void operator delete (void* ptr, std::size_t, std::align_val_t) noexcept { - _heap_delete(ptr, __builtin_return_address(0)); + DEBUG_DELETE_OP_PRINTF(); + + _heap_delete(ptr, __builtin_return_address(0)); } // del_opva void operator delete[] (void *ptr, std::align_val_t) noexcept { + DEBUG_DELETE_OP_PRINTF(); + _heap_delete(ptr, __builtin_return_address(0)); } // del_opvant void operator delete[] (void *ptr, std::align_val_t, const std::nothrow_t&) noexcept { + DEBUG_DELETE_OP_PRINTF(); + _heap_delete(ptr, __builtin_return_address(0)); } // del_opvsa void operator delete[] (void *ptr, std::size_t, std::align_val_t) noexcept { - _heap_delete(ptr, __builtin_return_address(0)); + DEBUG_DELETE_OP_PRINTF(); + + _heap_delete(ptr, __builtin_return_address(0)); } #endif // #if defined(UMM_ENABLE_MEMALIGN) #endif // #if defined(__cpp_exceptions) diff --git a/cores/esp8266/umm_malloc/Notes.h b/cores/esp8266/umm_malloc/Notes.h index 5d076c4b67..9546f99f0a 100644 --- a/cores/esp8266/umm_malloc/Notes.h +++ b/cores/esp8266/umm_malloc/Notes.h @@ -352,5 +352,30 @@ Enhancement ideas: Move get_poisoned() within UMM_CRITICAL_* in umm_malloc() and umm_realloc(). + + September 14, 2024 + + Added conditional build support (UMM_ENABLE_MEMALIGN) for memalign() needed + for support of C++17. Expand umm_malloc_core() to support an alignment value. + I updated umm_malloc/umm_memalign to handle minimum alignment parameter + testing. For the umm_malloc library, ignore all the C++ noise on lower + alignment limits, etc. Language-restrictive requirements are left to the upper + levels. + + Referenced info: + + New new() - The C++17's Alignment Parameter for Operator new() + https://www.cppstories.com/2019/08/newnew-align/ + + Alignment + https://en.cppreference.com/w/cpp/language/object#Alignment + + std::max_align_t (in stddef.h) is a typedef struct with a collection of + types that would be used. "alignof(std::max_align_t)" yields the largest + alignment for the largest type. In some locations, I have seen references + to "sizeof(std::max_align_t)" I think those were typos. + + From https://github.com/m-labs/uclibc-lm32/blob/defb191aab7711218035a506ec5cd8bb87c05c55/libc/stdlib/malloc-standard/malloc.h#L39 + */ #endif diff --git a/cores/esp8266/umm_malloc/umm_local.c b/cores/esp8266/umm_malloc/umm_local.c index 023208d499..86f0d7120a 100644 --- a/cores/esp8266/umm_malloc/umm_local.c +++ b/cores/esp8266/umm_malloc/umm_local.c @@ -393,30 +393,4 @@ size_t umm_umul_sat(const size_t a, const size_t b) { return r; } - -#if 0 -// UMM_ENABLE_MEMALIGN -/* - * Places for helpful info - * - * New new() - The C++17's Alignment Parameter for Operator new() - * https://www.cppstories.com/2019/08/newnew-align/ - * - * Alignment - * https://en.cppreference.com/w/cpp/language/object#Alignment - * - * std::max_align_t (in stddef.h) is a typedef struct with a collection of - * types that would be used. "alignof(std::max_align_t)" yields the largest - * alignment for the largest type. Note, "sizeof(std::max_align_t)" does not - * make sense, it would be the size of the struct with all the elements used - * to find the prefered alignment. - * - * From https://github.com/m-labs/uclibc-lm32/blob/defb191aab7711218035a506ec5cd8bb87c05c55/libc/stdlib/malloc-standard/malloc.h#L39 - * - * Expand umm_malloc_core() to handle an alignment value. Ignore all the C++ - * noise as to lower alignment limits, etc. Just make it work. The caller of - * umm_malloc_core() will deal with the applying the language requirements. - */ -#endif - #endif // BUILD_UMM_MALLOC_C diff --git a/cores/esp8266/umm_malloc/umm_malloc.cpp b/cores/esp8266/umm_malloc/umm_malloc.cpp index d6a2130983..fb7763ecb1 100644 --- a/cores/esp8266/umm_malloc/umm_malloc.cpp +++ b/cores/esp8266/umm_malloc/umm_malloc.cpp @@ -524,7 +524,7 @@ static void ICACHE_MAYBE _umm_init_heap(umm_heap_context_t *_context) { void ICACHE_MAYBE umm_init_heap(size_t id, void *start_addr, size_t size, bool full_init) { /* Check for bad values and block duplicate init attempts. */ umm_heap_context_t *_context = umm_get_heap_by_id(id); - if (NULL == start_addr || NULL == _context || _context->heap) { + if (NULL == start_addr || NULL == _context || _context->heap || size < 20u) { return; } @@ -542,9 +542,10 @@ void ICACHE_MAYBE umm_init_heap(size_t id, void *start_addr, size_t size, bool f _context->heap = (umm_block *)((uintptr_t)start_addr); #else _context->heap = (umm_block *)((uintptr_t)start_addr + 4u); + size -= 4u; #endif _context->numblocks = (size / sizeof(umm_block)); - _context->heap_end = (void *)((uintptr_t)start_addr + _context->numblocks * sizeof(umm_block)); + _context->heap_end = (void *)((uintptr_t)_context->heap + _context->numblocks * sizeof(umm_block)); // An option for blocking the zeroing of extra heaps. This allows for // post-crash debugging after reboot. @@ -781,7 +782,6 @@ static void *umm_malloc_core(umm_heap_context_t *_context, size_t size) #if UMM_ENABLE_MEMALIGN if (__builtin_expect(alignment, 0u)) { - size_t alignMask = (alignment - 1u); uintptr_t aptr = (uintptr_t)&UMM_DATA(cf); @@ -815,24 +815,6 @@ static void *umm_malloc_core(umm_heap_context_t *_context, size_t size) cf = c; blocks -= frag; } - - #if DEV_DEBUG - #if defined(UMM_POISON_CHECK) || defined(UMM_POISON_CHECK_LITE) || defined(UMM_INTEGRITY_CHECK) - #if defined(UMM_INTEGRITY_CHECK) - umm_integrity_check(); - #endif - // extra verify computations - uintptr_t ptr = (uintptr_t)&UMM_DATA(cf); - #if defined(UMM_POISON_CHECK) || defined(UMM_POISON_CHECK_LITE) - ptr += sizeof(UMM_POISONED_BLOCK_LEN_TYPE) + UMM_POISON_SIZE_BEFORE; - ptr = (ptr + alignMask) & ~alignMask; - ptr -= sizeof(UMM_POISONED_BLOCK_LEN_TYPE) + UMM_POISON_SIZE_BEFORE; - #else - ptr = (ptr + alignMask) & ~alignMask; - #endif - if (aptr != ptr) panic(); - #endif - #endif // #if DEV_DEBUG } #endif diff --git a/cores/esp8266/umm_malloc/umm_malloc_cfgport.h b/cores/esp8266/umm_malloc/umm_malloc_cfgport.h index f2122a9087..44bacb7278 100644 --- a/cores/esp8266/umm_malloc/umm_malloc_cfgport.h +++ b/cores/esp8266/umm_malloc/umm_malloc_cfgport.h @@ -100,6 +100,52 @@ extern char _heap_start[]; #define UMM_HEAP_STACK_DEPTH 32 #endif +/* + * -DUMM_ENABLE_MEMALIGN=1 + * + * Include function memalign(size_t alignment, size_t size) in the build. + * Provides lowlevel memalign function to support C++17 addition of aligned + * "new" operators. + * + * Requires default 8-byte aligned data addresses. + * Build options "-DUMM_LEGACY_ALIGN_4BYTE=1" and "-DUMM_LEGACY_ALIGN_4BYTE=1" + * are mutually exclusive. + * + * Allocations from memalign() internally appear and are handled like any other + * UMM_MALLOC memory allocation. + * + * The existing free() function handles releasing memalign() memory allocations. + * + * Function realloc() should not be called for aligned memory allocations. + * It can break the alignment. At worst, the alignment falls back to + * sizeof(umm_block), 8 bytes. + * + * The UMM_POISON build option supports memalign(). + * + #define UMM_ENABLE_MEMALIGN 1 + */ + +// #define UMM_ENABLE_MEMALIGN 1 + +#if ((1 - UMM_ENABLE_MEMALIGN - 1) == 2) +#undef UMM_ENABLE_MEMALIGN +#define UMM_ENABLE_MEMALIGN 1 +#elif ((1 - UMM_ENABLE_MEMALIGN - 1) == 0) +#undef UMM_ENABLE_MEMALIGN +#endif + +//D +//D #ifndef __STRINGIFY +//D #define __STRINGIFY(a) #a +//D #endif +//D #define QUOTE(a) __STRINGIFY(a) +//D #pragma message("UMM_ENABLE_MEMALIGN: \"" QUOTE(UMM_ENABLE_MEMALIGN) "\"") +//D #ifdef UMM_ENABLE_MEMALIGN +//D #pragma message("UMM_ENABLE_MEMALIGN defined") +//D #else +//D #pragma message("UMM_ENABLE_MEMALIGN not defined") +//D #endif + /* * The NONOS SDK API requires function `umm_info()` for implementing * `system_show_malloc()`. Build option `-DUMM_INFO` enables this support. @@ -380,39 +426,6 @@ extern bool umm_poison_check(void); #endif -/* - * -DUMM_ENABLE_MEMALIGN=1 - * - * Include function memalign(size_t alignment, size_t size) in the build. - * Provides lowlevel memalign function to support C++17 addition of aligned - * "new" operators. - * - * Requires default 8-byte aligned data addresses. - * Build options "-DUMM_LEGACY_ALIGN_4BYTE=1" and "-DUMM_LEGACY_ALIGN_4BYTE=1" - * are mutually exclusive. - * - * Allocations from memalign() internally appear and are handled like any other - * UMM_MALLOC memory allocation. - * - * The existing free() function handles releasing memalign() memory allocations. - * - * Function realloc() should not be called for aligned memory allocations. - * It can break the alignment. At worst, the alignment falls back to - * sizeof(umm_block), 8 bytes. - * - * The UMM_POISON build option supports memalign(). - * - */ - -#if ((1 - UMM_ENABLE_MEMALIGN - 1) == 2) -#undef UMM_ENABLE_MEMALIGN -#define UMM_ENABLE_MEMALIGN 1 -#elif ((1 - UMM_ENABLE_MEMALIGN - 1) == 0) -#undef UMM_ENABLE_MEMALIGN -#endif - - - /* * -DUMM_LEGACY_ALIGN_4BYTE=1 *