-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[zephyr] Allow to override default malloc with sys_heap (#16926)
* [zephyr] Allow to override default malloc with sys_heap Add a setting that overrides default malloc/calloc/realloc/ free functions with custom implementations based on sys_heap from Zephyr RTOS. Update DiagnosticDataProvider methods for obtaining the heap statistics to use the sys_heap statistics when sys_heap-baed malloc is used. Additionally, fix the DiagnosticDataProvider implementation using mallinfo() by taking the maximum heap size into account. * Restyled by whitespace * Restyled by clang-format * Restyled by gn * Handle mul overflow * Add separate switch for wrapping malloc/calloc/realloc/free symbols * Restyled by gn Co-authored-by: Restyled.io <[email protected]>
- Loading branch information
1 parent
41a431d
commit f86c68c
Showing
9 changed files
with
323 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,180 @@ | ||
/* | ||
* | ||
* Copyright (c) 2022 Project CHIP Authors | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
#include "SysHeapMalloc.h" | ||
|
||
#include <lib/support/CodeUtils.h> | ||
#include <system/SystemError.h> | ||
|
||
extern "C" { | ||
#include <init.h> | ||
#include <sys/math_extras.h> | ||
#include <sys/mutex.h> | ||
#include <sys/sys_heap.h> | ||
} | ||
|
||
#include <cstdint> | ||
#include <cstring> | ||
|
||
// Construct name of the given function wrapped with the `--wrap=symbol` GCC option. | ||
#define WRAP(f) __wrap_##f | ||
|
||
using namespace chip; | ||
|
||
namespace { | ||
|
||
// Alignment of memory blocks returned by malloc. | ||
// Choose the value that guarantees that the returned memory blocks are castable to all built-in types. | ||
constexpr size_t kMallocAlignment = alignof(long long); | ||
|
||
uint8_t sHeapMemory[CONFIG_CHIP_MALLOC_SYS_HEAP_SIZE] alignas(kMallocAlignment); | ||
sys_heap sHeap; | ||
SYS_MUTEX_DEFINE(sLock); | ||
|
||
// RAII helper for synchronizing access to the common heap. | ||
class LockGuard | ||
{ | ||
public: | ||
LockGuard() : mStatus(sys_mutex_lock(&sLock, K_FOREVER)) {} | ||
~LockGuard(); | ||
|
||
bool Locked() const { return mStatus == 0; } | ||
CHIP_ERROR Error() const { return System::MapErrorZephyr(mStatus); } | ||
|
||
private: | ||
const int mStatus; | ||
}; | ||
|
||
LockGuard::~LockGuard() | ||
{ | ||
if (mStatus == 0) | ||
{ | ||
sys_mutex_unlock(&sLock); | ||
} | ||
} | ||
|
||
int initHeap(const device *) | ||
{ | ||
sys_heap_init(&sHeap, sHeapMemory, sizeof(sHeapMemory)); | ||
return 0; | ||
} | ||
|
||
} // namespace | ||
|
||
// Initialize the heap in the POST_KERNEL phase to make sure that it is ready even before | ||
// C++ static constructors are called (which happens prior to the APPLICATION initialization phase). | ||
SYS_INIT(initHeap, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); | ||
|
||
namespace chip { | ||
namespace DeviceLayer { | ||
namespace Malloc { | ||
|
||
void * Malloc(size_t size) | ||
{ | ||
LockGuard lockGuard; | ||
|
||
return lockGuard.Locked() ? sys_heap_aligned_alloc(&sHeap, kMallocAlignment, size) : nullptr; | ||
} | ||
|
||
void * Calloc(size_t num, size_t size) | ||
{ | ||
size_t totalSize; | ||
|
||
if (size_mul_overflow(num, size, &totalSize)) | ||
{ | ||
return nullptr; | ||
} | ||
|
||
void * mem = malloc(totalSize); | ||
|
||
if (mem) | ||
{ | ||
memset(mem, 0, totalSize); | ||
} | ||
|
||
return mem; | ||
} | ||
|
||
void * Realloc(void * mem, size_t size) | ||
{ | ||
LockGuard lockGuard; | ||
|
||
return lockGuard.Locked() ? sys_heap_aligned_realloc(&sHeap, mem, kMallocAlignment, size) : nullptr; | ||
} | ||
|
||
void Free(void * mem) | ||
{ | ||
LockGuard lockGuard; | ||
|
||
VerifyOrReturn(lockGuard.Locked()); | ||
sys_heap_free(&sHeap, mem); | ||
} | ||
|
||
#ifdef CONFIG_SYS_HEAP_RUNTIME_STATS | ||
|
||
CHIP_ERROR GetStats(Stats & stats) | ||
{ | ||
LockGuard lockGuard; | ||
ReturnErrorOnFailure(lockGuard.Error()); | ||
|
||
sys_heap_runtime_stats sysHeapStats; | ||
ReturnErrorOnFailure(System::MapErrorZephyr(sys_heap_runtime_stats_get(&sHeap, &sysHeapStats))); | ||
|
||
stats.free = sysHeapStats.free_bytes; | ||
stats.used = sysHeapStats.allocated_bytes; | ||
|
||
return CHIP_NO_ERROR; | ||
} | ||
|
||
#endif // CONFIG_SYS_HEAP_RUNTIME_STATS | ||
|
||
} // namespace Malloc | ||
} // namespace DeviceLayer | ||
} // namespace chip | ||
|
||
#ifdef CONFIG_CHIP_MALLOC_SYS_HEAP_OVERRIDE | ||
|
||
extern "C" { | ||
|
||
void * WRAP(malloc)(size_t size) __attribute((alias("_ZN4chip11DeviceLayer6Malloc6MallocEj"))); | ||
void * WRAP(calloc)(size_t num, size_t size) __attribute((alias("_ZN4chip11DeviceLayer6Malloc6CallocEjj"))); | ||
void * WRAP(realloc)(void * mem, size_t size) __attribute((alias("_ZN4chip11DeviceLayer6Malloc7ReallocEPvj"))); | ||
void WRAP(free)(void * mem) __attribute((alias("_ZN4chip11DeviceLayer6Malloc4FreeEPv"))); | ||
|
||
void * WRAP(_malloc_r)(_reent *, size_t size) | ||
{ | ||
return WRAP(malloc)(size); | ||
} | ||
|
||
void * WRAP(_calloc_r)(_reent *, size_t num, size_t size) | ||
{ | ||
return WRAP(calloc)(num, size); | ||
} | ||
|
||
void * WRAP(_realloc_r)(_reent *, void * mem, size_t size) | ||
{ | ||
return WRAP(realloc)(mem, size); | ||
} | ||
|
||
void WRAP(_free_r)(_reent *, void * mem) | ||
{ | ||
WRAP(free)(mem); | ||
} | ||
|
||
} // extern "C" | ||
|
||
#endif // CONFIG_CHIP_MALLOC_SYS_HEAP_OVERRIDE |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
/* | ||
* | ||
* Copyright (c) 2022 Project CHIP Authors | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
#include <cstddef> | ||
|
||
#include <lib/core/CHIPError.h> | ||
|
||
namespace chip { | ||
namespace DeviceLayer { | ||
namespace Malloc { | ||
|
||
struct Stats | ||
{ | ||
size_t free; | ||
size_t used; | ||
}; | ||
|
||
void * Malloc(size_t size); | ||
void * Calloc(size_t num, size_t size); | ||
void * Realloc(void * mem, size_t size); | ||
void Free(void * mem); | ||
CHIP_ERROR GetStats(Stats & stats); | ||
|
||
} // namespace Malloc | ||
} // namespace DeviceLayer | ||
} // namespace chip |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.