diff --git a/include/zephyr/arch/posix/arch.h b/include/zephyr/arch/posix/arch.h index 83aceb1c14ba1f4..9a39740aa4ce7a6 100644 --- a/include/zephyr/arch/posix/arch.h +++ b/include/zephyr/arch/posix/arch.h @@ -17,6 +17,8 @@ #ifndef ZEPHYR_INCLUDE_ARCH_POSIX_ARCH_H_ #define ZEPHYR_INCLUDE_ARCH_POSIX_ARCH_H_ +#include + /* Add include for DTS generated information */ #include @@ -38,6 +40,52 @@ extern "C" { #define ARCH_STACK_PTR_ALIGN 4 #endif +/* "native_posix" should really use CONFIG_LOG_MODE_IMMEDIATE=y but better safe + * than sorry: debugging crashes is painful enough already, so try to be nice + * and flush all messages. The deferred logging code may also want to enjoy + * native_posix too. + * + * Other archs use Zephyr's elaborate "Fatal Errors" framework which takes care + * of flushing logs but native_posix is simpler so we have to do it ourselves. + */ +static inline void posix_arch_log_immediate(void) +{ +#if defined(CONFIG_LOG) && !defined(CONFIG_LOG_MODE_MINIMAL) + /* We can't #include the higher-level "log_ctrl.h" in this low-level + * file here because this descends into .h dependency hell. So let's + * use a one-line forward declaration instead. This void->void + * prototype does not look like it's going to change much in the + * future. + * + * We can't just declare "void log_panic(void);" here because system + * calls are complicated. As ARCH_EXCEPT() can't be possibly used in + * user mode, log_panic() is equivalent to just z_impl_log_panic(). + * Exceptionally invoke the latter directly. + */ + extern void z_impl_log_panic(void); + z_impl_log_panic(); +#endif +} + +/* Copied from kernel.h */ +#define _EXCEPT_LOC() __ASSERT_PRINT("@ %s:%d\n", __FILE__, __LINE__) + +/* Invoked by k_panic() and k_oops(). + * + * _EXCEPT_LOC() and "ZEPHYR FATAL ERROR" mimic z_fatal_error() + * + * [Z]TEST trigger panics on purpose: don't exit and don't interfere. + */ +#if !defined(CONFIG_ZTEST) && !defined(CONFIG_TEST) +#define ARCH_EXCEPT(reason_p) do { \ + posix_arch_log_immediate(); \ + _EXCEPT_LOC(); \ + printk("ZEPHYR FATAL ERROR: %u\n", reason_p); \ + abort(); CODE_UNREACHABLE; \ +} while (false) +#endif + +/* Exception context */ struct __esf { uint32_t dummy; /*maybe we will want to add something someday*/ }; diff --git a/lib/libc/common/CMakeLists.txt b/lib/libc/common/CMakeLists.txt index 4b101d8b84bdc97..609d4550c6bab88 100644 --- a/lib/libc/common/CMakeLists.txt +++ b/lib/libc/common/CMakeLists.txt @@ -4,10 +4,17 @@ zephyr_system_include_directories(include) zephyr_library() zephyr_library_property(ALLOW_EMPTY TRUE) + +# This abort.c is only a shim for k_panic(), which on POSIX ends up +# calling... abort()! Break that cycle and use the real POSIX abort(). +if(NOT CONFIG_ARCH_POSIX) zephyr_library_sources_ifdef(CONFIG_COMMON_LIBC_ABORT source/stdlib/abort.c) +endif() + zephyr_library_sources_ifdef(CONFIG_COMMON_LIBC_TIME source/time/time.c) zephyr_library_sources_ifdef(CONFIG_COMMON_LIBC_MALLOC source/stdlib/malloc.c) zephyr_library_sources_ifdef(CONFIG_COMMON_LIBC_STRNLEN source/string/strnlen.c) + zephyr_library_sources_ifdef(CONFIG_COMMON_LIBC_THRD source/thrd/cnd.c source/thrd/mtx.c