Merge branch 'refactor/nvs_allocatable_objects_v4.2' into 'release/v4.2'

refactor(nvs): custom allocator for all objects allocated in NVS (v4.2)

See merge request espressif/esp-idf!21796
This commit is contained in:
Zim Kalinowski 2023-03-14 03:58:03 +08:00
commit f558578958
9 changed files with 108 additions and 65 deletions

View File

@ -15,6 +15,7 @@
#define intrusive_list_h
#include <cassert>
#include <cstddef>
#include <unordered_map>
template <typename T>

View File

@ -24,6 +24,8 @@
#ifdef CONFIG_NVS_ENCRYPTION
#include "nvs_encr.hpp"
#endif
#include "nvs_memory_management.hpp"
#include "esp_err.h"
#ifdef ESP_PLATFORM
#include <esp32/rom/crc.h>
@ -37,7 +39,7 @@ static const char* TAG = "nvs";
#define ESP_LOGD(...)
#endif
class NVSHandleEntry : public intrusive_list_node<NVSHandleEntry> {
class NVSHandleEntry : public intrusive_list_node<NVSHandleEntry>, public ExceptionlessAllocatable {
public:
NVSHandleEntry(nvs::NVSHandleSimple *handle, const char* part_name)
: nvs_handle(handle),

View File

@ -1,16 +1,8 @@
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
//
// 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.
/*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef NVS_HANDLE_SIMPLE_HPP_
#define NVS_HANDLE_SIMPLE_HPP_
@ -18,6 +10,7 @@
#include "nvs_storage.hpp"
#include "nvs_platform.hpp"
#include "nvs_memory_management.hpp"
#include "nvs_handle.hpp"
namespace nvs {
@ -30,7 +23,9 @@ namespace nvs {
*
* For more details about the general member functions, see nvs_handle.hpp.
*/
class NVSHandleSimple : public intrusive_list_node<NVSHandleSimple>, public NVSHandle {
class NVSHandleSimple : public intrusive_list_node<NVSHandleSimple>,
public NVSHandle,
public ExceptionlessAllocatable {
friend class NVSPartitionManager;
public:
NVSHandleSimple(bool readOnly, uint8_t nsIndex, Storage *StoragePtr) :

View File

@ -1,22 +1,15 @@
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
//
// 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.
/*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef nvs_item_hash_list_h
#define nvs_item_hash_list_h
#include "nvs.h"
#include "nvs_types.hpp"
#include "nvs_memory_management.hpp"
#include "intrusive_list.h"
namespace nvs
@ -54,7 +47,7 @@ protected:
uint32_t mHash : 24;
};
struct HashListBlock : public intrusive_list_node<HashList::HashListBlock> {
struct HashListBlock : public intrusive_list_node<HashList::HashListBlock>, public ExceptionlessAllocatable {
HashListBlock();
static const size_t BYTE_SIZE = 128;

View File

@ -0,0 +1,62 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <cstdlib>
#pragma once
/**
* @brief Type that is only usable with new (std::nothrow) to avoid exceptions.
*
* This struct shall be inherited by all types in NVS that may be allocated dynamically (with new).
*
* NVS allocates memory at runtime. Because we use C++, we need to avoid the global ``operator new`` from libstdc++,
* since it throws exceptions and we compile NVS with ``-fno-exceptions``. We also need to avoid the global
* non-throwing version of that operator from libstdc++, since it is merely a wrapper around the original operator
* catching all exceptions.
*
* This struct removes the normal operator new from this and all types inheriting from it. It furthermore provides
* a custom version of operator new (..., const std::nothrow_t&) noexcept that will not use C++ exceptions.
*
* E.g., if you have a type MyType inheriting from ExceptionlessAllocatable, you want to use it as follows:
* @code{c++}
* MyType : public ExceptionlessAllocatable {
* ExceptionlessAllocatable();
* ExceptionlessAllocatable(int param);
* };
* // ...
* MyType *m0 = new (std::nothrow) MyType;
* MyType *m1 = new (std::nothrow) MyType(47);
* // ...
* delete m1;
* delete m0;
* @endcode
*/
struct ExceptionlessAllocatable {
/**
* Disallow use of the default new operator, all of NVS is currently tailored to not throw exceptions
*/
static void *operator new( std::size_t ) = delete;
/**
* Simple implementation with malloc(). No exceptions are thrown if the allocation fails.
* To use this operator, your type must inherit from this class and then allocate with:
* @code{c}
* new (std::nothrow) <YourType>; // default constructor
* new (std::nothrow) <YourType>(<constructor parameters>); // non-default constructor
* @endcode
*/
void *operator new (size_t size, const std::nothrow_t&) noexcept {
return std::malloc(size);
}
/**
* Use \c delete as normal. This operator will be called automatically instead of the global one from libstdc++.
*/
void operator delete (void *obj) noexcept {
free(obj);
}
};

View File

@ -14,9 +14,11 @@
#include "esp_spi_flash.h"
#include "nvs_ops.hpp"
#include <cstddef>
#ifdef CONFIG_NVS_ENCRYPTION
#include "nvs_encr.hpp"
#include <string.h>
#include <cstdlib>
#endif
namespace nvs
@ -39,7 +41,7 @@ esp_err_t nvs_flash_write(size_t destAddr, const void *srcAddr, size_t size) {
return err;
}
err = spi_flash_write(destAddr, buf, size);
delete buf;
free(buf);
return err;
}
}

View File

@ -24,12 +24,13 @@
#include "compressed_enum_table.hpp"
#include "intrusive_list.h"
#include "nvs_item_hash_list.hpp"
#include "nvs_memory_management.hpp"
namespace nvs
{
class Page : public intrusive_list_node<Page>
class Page : public intrusive_list_node<Page>, public ExceptionlessAllocatable
{
public:
static const uint32_t PSB_INIT = 0x1;

View File

@ -1,21 +1,14 @@
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
//
// 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.
/*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef NVS_PARTITION_MANAGER_HPP_
#define NVS_PARTITION_MANAGER_HPP_
#include "nvs_handle_simple.hpp"
#include "nvs_storage.hpp"
#include "nvs_memory_management.hpp"
#ifdef CONFIG_NVS_ENCRYPTION
#include "nvs_encr.hpp"
@ -23,7 +16,7 @@
namespace nvs {
class NVSPartitionManager {
class NVSPartitionManager : public ExceptionlessAllocatable {
public:
virtual ~NVSPartitionManager() { }

View File

@ -1,39 +1,33 @@
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
//
// 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.
/*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef nvs_storage_hpp
#define nvs_storage_hpp
#include <memory>
#include <cstdlib>
#include <unordered_map>
#include "nvs.hpp"
#include "nvs_types.hpp"
#include "nvs_page.hpp"
#include "nvs_pagemanager.hpp"
#include "nvs_memory_management.hpp"
//extern void dumpBytes(const uint8_t* data, size_t count);
namespace nvs
{
class Storage : public intrusive_list_node<Storage>
class Storage : public intrusive_list_node<Storage>, public ExceptionlessAllocatable
{
enum class StorageState : uint32_t {
INVALID,
ACTIVE,
};
struct NamespaceEntry : public intrusive_list_node<NamespaceEntry> {
struct NamespaceEntry : public intrusive_list_node<NamespaceEntry>, public ExceptionlessAllocatable {
public:
char mName[Item::MAX_KEY_LENGTH + 1];
uint8_t mIndex;
@ -41,13 +35,13 @@ class Storage : public intrusive_list_node<Storage>
typedef intrusive_list<NamespaceEntry> TNamespaces;
struct UsedPageNode: public intrusive_list_node<UsedPageNode> {
struct UsedPageNode: public intrusive_list_node<UsedPageNode>, public ExceptionlessAllocatable {
public: Page* mPage;
};
typedef intrusive_list<UsedPageNode> TUsedPageList;
struct BlobIndexNode: public intrusive_list_node<BlobIndexNode> {
struct BlobIndexNode: public intrusive_list_node<BlobIndexNode>, public ExceptionlessAllocatable {
public:
char key[Item::MAX_KEY_LENGTH + 1];
uint8_t nsIndex;