diff --git a/features/TESTS/filesystem/util_block_device/main.cpp b/features/TESTS/filesystem/util_block_device/main.cpp index e4fff615b4..f551861824 100644 --- a/features/TESTS/filesystem/util_block_device/main.cpp +++ b/features/TESTS/filesystem/util_block_device/main.cpp @@ -92,10 +92,6 @@ void test_slicing() { TEST_ASSERT_EQUAL(0xff & rand(), read_block[i]); } - err = slice1.deinit(); - TEST_ASSERT_EQUAL(0, err); - - // Test with second slice of block device err = slice2.init(); TEST_ASSERT_EQUAL(0, err); @@ -109,6 +105,10 @@ void test_slicing() { write_block[i] = 0xff & rand(); } + // Deinitialize slice1 here, to check whether init reference count works + err = slice1.deinit(); + TEST_ASSERT_EQUAL(0, err); + // Write, sync, and read the block err = slice2.program(write_block, 0, BLOCK_SIZE); TEST_ASSERT_EQUAL(0, err); diff --git a/features/filesystem/bd/BufferedBlockDevice.cpp b/features/filesystem/bd/BufferedBlockDevice.cpp index 7fba7c7f7e..996f2c0bcb 100644 --- a/features/filesystem/bd/BufferedBlockDevice.cpp +++ b/features/filesystem/bd/BufferedBlockDevice.cpp @@ -16,6 +16,7 @@ #include "BufferedBlockDevice.h" #include "mbed_assert.h" +#include "mbed_critical.h" #include #include @@ -25,7 +26,7 @@ static inline uint32_t align_down(bd_size_t val, bd_size_t size) } BufferedBlockDevice::BufferedBlockDevice(BlockDevice *bd) - : _bd(bd), _bd_program_size(0), _curr_aligned_addr(0), _flushed(true), _cache(0) + : _bd(bd), _bd_program_size(0), _curr_aligned_addr(0), _flushed(true), _cache(0), _init_ref_count(0) { } @@ -36,6 +37,12 @@ BufferedBlockDevice::~BufferedBlockDevice() int BufferedBlockDevice::init() { + uint32_t val = core_util_atomic_incr_u32(&_init_ref_count, 1); + + if (val != 1) { + return BD_ERROR_OK; + } + int err = _bd->init(); if (err) { return err; @@ -55,6 +62,12 @@ int BufferedBlockDevice::init() int BufferedBlockDevice::deinit() { + uint32_t val = core_util_atomic_decr_u32(&_init_ref_count, 1); + + if (val) { + return BD_ERROR_OK; + } + delete[] _cache; _cache = 0; return _bd->deinit(); diff --git a/features/filesystem/bd/BufferedBlockDevice.h b/features/filesystem/bd/BufferedBlockDevice.h index 85aa117662..52742f78ce 100644 --- a/features/filesystem/bd/BufferedBlockDevice.h +++ b/features/filesystem/bd/BufferedBlockDevice.h @@ -153,6 +153,7 @@ protected: bd_size_t _curr_aligned_addr; bool _flushed; uint8_t *_cache; + uint32_t _init_ref_count; /** Flush data in cache * diff --git a/features/filesystem/bd/ChainingBlockDevice.cpp b/features/filesystem/bd/ChainingBlockDevice.cpp index f0be36b314..fd00fea473 100644 --- a/features/filesystem/bd/ChainingBlockDevice.cpp +++ b/features/filesystem/bd/ChainingBlockDevice.cpp @@ -15,12 +15,13 @@ */ #include "ChainingBlockDevice.h" +#include "mbed_critical.h" ChainingBlockDevice::ChainingBlockDevice(BlockDevice **bds, size_t bd_count) : _bds(bds), _bd_count(bd_count) , _read_size(0), _program_size(0), _erase_size(0), _size(0) - , _erase_value(-1) + , _erase_value(-1), _init_ref_count(0) { } @@ -31,6 +32,12 @@ static bool is_aligned(uint64_t x, uint64_t alignment) int ChainingBlockDevice::init() { + uint32_t val = core_util_atomic_incr_u32(&_init_ref_count, 1); + + if (val != 1) { + return BD_ERROR_OK; + } + _read_size = 0; _program_size = 0; _erase_size = 0; @@ -83,6 +90,12 @@ int ChainingBlockDevice::init() int ChainingBlockDevice::deinit() { + uint32_t val = core_util_atomic_decr_u32(&_init_ref_count, 1); + + if (val) { + return BD_ERROR_OK; + } + for (size_t i = 0; i < _bd_count; i++) { int err = _bds[i]->deinit(); if (err) { diff --git a/features/filesystem/bd/ChainingBlockDevice.h b/features/filesystem/bd/ChainingBlockDevice.h index ad3c6e884a..d1d1085e8f 100644 --- a/features/filesystem/bd/ChainingBlockDevice.h +++ b/features/filesystem/bd/ChainingBlockDevice.h @@ -64,7 +64,7 @@ public: template ChainingBlockDevice(BlockDevice *(&bds)[Size]) : _bds(bds), _bd_count(sizeof(bds) / sizeof(bds[0])) - , _read_size(0), _program_size(0), _erase_size(0), _size(0) + , _read_size(0), _program_size(0), _erase_size(0), _size(0), _init_ref_count(0) { } @@ -175,6 +175,7 @@ protected: bd_size_t _erase_size; bd_size_t _size; int _erase_value; + uint32_t _init_ref_count; }; diff --git a/features/filesystem/bd/ExhaustibleBlockDevice.cpp b/features/filesystem/bd/ExhaustibleBlockDevice.cpp index 2c5ed3d104..a7bb0bc05d 100644 --- a/features/filesystem/bd/ExhaustibleBlockDevice.cpp +++ b/features/filesystem/bd/ExhaustibleBlockDevice.cpp @@ -16,10 +16,11 @@ #include "ExhaustibleBlockDevice.h" #include "mbed.h" +#include "mbed_critical.h" ExhaustibleBlockDevice::ExhaustibleBlockDevice(BlockDevice *bd, uint32_t erase_cycles) - : _bd(bd), _erase_array(NULL), _erase_cycles(erase_cycles) + : _bd(bd), _erase_array(NULL), _erase_cycles(erase_cycles), _init_ref_count(0) { } @@ -30,6 +31,12 @@ ExhaustibleBlockDevice::~ExhaustibleBlockDevice() int ExhaustibleBlockDevice::init() { + uint32_t val = core_util_atomic_incr_u32(&_init_ref_count, 1); + + if (val != 1) { + return BD_ERROR_OK; + } + int err = _bd->init(); if (err) { return err; @@ -48,6 +55,12 @@ int ExhaustibleBlockDevice::init() int ExhaustibleBlockDevice::deinit() { + core_util_atomic_decr_u32(&_init_ref_count, 1); + + if (_init_ref_count) { + return BD_ERROR_OK; + } + // _erase_array is lazily cleaned up in destructor to allow // data to live across de/reinitialization return _bd->deinit(); diff --git a/features/filesystem/bd/ExhaustibleBlockDevice.h b/features/filesystem/bd/ExhaustibleBlockDevice.h index e55f662fe9..55b0041a7c 100644 --- a/features/filesystem/bd/ExhaustibleBlockDevice.h +++ b/features/filesystem/bd/ExhaustibleBlockDevice.h @@ -154,6 +154,7 @@ private: BlockDevice *_bd; uint32_t *_erase_array; uint32_t _erase_cycles; + uint32_t _init_ref_count; }; diff --git a/features/filesystem/bd/FlashSimBlockDevice.cpp b/features/filesystem/bd/FlashSimBlockDevice.cpp index 35bb8b69f4..631ea42b7c 100644 --- a/features/filesystem/bd/FlashSimBlockDevice.cpp +++ b/features/filesystem/bd/FlashSimBlockDevice.cpp @@ -16,6 +16,7 @@ #include "FlashSimBlockDevice.h" #include "mbed_assert.h" +#include "mbed_critical.h" #include #include #include @@ -29,7 +30,7 @@ static inline uint32_t align_up(bd_size_t val, bd_size_t size) FlashSimBlockDevice::FlashSimBlockDevice(BlockDevice *bd, uint8_t erase_value) : _erase_value(erase_value), _blank_buf_size(0), - _blank_buf(0), _bd(bd) + _blank_buf(0), _bd(bd), _init_ref_count(0) { } @@ -41,6 +42,12 @@ FlashSimBlockDevice::~FlashSimBlockDevice() int FlashSimBlockDevice::init() { + uint32_t val = core_util_atomic_incr_u32(&_init_ref_count, 1); + + if (val != 1) { + return BD_ERROR_OK; + } + int ret = _bd->init(); if (ret) { return ret; @@ -55,6 +62,12 @@ int FlashSimBlockDevice::init() int FlashSimBlockDevice::deinit() { + uint32_t val = core_util_atomic_decr_u32(&_init_ref_count, 1); + + if (val) { + return BD_ERROR_OK; + } + return _bd->deinit(); } diff --git a/features/filesystem/bd/FlashSimBlockDevice.h b/features/filesystem/bd/FlashSimBlockDevice.h index 6ee7cc4abe..832374ab82 100644 --- a/features/filesystem/bd/FlashSimBlockDevice.h +++ b/features/filesystem/bd/FlashSimBlockDevice.h @@ -135,6 +135,7 @@ private: bd_size_t _blank_buf_size; uint8_t *_blank_buf; BlockDevice *_bd; + uint32_t _init_ref_count; }; #endif diff --git a/features/filesystem/bd/HeapBlockDevice.cpp b/features/filesystem/bd/HeapBlockDevice.cpp index 379fea8c75..70de3f4730 100644 --- a/features/filesystem/bd/HeapBlockDevice.cpp +++ b/features/filesystem/bd/HeapBlockDevice.cpp @@ -15,18 +15,19 @@ */ #include "HeapBlockDevice.h" +#include "mbed_critical.h" HeapBlockDevice::HeapBlockDevice(bd_size_t size, bd_size_t block) : _read_size(block), _program_size(block), _erase_size(block) - , _count(size / block), _blocks(0) + , _count(size / block), _blocks(0), _init_ref_count(0) { MBED_ASSERT(_count * _erase_size == size); } HeapBlockDevice::HeapBlockDevice(bd_size_t size, bd_size_t read, bd_size_t program, bd_size_t erase) : _read_size(read), _program_size(program), _erase_size(erase) - , _count(size / erase), _blocks(0) + , _count(size / erase), _blocks(0), _init_ref_count(0) { MBED_ASSERT(_count * _erase_size == size); } @@ -45,6 +46,12 @@ HeapBlockDevice::~HeapBlockDevice() int HeapBlockDevice::init() { + uint32_t val = core_util_atomic_incr_u32(&_init_ref_count, 1); + + if (val != 1) { + return BD_ERROR_OK; + } + if (!_blocks) { _blocks = new uint8_t*[_count]; for (size_t i = 0; i < _count; i++) { @@ -57,6 +64,12 @@ int HeapBlockDevice::init() int HeapBlockDevice::deinit() { + uint32_t val = core_util_atomic_decr_u32(&_init_ref_count, 1); + + if (val) { + return BD_ERROR_OK; + } + MBED_ASSERT(_blocks != NULL); // Memory is lazily cleaned up in destructor to allow // data to live across de/reinitialization diff --git a/features/filesystem/bd/HeapBlockDevice.h b/features/filesystem/bd/HeapBlockDevice.h index 8d65e82b3d..874661b8f8 100644 --- a/features/filesystem/bd/HeapBlockDevice.h +++ b/features/filesystem/bd/HeapBlockDevice.h @@ -150,6 +150,7 @@ private: bd_size_t _erase_size; bd_size_t _count; uint8_t **_blocks; + uint32_t _init_ref_count; }; diff --git a/features/filesystem/bd/MBRBlockDevice.cpp b/features/filesystem/bd/MBRBlockDevice.cpp index bcea66f69b..9a841bbcc2 100644 --- a/features/filesystem/bd/MBRBlockDevice.cpp +++ b/features/filesystem/bd/MBRBlockDevice.cpp @@ -15,6 +15,7 @@ */ #include "MBRBlockDevice.h" +#include "mbed_critical.h" #include @@ -194,13 +195,19 @@ int MBRBlockDevice::partition(BlockDevice *bd, int part, uint8_t type, } MBRBlockDevice::MBRBlockDevice(BlockDevice *bd, int part) - : _bd(bd), _part(part) + : _bd(bd), _part(part), _init_ref_count(0) { MBED_ASSERT(_part >= 1 && _part <= 4); } int MBRBlockDevice::init() { + uint32_t val = core_util_atomic_incr_u32(&_init_ref_count, 1); + + if (val != 1) { + return BD_ERROR_OK; + } + int err = _bd->init(); if (err) { return err; @@ -252,6 +259,12 @@ int MBRBlockDevice::init() int MBRBlockDevice::deinit() { + uint32_t val = core_util_atomic_decr_u32(&_init_ref_count, 1); + + if (val) { + return BD_ERROR_OK; + } + return _bd->deinit(); } diff --git a/features/filesystem/bd/MBRBlockDevice.h b/features/filesystem/bd/MBRBlockDevice.h index c2ad5d5082..ef2e12233a 100644 --- a/features/filesystem/bd/MBRBlockDevice.h +++ b/features/filesystem/bd/MBRBlockDevice.h @@ -252,6 +252,7 @@ protected: bd_size_t _size; uint8_t _type; uint8_t _part; + uint32_t _init_ref_count; };