mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'feature/cxx_exceptions_emg_pool' into 'master'
esp32: Adds C++ exceptions emergency pool size menuconfig option See merge request !1561
This commit is contained in:
commit
b669b415e6
14
Kconfig
14
Kconfig
@ -93,7 +93,7 @@ config OPTIMIZATION_ASSERTIONS_DISABLED
|
|||||||
|
|
||||||
endchoice # assertions
|
endchoice # assertions
|
||||||
|
|
||||||
config CXX_EXCEPTIONS
|
menuconfig CXX_EXCEPTIONS
|
||||||
bool "Enable C++ exceptions"
|
bool "Enable C++ exceptions"
|
||||||
default n
|
default n
|
||||||
help
|
help
|
||||||
@ -102,8 +102,16 @@ config CXX_EXCEPTIONS
|
|||||||
Disabling this option disables C++ exception support in all compiled files, and any libstdc++ code which throws
|
Disabling this option disables C++ exception support in all compiled files, and any libstdc++ code which throws
|
||||||
an exception will abort instead.
|
an exception will abort instead.
|
||||||
|
|
||||||
Enabling this option currently adds an additional 20KB of heap overhead, and 4KB of additional heap is allocated
|
Enabling this option currently adds an additional ~500 bytes of heap overhead
|
||||||
the first time an exception is thrown in user code.
|
when an exception is thrown in user code for the first time.
|
||||||
|
|
||||||
|
config CXX_EXCEPTIONS_EMG_POOL_SIZE
|
||||||
|
int "Emergency Pool Size"
|
||||||
|
default 0
|
||||||
|
depends on CXX_EXCEPTIONS
|
||||||
|
help
|
||||||
|
Size (in bytes) of the emergency memory pool for C++ exceptions. This pool will be used to allocate
|
||||||
|
memory for thrown exceptions when there is not enough memory on the heap.
|
||||||
|
|
||||||
choice STACK_CHECK_MODE
|
choice STACK_CHECK_MODE
|
||||||
prompt "Stack smashing protection mode"
|
prompt "Stack smashing protection mode"
|
||||||
|
@ -20,7 +20,7 @@ class Base
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~Base() {}
|
virtual ~Base() {}
|
||||||
virtual void foo() = 0;
|
virtual void foo() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Derived : public Base
|
class Derived : public Base
|
||||||
@ -192,8 +192,13 @@ TEST_CASE("before scheduler has started, static initializers work correctly", "[
|
|||||||
|
|
||||||
TEST_CASE("c++ exceptions work", "[cxx]")
|
TEST_CASE("c++ exceptions work", "[cxx]")
|
||||||
{
|
{
|
||||||
/* Note: This test currently trips the memory leak threshold
|
/* Note: When first exception (in system) is thrown this test produces memory leaks report (~500 bytes):
|
||||||
as libunwind allocates ~4KB of data on first exception. */
|
- 392 bytes (can vary) as libunwind allocates memory to keep stack frames info to handle exceptions.
|
||||||
|
This info is kept until global destructors are called by __do_global_dtors_aux()
|
||||||
|
- 8 bytes are allocated by __cxa_get_globals() to keep __cxa_eh_globals
|
||||||
|
- 16 bytes are allocated by pthread_setspecific() which is called by __cxa_get_globals() to init TLS var for __cxa_eh_globals
|
||||||
|
- 88 bytes are allocated by pthread_setspecific() to init internal lock
|
||||||
|
*/
|
||||||
int thrown_value;
|
int thrown_value;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -207,6 +212,60 @@ TEST_CASE("c++ exceptions work", "[cxx]")
|
|||||||
printf("OK?\n");
|
printf("OK?\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("c++ exceptions emergency pool", "[cxx] [ignore]")
|
||||||
|
{
|
||||||
|
/* Note: When first exception (in system) is thrown this test produces memory leaks report (~500 bytes):
|
||||||
|
- 392 bytes (can vary) as libunwind allocates memory to keep stack frames info to handle exceptions.
|
||||||
|
This info is kept until global destructors are called by __do_global_dtors_aux()
|
||||||
|
- 8 bytes are allocated by __cxa_get_globals() to keep __cxa_eh_globals
|
||||||
|
- 16 bytes are allocated by pthread_setspecific() which is called by __cxa_get_globals() to init TLS var for __cxa_eh_globals
|
||||||
|
- 88 bytes are allocated by pthread_setspecific() to init internal lock
|
||||||
|
*/
|
||||||
|
void **p, **pprev = NULL;
|
||||||
|
int thrown_value = 0;
|
||||||
|
// throw first exception to ensure that all initial allocations are made
|
||||||
|
try
|
||||||
|
{
|
||||||
|
throw 33;
|
||||||
|
}
|
||||||
|
catch (int e)
|
||||||
|
{
|
||||||
|
thrown_value = e;
|
||||||
|
}
|
||||||
|
TEST_ASSERT_EQUAL(33, thrown_value);
|
||||||
|
// consume all dynamic memory
|
||||||
|
while ((p = (void **)malloc(sizeof(void *)))) {
|
||||||
|
if (pprev) {
|
||||||
|
*p = pprev;
|
||||||
|
} else {
|
||||||
|
*p = NULL;
|
||||||
|
}
|
||||||
|
pprev = p;
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
throw 20;
|
||||||
|
}
|
||||||
|
catch (int e)
|
||||||
|
{
|
||||||
|
thrown_value = e;
|
||||||
|
printf("Got exception %d\n", thrown_value);
|
||||||
|
}
|
||||||
|
#if CONFIG_CXX_EXCEPTIONS_EMG_POOL_SIZE > 0
|
||||||
|
// free all memory
|
||||||
|
while (pprev) {
|
||||||
|
p = (void **)(*pprev);
|
||||||
|
free(pprev);
|
||||||
|
pprev = p;
|
||||||
|
}
|
||||||
|
TEST_ASSERT_EQUAL(20, thrown_value);
|
||||||
|
#else
|
||||||
|
// if emergency pool is disabled we should never get here,
|
||||||
|
// expect abort() due to lack of memory for new exception
|
||||||
|
TEST_ASSERT_TRUE(0 == 1);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* These test cases pull a lot of code from libstdc++ and are disabled for now
|
/* These test cases pull a lot of code from libstdc++ and are disabled for now
|
||||||
|
@ -397,6 +397,13 @@ void start_cpu1_default(void)
|
|||||||
}
|
}
|
||||||
#endif //!CONFIG_FREERTOS_UNICORE
|
#endif //!CONFIG_FREERTOS_UNICORE
|
||||||
|
|
||||||
|
#ifdef CONFIG_CXX_EXCEPTIONS
|
||||||
|
size_t __cxx_eh_arena_size_get()
|
||||||
|
{
|
||||||
|
return CONFIG_CXX_EXCEPTIONS_EMG_POOL_SIZE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void do_global_ctors(void)
|
static void do_global_ctors(void)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_CXX_EXCEPTIONS
|
#ifdef CONFIG_CXX_EXCEPTIONS
|
||||||
|
Loading…
Reference in New Issue
Block a user