Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions components/libc/cplusplus/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,17 @@ menuconfig RT_USING_CPLUSPLUS

if RT_USING_CPLUSPLUS

config RT_USING_CPP_CRT_INIT
bool "Let the startup runtime initialize C++ constructors"
default y if SOC_SIMULATOR
default n
help
Enable this for GCC ports whose startup runtime already calls
global constructors. RT-Thread will skip both the ctors and
init_array ranges to avoid running constructors twice.
Leave this disabled with RT-Thread's newlib port, which provides
an empty __libc_init_array and defers constructors to RT-Thread.

config RT_USING_CPLUSPLUS11
bool "Enable C++11 standard multi-threading feature support"
default n
Expand Down
40 changes: 33 additions & 7 deletions components/libc/cplusplus/cxx_crt_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,7 @@ rt_weak void *__dso_handle = 0;
* @note If there is no SHT$$INIT_ARRAY section, calling $Super$$__cpp_initialize__aeabi_() will cause an error
* in ARMCC compiler. Therefore, this function manually iterates through the base addresses of the
* SHT$$INIT_ARRAY section to call the constructor functions of each object. In GCC compiler, this function
* uses the __ctors_start__ and __ctors_end__ global variables to determine the range of constructor function
* pointers and calls each constructor function of every object in that range.
* walks the ctors and init_array ranges unless RT_USING_CPP_CRT_INIT assigns this to the startup runtime.
*
* @return Returns 0 if the initialization of the C++ runtime environment is successful. Otherwise, it returns
* an error code indicating the failure of the operation.
Expand All @@ -65,14 +64,41 @@ rt_weak int cplusplus_system_init(void)
PROC *proc = (PROC *)((const char *)base + *base);
(*proc)();
}
#elif defined(__GNUC__)
#elif defined(__GNUC__) && !defined(RT_USING_CPP_CRT_INIT)
typedef void(*pfunc)();
extern pfunc __ctors_start__[];
extern pfunc __ctors_end__[];
/* Linker scripts may provide either or both constructor ranges. */
extern pfunc __ctors_start__[] __attribute__((weak));
extern pfunc __ctors_end__[] __attribute__((weak));
extern pfunc __init_array_start[] __attribute__((weak));
extern pfunc __init_array_end[] __attribute__((weak));
pfunc *ctors_start = __ctors_start__;
pfunc *ctors_end = __ctors_end__;
pfunc *init_start = __init_array_start;
pfunc *init_end = __init_array_end;
pfunc *p;

for (p = __ctors_start__; p < __ctors_end__; p++)
(*p)();
if (ctors_start && ctors_end)
{
for (p = ctors_start; (uintptr_t)p < (uintptr_t)ctors_end; p++)
{
(*p)();
}
}

if (init_start && init_end)
{
for (p = init_start; (uintptr_t)p < (uintptr_t)init_end; p++)
{
/* Skip entries already called through the ctors range. */
if (ctors_start && ctors_end &&
(uintptr_t)p >= (uintptr_t)ctors_start &&
(uintptr_t)p < (uintptr_t)ctors_end)
{
continue;
}
(*p)();
}
}
#endif

return 0;
Expand Down
Loading