diff --git a/include/zephyr/arch/posix/arch.h b/include/zephyr/arch/posix/arch.h index 83aceb1c14ba1f..79e83bd9d928d5 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,53 @@ 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() + * + * Many [Z]TESTs invoke k_panic(). The test framework expects that to + * hang forever like hardware does; so don't exit / 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 4b101d8b84bdc9..a34bec49310164 100644 --- a/lib/libc/common/CMakeLists.txt +++ b/lib/libc/common/CMakeLists.txt @@ -4,10 +4,18 @@ zephyr_system_include_directories(include) zephyr_library() zephyr_library_property(ALLOW_EMPTY TRUE) + +# This abort.c is only a shim for k_panic(), which in posix/arch.h 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 diff --git a/tests/lib/c_lib/common/src/main.c b/tests/lib/c_lib/common/src/main.c index 986dba55f8e917..3d2ffeb70cab86 100644 --- a/tests/lib/c_lib/common/src/main.c +++ b/tests/lib/c_lib/common/src/main.c @@ -1220,7 +1220,8 @@ ZTEST(libc_common, test_rand_reproducibility) */ ZTEST(libc_common, test_abort) { -#ifdef CONFIG_EXTERNAL_LIBC +/* posix/arch.h uses a real abort() too */ +#if defined(CONFIG_EXTERNAL_LIBC) || defined(CONFIG_ARCH_POSIX) ztest_test_skip(); #else int a = 0;