From be87822a361ece714b99b89e41d3b64a5cd41402 Mon Sep 17 00:00:00 2001 From: Nikola Kosturski Date: Fri, 12 Jul 2024 12:45:44 +0300 Subject: [PATCH] Add CHIP_CONFIG_DYNAMIC_GLOBALS option to enable dynamic allocation of Globals --- src/app/reporting/ReportSchedulerImpl.h | 6 ++-- src/lib/core/CHIPConfig.h | 12 ++++++++ src/lib/core/Global.h | 41 +++++++++++++++++++------ src/platform/Linux/CHIPPlatformConfig.h | 6 ++++ 4 files changed, 52 insertions(+), 13 deletions(-) diff --git a/src/app/reporting/ReportSchedulerImpl.h b/src/app/reporting/ReportSchedulerImpl.h index ff72eecc8c2de6..87a1f7f4faa555 100644 --- a/src/app/reporting/ReportSchedulerImpl.h +++ b/src/app/reporting/ReportSchedulerImpl.h @@ -73,7 +73,7 @@ class ReportSchedulerImpl : public ReportScheduler * solely based on its ReadHandler's state. Therefore, no synchronization action on the ICDState is needed in this * implementation. */ - void OnTransitionToIdle() override {}; + void OnTransitionToIdle() override{}; /** * @brief When the ICD transitions to Active mode, this implementation will trigger a report emission on each ReadHandler that @@ -88,13 +88,13 @@ class ReportSchedulerImpl : public ReportScheduler * @brief Similar to the OnTransitionToIdle() method, this implementation does not attempt any synchronization on ICD events, * therefore no action is needed on the ICDModeChange() method. */ - void OnICDModeChange() override {}; + void OnICDModeChange() override{}; /** * @brief This implementation does not attempt any synchronization on this ICD event, therefore no action is needed on * ICDEnterIdleMode() */ - void OnEnterIdleMode() override {}; + void OnEnterIdleMode() override{}; // ReadHandlerObserver diff --git a/src/lib/core/CHIPConfig.h b/src/lib/core/CHIPConfig.h index e9c317dfc79d5c..c8c8fdc66ebf5e 100644 --- a/src/lib/core/CHIPConfig.h +++ b/src/lib/core/CHIPConfig.h @@ -187,6 +187,18 @@ #define CHIP_CONFIG_GLOBALS_NO_DESTRUCT 0 #endif // CHIP_CONFIG_GLOBALS_NO_DESTRUCT +/** + * @def CHIP_CONFIG_DYNAMIC_GLOBALS + * + * @brief + * Whether to use dynamic allocation for chip::Global objects. + * + * The default is to use static allocation. + */ +#ifndef CHIP_CONFIG_DYNAMIC_GLOBALS +#define CHIP_CONFIG_DYNAMIC_GLOBALS 0 +#endif // CHIP_CONFIG_DYNAMIC_GLOBALS + /** * @def CHIP_CONFIG_SHA256_CONTEXT_SIZE * diff --git a/src/lib/core/Global.h b/src/lib/core/Global.h index c5fe3739b8fec5..3573998ade8d47 100644 --- a/src/lib/core/Global.h +++ b/src/lib/core/Global.h @@ -85,13 +85,12 @@ class Global /// NOT thread-safe, external synchronization is required. T & get() { return _get(); } T * operator->() { return &_get(); } - - template ::type> + template > U & operator[](std::size_t i) { return _get()[i]; } - template ::value> + template > constexpr std::size_t size() const { return N; @@ -110,17 +109,28 @@ class Global private: // Zero-initialize everything. We should technically leave mStorage uninitialized, // but that can sometimes cause clang to be unable to constant-initialize the object. +#if CHIP_CONFIG_DYNAMIC_GLOBALS + unsigned char * mStorage = nullptr; +#else alignas(T) unsigned char mStorage[sizeof(T)] = {}; +#endif // CHIP_CONFIG_DYNAMIC_GLOBALS OnceStrategy mOnce; T & _get() { - T * value = reinterpret_cast(mStorage); - mOnce.call(&create, value); - return *value; +#if CHIP_CONFIG_DYNAMIC_GLOBALS + mOnce.call(&create, &mStorage); +#else + mOnce.call(&create, mStorage); +#endif // CHIP_CONFIG_DYNAMIC_GLOBALS + return *reinterpret_cast(mStorage); } static void create(void * value) { +#if CHIP_CONFIG_DYNAMIC_GLOBALS + unsigned char ** storage = static_cast(value); + value = *storage = new unsigned char[sizeof(T)]; +#endif // CHIP_CONFIG_DYNAMIC_GLOBALS new (value) T(); #if !CHIP_CONFIG_GLOBALS_NO_DESTRUCT CHIP_CXA_ATEXIT(&destroy, value); @@ -128,17 +138,28 @@ class Global } template - static void destroy(U (*value)[N]) + static void _destroy(U (*value)[N]) + { + _destroy_array(*value, N); + } + template + static void _destroy_array(U * array, std::size_t N) { for (std::size_t i = 0; i < N; ++i) - destroy(value[i]); + array[i].~U(); } template - static void destroy(U * value) + static void _destroy(U * value) { value->~U(); } - static void destroy(void * value) { destroy(static_cast(value)); } + static void destroy(void * value) + { + _destroy(static_cast(value)); +#if CHIP_CONFIG_DYNAMIC_GLOBALS + delete[] static_cast(value); +#endif // CHIP_CONFIG_DYNAMIC_GLOBALS + } #else // CHIP_CONFIG_GLOBALS_LAZY_INIT public: diff --git a/src/platform/Linux/CHIPPlatformConfig.h b/src/platform/Linux/CHIPPlatformConfig.h index 9e2832307f27b2..7eb102b1a6c122 100644 --- a/src/platform/Linux/CHIPPlatformConfig.h +++ b/src/platform/Linux/CHIPPlatformConfig.h @@ -27,6 +27,12 @@ #define CHIP_CONFIG_ABORT() abort() +extern "C" int __cxa_atexit(void (*func)(void *), void * arg, void * d); +#define CHIP_CXA_ATEXIT(f, p) __cxa_atexit((f), (p), nullptr) + +#define CHIP_CONFIG_DYNAMIC_GLOBALS 1 +#define CHIP_CONFIG_GLOBALS_LAZY_INIT 1 + using CHIP_CONFIG_PERSISTED_STORAGE_KEY_TYPE = const char *; #define CHIP_CONFIG_PERSISTED_STORAGE_MAX_KEY_LENGTH 16