mirror of https://github.com/ARMmbed/mbed-os.git
Rationalise MemoryPool/Mail alloc APIs
alloc APIs were generally inconsistent - take the opportunity to align with
other APIs like Semaphore.
alloc -> try_alloc
alloc_for -> try_alloc_for
alloc_until -> try_alloc_until
In future the name `alloc` can be used for an untimed blocking
allocation.
pull/12901/head
parent
029109a2f0
commit
166ada084e
|
|
@ -23,10 +23,24 @@
|
|||
#error [NOT_SUPPORTED] MemoryPool test cases require a RTOS to run.
|
||||
#else
|
||||
|
||||
#define TEST_ASSERT_DURATION_WITHIN(delta, expected, actual) \
|
||||
do { \
|
||||
using ct = std::common_type_t<decltype(delta), decltype(expected), decltype(actual)>; \
|
||||
TEST_ASSERT_INT_WITHIN(ct(delta).count(), ct(expected).count(), ct(actual).count()); \
|
||||
} while (0)
|
||||
|
||||
#define TEST_ASSERT_TIME_POINT_WITHIN(delta, expected, actual) \
|
||||
do { \
|
||||
using ct_tp = std::common_type_t<decltype(expected), decltype(actual)>; \
|
||||
using ct = std::common_type_t<decltype(delta), ct_tp::duration>; \
|
||||
TEST_ASSERT_INT_WITHIN(ct(delta).count(), ct(expected.time_since_epoch()).count(), ct(actual.time_since_epoch()).count()); \
|
||||
} while (0)
|
||||
|
||||
using namespace utest::v1;
|
||||
using namespace std::chrono;
|
||||
|
||||
#define THREAD_STACK_SIZE 512
|
||||
#define TEST_TIMEOUT 50
|
||||
#define TEST_TIMEOUT 50ms
|
||||
|
||||
/* Enum used to select block allocation method. */
|
||||
typedef enum {
|
||||
|
|
@ -68,7 +82,7 @@ void comp_set(COMPLEX_TYPE *object, int a, char b, int c)
|
|||
object->c = c;
|
||||
}
|
||||
|
||||
/* Template for functional tests for alloc(), calloc() functions
|
||||
/* Template for functional tests for try_alloc(), try_calloc() functions
|
||||
* of MemoryPool object.
|
||||
*
|
||||
* Given MemoryPool object of the specified type and queue size has
|
||||
|
|
@ -89,9 +103,9 @@ void test_mem_pool_alloc_success(AllocType atype)
|
|||
for (i = 0; i < numOfEntries; i++) {
|
||||
/* Allocate memory block. */
|
||||
if (atype == ALLOC) {
|
||||
p_blocks[i] = mem_pool.alloc();
|
||||
p_blocks[i] = mem_pool.try_alloc();
|
||||
} else {
|
||||
p_blocks[i] = mem_pool.calloc();
|
||||
p_blocks[i] = mem_pool.try_calloc();
|
||||
}
|
||||
|
||||
/* Show that memory pool block has been allocated. */
|
||||
|
|
@ -112,7 +126,7 @@ void test_mem_pool_alloc_success(AllocType atype)
|
|||
}
|
||||
}
|
||||
|
||||
/* Template for functional tests for alloc(), calloc() functions
|
||||
/* Template for functional tests for try_alloc(), try_calloc() functions
|
||||
* of MemoryPool object.
|
||||
*
|
||||
* Complex memory pool block type is used.
|
||||
|
|
@ -135,9 +149,9 @@ void test_mem_pool_alloc_success_complex(AllocType atype)
|
|||
for (i = 0; i < numOfEntries; i++) {
|
||||
/* Allocate memory block. */
|
||||
if (atype == ALLOC) {
|
||||
p_blocks[i] = mem_pool.alloc();
|
||||
p_blocks[i] = mem_pool.try_alloc();
|
||||
} else {
|
||||
p_blocks[i] = mem_pool.calloc();
|
||||
p_blocks[i] = mem_pool.try_calloc();
|
||||
}
|
||||
|
||||
/* Show that memory pool block has been allocated. */
|
||||
|
|
@ -158,7 +172,7 @@ void test_mem_pool_alloc_success_complex(AllocType atype)
|
|||
}
|
||||
}
|
||||
|
||||
/* Template for functional tests for alloc(), calloc() functions
|
||||
/* Template for functional tests for try_alloc(), try_calloc() functions
|
||||
* of MemoryPool object.
|
||||
*
|
||||
* Given MemoryPool has already max number of blocks allocated from the pool.
|
||||
|
|
@ -177,9 +191,9 @@ void test_mem_pool_alloc_fail(AllocType atype)
|
|||
/* Allocate all available blocks. */
|
||||
for (i = 0; i < numOfEntries; i++) {
|
||||
if (atype == ALLOC) {
|
||||
p_blocks[i] = mem_pool.alloc();
|
||||
p_blocks[i] = mem_pool.try_alloc();
|
||||
} else {
|
||||
p_blocks[i] = mem_pool.calloc();
|
||||
p_blocks[i] = mem_pool.try_calloc();
|
||||
}
|
||||
|
||||
/* Show that memory pool block has been allocated. */
|
||||
|
|
@ -188,9 +202,9 @@ void test_mem_pool_alloc_fail(AllocType atype)
|
|||
|
||||
/* There are no more blocks available. Try to allocate another block. */
|
||||
if (atype == ALLOC) {
|
||||
p_extra_block = mem_pool.alloc();
|
||||
p_extra_block = mem_pool.try_alloc();
|
||||
} else {
|
||||
p_extra_block = mem_pool.calloc();
|
||||
p_extra_block = mem_pool.try_calloc();
|
||||
}
|
||||
|
||||
/* Show that memory pool block has NOT been allocated. */
|
||||
|
|
@ -216,9 +230,9 @@ void test_mem_pool_free_success(AllocType atype)
|
|||
/* Allocate all available blocks. */
|
||||
for (i = 0; i < numOfEntries; i++) {
|
||||
if (atype == ALLOC) {
|
||||
p_blocks[i] = mem_pool.alloc();
|
||||
p_blocks[i] = mem_pool.try_alloc();
|
||||
} else {
|
||||
p_blocks[i] = mem_pool.calloc();
|
||||
p_blocks[i] = mem_pool.try_calloc();
|
||||
}
|
||||
|
||||
/* Show that memory pool block has been allocated. */
|
||||
|
|
@ -234,7 +248,7 @@ void test_mem_pool_free_success(AllocType atype)
|
|||
}
|
||||
}
|
||||
|
||||
/* Template for functional tests for alloc(), calloc() functions
|
||||
/* Template for functional tests for try_alloc(), try_calloc() functions
|
||||
* of MemoryPool object.
|
||||
*
|
||||
* Basic memory pool block type is used.
|
||||
|
|
@ -256,9 +270,9 @@ void test_mem_pool_free_realloc_last(AllocType atype)
|
|||
/* Allocate all available blocks. */
|
||||
for (i = 0; i < numOfEntries; i++) {
|
||||
if (atype == ALLOC) {
|
||||
p_blocks[i] = mem_pool.alloc();
|
||||
p_blocks[i] = mem_pool.try_alloc();
|
||||
} else {
|
||||
p_blocks[i] = mem_pool.calloc();
|
||||
p_blocks[i] = mem_pool.try_calloc();
|
||||
}
|
||||
|
||||
/* Init block. */
|
||||
|
|
@ -276,9 +290,9 @@ void test_mem_pool_free_realloc_last(AllocType atype)
|
|||
|
||||
/* Try to allocate another block (one block is now available). */
|
||||
if (atype == ALLOC) {
|
||||
p_blocks[numOfEntries - 1] = mem_pool.alloc();
|
||||
p_blocks[numOfEntries - 1] = mem_pool.try_alloc();
|
||||
} else {
|
||||
p_blocks[numOfEntries - 1] = mem_pool.calloc();
|
||||
p_blocks[numOfEntries - 1] = mem_pool.try_calloc();
|
||||
}
|
||||
|
||||
/* Show that memory pool block has been now allocated. */
|
||||
|
|
@ -290,7 +304,7 @@ void test_mem_pool_free_realloc_last(AllocType atype)
|
|||
}
|
||||
}
|
||||
|
||||
/* Template for functional tests for alloc(), calloc() functions
|
||||
/* Template for functional tests for try_alloc(), try_calloc() functions
|
||||
* of MemoryPool object.
|
||||
*
|
||||
* Complex memory pool block type is used.
|
||||
|
|
@ -312,9 +326,9 @@ void test_mem_pool_free_realloc_last_complex(AllocType atype)
|
|||
/* Allocate all available blocks. */
|
||||
for (i = 0; i < numOfEntries; i++) {
|
||||
if (atype == ALLOC) {
|
||||
p_blocks[i] = mem_pool.alloc();
|
||||
p_blocks[i] = mem_pool.try_alloc();
|
||||
} else {
|
||||
p_blocks[i] = mem_pool.calloc();
|
||||
p_blocks[i] = mem_pool.try_calloc();
|
||||
}
|
||||
|
||||
/* Init block. */
|
||||
|
|
@ -332,9 +346,9 @@ void test_mem_pool_free_realloc_last_complex(AllocType atype)
|
|||
|
||||
/* Try to allocate another block (one block is now available). */
|
||||
if (atype == ALLOC) {
|
||||
p_blocks[numOfEntries - 1] = mem_pool.alloc();
|
||||
p_blocks[numOfEntries - 1] = mem_pool.try_alloc();
|
||||
} else {
|
||||
p_blocks[numOfEntries - 1] = mem_pool.calloc();
|
||||
p_blocks[numOfEntries - 1] = mem_pool.try_calloc();
|
||||
}
|
||||
|
||||
/* Show that memory pool block has been now allocated. */
|
||||
|
|
@ -346,7 +360,7 @@ void test_mem_pool_free_realloc_last_complex(AllocType atype)
|
|||
}
|
||||
}
|
||||
|
||||
/* Template for functional tests for alloc(), calloc() functions
|
||||
/* Template for functional tests for try_alloc(), try_calloc() functions
|
||||
* of MemoryPool object.
|
||||
*
|
||||
* Basic memory pool block type is used.
|
||||
|
|
@ -368,9 +382,9 @@ void test_mem_pool_free_realloc_first(AllocType atype)
|
|||
/* Allocate all available blocks. */
|
||||
for (i = 0; i < numOfEntries; i++) {
|
||||
if (atype == ALLOC) {
|
||||
p_blocks[i] = mem_pool.alloc();
|
||||
p_blocks[i] = mem_pool.try_alloc();
|
||||
} else {
|
||||
p_blocks[i] = mem_pool.calloc();
|
||||
p_blocks[i] = mem_pool.try_calloc();
|
||||
}
|
||||
|
||||
/* Init block. */
|
||||
|
|
@ -388,9 +402,9 @@ void test_mem_pool_free_realloc_first(AllocType atype)
|
|||
|
||||
/* Try to allocate another block (one block is now available). */
|
||||
if (atype == ALLOC) {
|
||||
p_blocks[0] = mem_pool.alloc();
|
||||
p_blocks[0] = mem_pool.try_alloc();
|
||||
} else {
|
||||
p_blocks[0] = mem_pool.calloc();
|
||||
p_blocks[0] = mem_pool.try_calloc();
|
||||
}
|
||||
|
||||
/* Show that memory pool block has been now allocated. */
|
||||
|
|
@ -402,7 +416,7 @@ void test_mem_pool_free_realloc_first(AllocType atype)
|
|||
}
|
||||
}
|
||||
|
||||
/* Template for functional tests for alloc(), calloc() functions
|
||||
/* Template for functional tests for try_alloc(), try_calloc() functions
|
||||
* of MemoryPool object.
|
||||
*
|
||||
* Complex memory pool block type is used.
|
||||
|
|
@ -424,9 +438,9 @@ void test_mem_pool_free_realloc_first_complex(AllocType atype)
|
|||
/* Allocate all available blocks. */
|
||||
for (i = 0; i < numOfEntries; i++) {
|
||||
if (atype == ALLOC) {
|
||||
p_blocks[i] = mem_pool.alloc();
|
||||
p_blocks[i] = mem_pool.try_alloc();
|
||||
} else {
|
||||
p_blocks[i] = mem_pool.calloc();
|
||||
p_blocks[i] = mem_pool.try_calloc();
|
||||
}
|
||||
|
||||
/* Init block. */
|
||||
|
|
@ -444,9 +458,9 @@ void test_mem_pool_free_realloc_first_complex(AllocType atype)
|
|||
|
||||
/* Try to allocate another block (one block is now available). */
|
||||
if (atype == ALLOC) {
|
||||
p_blocks[0] = mem_pool.alloc();
|
||||
p_blocks[0] = mem_pool.try_alloc();
|
||||
} else {
|
||||
p_blocks[0] = mem_pool.calloc();
|
||||
p_blocks[0] = mem_pool.try_calloc();
|
||||
}
|
||||
|
||||
/* Show that memory pool block has been now allocated. */
|
||||
|
|
@ -458,7 +472,7 @@ void test_mem_pool_free_realloc_first_complex(AllocType atype)
|
|||
}
|
||||
}
|
||||
|
||||
/* Test alloc timeout
|
||||
/* Test try_alloc_for/try_alloc_until timeout
|
||||
*
|
||||
* Given a pool with one slot for int data
|
||||
* When a thread tries to allocate two blocks with @ TEST_TIMEOUT timeout
|
||||
|
|
@ -471,18 +485,18 @@ void test_mem_pool_timeout()
|
|||
Timer timer;
|
||||
timer.start();
|
||||
|
||||
int *item = mem_pool.alloc_for(TEST_TIMEOUT);
|
||||
int *item = mem_pool.try_alloc_for(TEST_TIMEOUT);
|
||||
TEST_ASSERT_NOT_NULL(item);
|
||||
TEST_ASSERT_UINT32_WITHIN(TEST_TIMEOUT * 100, 0, timer.read_us());
|
||||
TEST_ASSERT_DURATION_WITHIN(TEST_TIMEOUT / 10, 0ms, timer.elapsed_time());
|
||||
|
||||
item = mem_pool.alloc_for(TEST_TIMEOUT);
|
||||
item = mem_pool.try_alloc_for(TEST_TIMEOUT);
|
||||
TEST_ASSERT_NULL(item);
|
||||
TEST_ASSERT_UINT32_WITHIN(TEST_TIMEOUT * 100, TEST_TIMEOUT * 1000, timer.read_us());
|
||||
TEST_ASSERT_DURATION_WITHIN(TEST_TIMEOUT / 10, TEST_TIMEOUT, timer.elapsed_time());
|
||||
|
||||
uint64_t end_time = Kernel::get_ms_count() + TEST_TIMEOUT;
|
||||
item = mem_pool.alloc_until(end_time);
|
||||
auto end_time = Kernel::Clock::now() + TEST_TIMEOUT;
|
||||
item = mem_pool.try_alloc_until(end_time);
|
||||
TEST_ASSERT_NULL(item);
|
||||
TEST_ASSERT_UINT64_WITHIN(TEST_TIMEOUT * 100, end_time, Kernel::get_ms_count());
|
||||
TEST_ASSERT_TIME_POINT_WITHIN(TEST_TIMEOUT / 10, end_time, Kernel::Clock::now());
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
|
@ -516,18 +530,18 @@ void test_mem_pool_waitforever()
|
|||
Timer timer;
|
||||
timer.start();
|
||||
|
||||
int *item = pool.alloc_for(osWaitForever);
|
||||
int *item = pool.try_alloc_for(Kernel::wait_for_u32_forever);
|
||||
TEST_ASSERT_NOT_NULL(item);
|
||||
TEST_ASSERT_UINT32_WITHIN(TEST_TIMEOUT * 100, 0, timer.read_us());
|
||||
TEST_ASSERT_DURATION_WITHIN(TEST_TIMEOUT / 10, 0ms, timer.elapsed_time());
|
||||
|
||||
struct free_capture to_free;
|
||||
to_free.pool = &pool;
|
||||
to_free.item = item;
|
||||
t.start(callback(free_int_item, &to_free));
|
||||
|
||||
item = pool.alloc_for(osWaitForever);
|
||||
item = pool.try_alloc_for(Kernel::wait_for_u32_forever);
|
||||
TEST_ASSERT_EQUAL(item, to_free.item);
|
||||
TEST_ASSERT_UINT32_WITHIN(TEST_TIMEOUT * 100, TEST_TIMEOUT * 1000, timer.read_us());
|
||||
TEST_ASSERT_DURATION_WITHIN(TEST_TIMEOUT / 10, TEST_TIMEOUT, timer.elapsed_time());
|
||||
|
||||
t.join();
|
||||
}
|
||||
|
|
@ -632,12 +646,12 @@ void test_mem_pool_alloc_fail_wrapper()
|
|||
}
|
||||
|
||||
Case cases[] = {
|
||||
Case("Test: alloc()/calloc() - success, 4 bytes b_type, q_size equal to 1.", test_mem_pool_alloc_success_wrapper<int, 1>),
|
||||
Case("Test: alloc()/calloc() - success, 4 bytes b_type, q_size equal to 3.", test_mem_pool_alloc_success_wrapper<int, 3>),
|
||||
Case("Test: alloc()/calloc() - success, 1 bytes b_type, q_size equal to 1.", test_mem_pool_alloc_success_wrapper<char, 1>),
|
||||
Case("Test: alloc()/calloc() - success, 1 bytes b_type, q_size equal to 3.", test_mem_pool_alloc_success_wrapper<char, 3>),
|
||||
Case("Test: alloc()/calloc() - success, complex b_type, q_size equal to 1.", test_mem_pool_alloc_success_complex_wrapper<COMPLEX_TYPE, 1>),
|
||||
Case("Test: alloc()/calloc() - success, complex b_type, q_size equal to 3.", test_mem_pool_alloc_success_complex_wrapper<COMPLEX_TYPE, 3>),
|
||||
Case("Test: try_alloc()/try_calloc() - success, 4 bytes b_type, q_size equal to 1.", test_mem_pool_alloc_success_wrapper<int, 1>),
|
||||
Case("Test: try_alloc()/try_calloc() - success, 4 bytes b_type, q_size equal to 3.", test_mem_pool_alloc_success_wrapper<int, 3>),
|
||||
Case("Test: try_alloc()/try_calloc() - success, 1 bytes b_type, q_size equal to 1.", test_mem_pool_alloc_success_wrapper<char, 1>),
|
||||
Case("Test: try_alloc()/try_calloc() - success, 1 bytes b_type, q_size equal to 3.", test_mem_pool_alloc_success_wrapper<char, 3>),
|
||||
Case("Test: try_alloc()/try_calloc() - success, complex b_type, q_size equal to 1.", test_mem_pool_alloc_success_complex_wrapper<COMPLEX_TYPE, 1>),
|
||||
Case("Test: try_alloc()/try_calloc() - success, complex b_type, q_size equal to 3.", test_mem_pool_alloc_success_complex_wrapper<COMPLEX_TYPE, 3>),
|
||||
|
||||
Case("Test: free() - success, 4 bytes b_type, q_size equal to 1.", test_mem_pool_free_success_wrapper<int, 1>),
|
||||
Case("Test: free() - success, 4 bytes b_type, q_size equal to 3.", test_mem_pool_free_success_wrapper<int, 3>),
|
||||
|
|
|
|||
|
|
@ -29,6 +29,13 @@
|
|||
#include "rtos.h"
|
||||
|
||||
using namespace utest::v1;
|
||||
using namespace std::chrono;
|
||||
|
||||
#define TEST_ASSERT_DURATION_WITHIN(delta, expected, actual) \
|
||||
do { \
|
||||
using ct = std::common_type_t<decltype(delta), decltype(expected), decltype(actual)>; \
|
||||
TEST_ASSERT_INT_WITHIN(ct(delta).count(), ct(expected).count(), ct(actual).count()); \
|
||||
} while (0)
|
||||
|
||||
#if defined(__CORTEX_M23) || defined(__CORTEX_M33)
|
||||
#define THREAD_STACK_SIZE 512
|
||||
|
|
@ -43,9 +50,9 @@ using namespace utest::v1;
|
|||
#define THREAD_1_ID 1
|
||||
#define THREAD_2_ID 2
|
||||
#define THREAD_3_ID 3
|
||||
#define QUEUE_PUT_DELAY_1 5
|
||||
#define QUEUE_PUT_DELAY_2 50
|
||||
#define QUEUE_PUT_DELAY_3 100
|
||||
#define QUEUE_PUT_DELAY_1 5ms
|
||||
#define QUEUE_PUT_DELAY_2 50ms
|
||||
#define QUEUE_PUT_DELAY_3 100ms
|
||||
#define DATA_BASE 100
|
||||
|
||||
|
||||
|
|
@ -55,27 +62,26 @@ typedef struct {
|
|||
} mail_t;
|
||||
|
||||
|
||||
template<uint8_t thread_id, uint32_t wait_ms, uint32_t send_count>
|
||||
void send_thread(Mail<mail_t, QUEUE_SIZE> *m)
|
||||
void send_thread(Mail<mail_t, QUEUE_SIZE> *m, uint8_t thread_id, milliseconds wait, uint32_t send_count)
|
||||
{
|
||||
uint32_t data = thread_id * DATA_BASE;
|
||||
|
||||
for (uint32_t i = 0; i < send_count; i++) {
|
||||
mail_t *mail = m->alloc();
|
||||
mail_t *mail = m->try_alloc();
|
||||
mail->thread_id = thread_id;
|
||||
mail->data = data++;
|
||||
m->put(mail);
|
||||
ThisThread::sleep_for(wait_ms);
|
||||
ThisThread::sleep_for(wait);
|
||||
}
|
||||
}
|
||||
|
||||
template<uint8_t thread_id, uint32_t queue_size, uint32_t wait_ms>
|
||||
void receive_thread(Mail<mail_t, queue_size> *m)
|
||||
template<uint32_t queue_size>
|
||||
void receive_thread(Mail<mail_t, queue_size> *m, uint8_t thread_id, milliseconds wait)
|
||||
{
|
||||
int result_counter = 0;
|
||||
uint32_t data = thread_id * DATA_BASE;
|
||||
|
||||
ThisThread::sleep_for(wait_ms);
|
||||
ThisThread::sleep_for(wait);
|
||||
for (uint32_t i = 0; i < queue_size; i++) {
|
||||
osEvent evt = m->get();
|
||||
if (evt.status == osEventMail) {
|
||||
|
|
@ -108,10 +114,10 @@ void test_single_thread_order(void)
|
|||
|
||||
// mail send thread creation
|
||||
Thread thread(osPriorityNormal, THREAD_STACK_SIZE);
|
||||
thread.start(callback(send_thread<THREAD_1_ID, QUEUE_PUT_DELAY_1, QUEUE_SIZE>, &mail_box));
|
||||
thread.start([&] { send_thread(&mail_box, THREAD_1_ID, QUEUE_PUT_DELAY_1, QUEUE_SIZE); });
|
||||
|
||||
// wait for some mail to be collected
|
||||
ThisThread::sleep_for(10);
|
||||
ThisThread::sleep_for(10ms);
|
||||
|
||||
for (uint32_t i = 0; i < QUEUE_SIZE; i++) {
|
||||
// mail receive (main thread)
|
||||
|
|
@ -148,12 +154,12 @@ void test_multi_thread_order(void)
|
|||
Thread thread1(osPriorityNormal, THREAD_STACK_SIZE);
|
||||
Thread thread2(osPriorityNormal, THREAD_STACK_SIZE);
|
||||
Thread thread3(osPriorityNormal, THREAD_STACK_SIZE);
|
||||
thread1.start(callback(send_thread<THREAD_1_ID, QUEUE_PUT_DELAY_1, 7>, &mail_box));
|
||||
thread2.start(callback(send_thread<THREAD_2_ID, QUEUE_PUT_DELAY_2, 5>, &mail_box));
|
||||
thread3.start(callback(send_thread<THREAD_3_ID, QUEUE_PUT_DELAY_3, 4>, &mail_box));
|
||||
thread1.start([&] { send_thread(&mail_box, THREAD_1_ID, QUEUE_PUT_DELAY_1, 7); });
|
||||
thread2.start([&] { send_thread(&mail_box, THREAD_2_ID, QUEUE_PUT_DELAY_2, 5); });
|
||||
thread3.start([&] { send_thread(&mail_box, THREAD_3_ID, QUEUE_PUT_DELAY_3, 4); });
|
||||
|
||||
// wait for some mail to be collected
|
||||
ThisThread::sleep_for(10);
|
||||
ThisThread::sleep_for(10ms);
|
||||
|
||||
for (uint32_t i = 0; i < QUEUE_SIZE; i++) {
|
||||
// mail receive (main thread)
|
||||
|
|
@ -191,30 +197,30 @@ void test_multi_thread_multi_mail_order(void)
|
|||
Thread thread1(osPriorityNormal, THREAD_STACK_SIZE);
|
||||
Thread thread2(osPriorityNormal, THREAD_STACK_SIZE);
|
||||
Thread thread3(osPriorityNormal, THREAD_STACK_SIZE);
|
||||
thread1.start(callback(receive_thread<THREAD_1_ID, 4, 0>, mail_box + 1));
|
||||
thread2.start(callback(receive_thread<THREAD_2_ID, 4, 10>, mail_box + 2));
|
||||
thread3.start(callback(receive_thread<THREAD_3_ID, 4, 100>, mail_box + 3));
|
||||
thread1.start([&] { receive_thread<4>(mail_box + 1, THREAD_1_ID, 0ms); });
|
||||
thread2.start([&] { receive_thread<4>(mail_box + 2, THREAD_2_ID, 10ms); });
|
||||
thread3.start([&] { receive_thread<4>(mail_box + 3, THREAD_3_ID, 100ms); });
|
||||
|
||||
for (uint32_t i = 0; i < 4; i++) {
|
||||
id = THREAD_1_ID;
|
||||
mail = mail_box[id].alloc();
|
||||
mail = mail_box[id].try_alloc();
|
||||
mail->thread_id = id;
|
||||
mail->data = data[id]++;
|
||||
mail_box[id].put(mail);
|
||||
|
||||
id = THREAD_2_ID;
|
||||
mail = mail_box[id].alloc();
|
||||
mail = mail_box[id].try_alloc();
|
||||
mail->thread_id = id;
|
||||
mail->data = data[id]++;
|
||||
mail_box[id].put(mail);
|
||||
|
||||
id = THREAD_3_ID;
|
||||
mail = mail_box[id].alloc();
|
||||
mail = mail_box[id].try_alloc();
|
||||
mail->thread_id = id;
|
||||
mail->data = data[id]++;
|
||||
mail_box[id].put(mail);
|
||||
|
||||
ThisThread::sleep_for(i * 10);
|
||||
ThisThread::sleep_for(i * 10ms);
|
||||
}
|
||||
|
||||
thread1.join();
|
||||
|
|
@ -238,7 +244,7 @@ void test_free_wrong()
|
|||
status = mail_box.free(mail);
|
||||
TEST_ASSERT_EQUAL(osErrorParameter, status);
|
||||
|
||||
mail = mail_box.alloc();
|
||||
mail = mail_box.try_alloc();
|
||||
TEST_ASSERT_NOT_EQUAL(NULL, mail);
|
||||
|
||||
mail = &data;
|
||||
|
|
@ -262,7 +268,7 @@ void test_free_null()
|
|||
status = mail_box.free(mail);
|
||||
TEST_ASSERT_EQUAL(osErrorParameter, status);
|
||||
|
||||
mail = mail_box.alloc();
|
||||
mail = mail_box.try_alloc();
|
||||
TEST_ASSERT_NOT_EQUAL(NULL, mail);
|
||||
|
||||
mail = NULL;
|
||||
|
|
@ -282,8 +288,8 @@ void test_get_empty_timeout()
|
|||
Timer timer;
|
||||
|
||||
timer.start();
|
||||
osEvent evt = mail_box.get(50);
|
||||
TEST_ASSERT_UINT32_WITHIN(5000, 50000, timer.read_us());
|
||||
osEvent evt = mail_box.get(50ms);
|
||||
TEST_ASSERT_DURATION_WITHIN(5ms, 50ms, timer.elapsed_time());
|
||||
TEST_ASSERT_EQUAL(osEventTimeout, evt.status);
|
||||
}
|
||||
|
||||
|
|
@ -297,7 +303,7 @@ void test_get_empty_no_timeout()
|
|||
{
|
||||
Mail<uint32_t, 4> mail_box;
|
||||
|
||||
osEvent evt = mail_box.get(0);
|
||||
osEvent evt = mail_box.get(0ms);
|
||||
TEST_ASSERT_EQUAL(osOK, evt.status);
|
||||
}
|
||||
|
||||
|
|
@ -316,14 +322,14 @@ void test_order(void)
|
|||
const int32_t TEST_VAL1 = 123;
|
||||
const int32_t TEST_VAL2 = 456;
|
||||
|
||||
int32_t *mail1 = mail_box.alloc();
|
||||
int32_t *mail1 = mail_box.try_alloc();
|
||||
TEST_ASSERT_NOT_EQUAL(NULL, mail1);
|
||||
|
||||
*mail1 = TEST_VAL1;
|
||||
status = mail_box.put(mail1);
|
||||
TEST_ASSERT_EQUAL(osOK, status);
|
||||
|
||||
int32_t *mail2 = mail_box.alloc();
|
||||
int32_t *mail2 = mail_box.try_alloc();
|
||||
TEST_ASSERT_NOT_EQUAL(NULL, mail2);
|
||||
|
||||
*mail2 = TEST_VAL2;
|
||||
|
|
@ -354,9 +360,9 @@ void test_order(void)
|
|||
/** Test Mail box max size limit
|
||||
|
||||
Given an Mail box with max size of 4 elements
|
||||
When call @a alloc four times it returns memory blocks
|
||||
When call @a try_alloc four times it returns memory blocks
|
||||
Then the memory blocks should be valid
|
||||
When call @a alloc one more time it returns memory blocks
|
||||
When call @a try_alloc one more time it returns memory blocks
|
||||
Then the memory blocks should be not valid (NULL - no memory available)
|
||||
*/
|
||||
void test_max_size()
|
||||
|
|
@ -366,23 +372,23 @@ void test_max_size()
|
|||
const uint32_t TEST_VAL = 123;
|
||||
|
||||
// 1 OK
|
||||
uint32_t *mail1 = mail_box.alloc();
|
||||
uint32_t *mail1 = mail_box.try_alloc();
|
||||
TEST_ASSERT_NOT_EQUAL(NULL, mail1);
|
||||
|
||||
// 2 OK
|
||||
uint32_t *mail2 = mail_box.alloc();
|
||||
uint32_t *mail2 = mail_box.try_alloc();
|
||||
TEST_ASSERT_NOT_EQUAL(NULL, mail2);
|
||||
|
||||
// 3 OK
|
||||
uint32_t *mail3 = mail_box.alloc();
|
||||
uint32_t *mail3 = mail_box.try_alloc();
|
||||
TEST_ASSERT_NOT_EQUAL(NULL, mail3);
|
||||
|
||||
// 4 OK
|
||||
uint32_t *mail4 = mail_box.alloc();
|
||||
uint32_t *mail4 = mail_box.try_alloc();
|
||||
TEST_ASSERT_NOT_EQUAL(NULL, mail4);
|
||||
|
||||
// 5 KO
|
||||
uint32_t *mail5 = mail_box.alloc();
|
||||
uint32_t *mail5 = mail_box.try_alloc();
|
||||
TEST_ASSERT_EQUAL(NULL, mail5);
|
||||
|
||||
|
||||
|
|
@ -412,7 +418,7 @@ void test_data_type(void)
|
|||
Mail<T, 4> mail_box;
|
||||
const T TEST_VAL = 123;
|
||||
|
||||
T *mail = mail_box.alloc();
|
||||
T *mail = mail_box.try_alloc();
|
||||
TEST_ASSERT_NOT_EQUAL(NULL, mail);
|
||||
|
||||
*mail = TEST_VAL;
|
||||
|
|
@ -430,17 +436,17 @@ void test_data_type(void)
|
|||
TEST_ASSERT_EQUAL(osOK, status);
|
||||
}
|
||||
|
||||
/** Test calloc - memory block allocation with resetting
|
||||
/** Test try_calloc - memory block allocation with resetting
|
||||
|
||||
Given an empty Mail box
|
||||
When call @a calloc it returns allocated memory block
|
||||
When call @a try_calloc it returns allocated memory block
|
||||
Then the memory block should be valid and filled with zeros
|
||||
*/
|
||||
void test_calloc()
|
||||
{
|
||||
Mail<uint32_t, 1> mail_box;
|
||||
|
||||
uint32_t *mail = mail_box.calloc();
|
||||
uint32_t *mail = mail_box.try_calloc();
|
||||
TEST_ASSERT_NOT_EQUAL(NULL, mail);
|
||||
TEST_ASSERT_EQUAL(0, *mail);
|
||||
}
|
||||
|
|
@ -455,7 +461,7 @@ void test_mail_empty()
|
|||
{
|
||||
Mail<mail_t, 1> m;
|
||||
|
||||
mail_t *mail = m.alloc();
|
||||
mail_t *mail = m.try_alloc();
|
||||
|
||||
TEST_ASSERT_EQUAL(true, m.empty());
|
||||
|
||||
|
|
@ -474,7 +480,7 @@ void test_mail_full()
|
|||
{
|
||||
Mail<mail_t, 1> m;
|
||||
|
||||
mail_t *mail = m.alloc();
|
||||
mail_t *mail = m.try_alloc();
|
||||
|
||||
TEST_ASSERT_EQUAL(false, m.full());
|
||||
|
||||
|
|
@ -490,7 +496,7 @@ utest::v1::status_t test_setup(const size_t number_of_cases)
|
|||
}
|
||||
|
||||
Case cases[] = {
|
||||
Case("Test calloc", test_calloc),
|
||||
Case("Test try_calloc", test_calloc),
|
||||
Case("Test message type uint8", test_data_type<uint8_t>),
|
||||
Case("Test message type uint16", test_data_type<uint16_t>),
|
||||
Case("Test message type uint32", test_data_type<uint32_t>),
|
||||
|
|
|
|||
62
rtos/Mail.h
62
rtos/Mail.h
|
|
@ -105,11 +105,25 @@ public:
|
|||
* @return Pointer to memory block that you can fill with mail or nullptr in case error.
|
||||
*
|
||||
* @note You may call this function from ISR context.
|
||||
* @note If blocking is required, use Mail::alloc_for or Mail::alloc_until
|
||||
* @note If blocking is required, use Mail::try_alloc_for or Mail::try_alloc_until
|
||||
* @deprecated Replaced with try_alloc. In future alloc() will be an untimed blocking call.
|
||||
*/
|
||||
MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Replaced with try_alloc. In future alloc() will be an untimed blocking call.")
|
||||
T *alloc(MBED_UNUSED uint32_t millisec = 0)
|
||||
{
|
||||
return _pool.alloc();
|
||||
return try_alloc();
|
||||
}
|
||||
|
||||
/** Allocate a memory block of type T, without blocking.
|
||||
*
|
||||
* @return Pointer to memory block that you can fill with mail or nullptr in case error.
|
||||
*
|
||||
* @note You may call this function from ISR context.
|
||||
* @note If blocking is required, use Mail::try_alloc_for or Mail::try_alloc_until
|
||||
*/
|
||||
T *try_alloc()
|
||||
{
|
||||
return _pool.try_alloc();
|
||||
}
|
||||
|
||||
/** Allocate a memory block of type T, optionally blocking.
|
||||
|
|
@ -120,9 +134,9 @@ public:
|
|||
*
|
||||
* @note You may call this function from ISR context if the millisec parameter is set to 0.
|
||||
*/
|
||||
T *alloc_for(Kernel::Clock::duration_u32 rel_time)
|
||||
T *try_alloc_for(Kernel::Clock::duration_u32 rel_time)
|
||||
{
|
||||
return _pool.alloc_for(rel_time);
|
||||
return _pool.try_alloc_for(rel_time);
|
||||
}
|
||||
|
||||
/** Allocate a memory block of type T, optionally blocking.
|
||||
|
|
@ -137,7 +151,7 @@ public:
|
|||
MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Pass a chrono duration, not an integer millisecond count. For example use `5s` rather than `5000`.")
|
||||
T *alloc_for(uint32_t millisec)
|
||||
{
|
||||
return alloc_for(std::chrono::duration<uint32_t, std::milli>(millisec));
|
||||
return try_alloc_for(std::chrono::duration<uint32_t, std::milli>(millisec));
|
||||
}
|
||||
|
||||
/** Allocate a memory block of type T, blocking.
|
||||
|
|
@ -152,9 +166,9 @@ public:
|
|||
* wait is <= 0x7fffffff milliseconds (~24 days). If the limit is exceeded,
|
||||
* the wait will time out earlier than specified.
|
||||
*/
|
||||
T *alloc_until(Kernel::Clock::time_point abs_time)
|
||||
T *try_alloc_until(Kernel::Clock::time_point abs_time)
|
||||
{
|
||||
return _pool.alloc_until(abs_time);
|
||||
return _pool.try_alloc_until(abs_time);
|
||||
}
|
||||
|
||||
/** Allocate a memory block of type T, blocking.
|
||||
|
|
@ -174,7 +188,7 @@ public:
|
|||
MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Pass a chrono time_point, not an integer millisecond count. For example use `Kernel::Clock::now() + 5s` rather than `Kernel::get_ms_count() + 5000`.")
|
||||
T *alloc_until(uint64_t millisec)
|
||||
{
|
||||
return alloc_until(Kernel::Clock::time_point(std::chrono::duration<uint64_t, std::milli>(millisec)));
|
||||
return try_alloc_until(Kernel::Clock::time_point(std::chrono::duration<uint64_t, std::milli>(millisec)));
|
||||
}
|
||||
|
||||
/** Allocate a memory block of type T, and set memory block to zero.
|
||||
|
|
@ -183,12 +197,26 @@ public:
|
|||
*
|
||||
* @return Pointer to memory block that you can fill with mail or nullptr in case error.
|
||||
*
|
||||
* @note You may call this function from ISR context if the millisec parameter is set to 0.
|
||||
* @note If blocking is required, use Mail::calloc_for or Mail::calloc_until
|
||||
* @note You may call this function from ISR context.
|
||||
* @note If blocking is required, use Mail::try_calloc_for or Mail::try_calloc_until
|
||||
* @deprecated Replaced with try_calloc. In future calloc() will be an untimed blocking call.
|
||||
*/
|
||||
MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Replaced with try_calloc. In future calloc() will be an untimed blocking call.")
|
||||
T *calloc(MBED_UNUSED uint32_t millisec = 0)
|
||||
{
|
||||
return _pool.calloc();
|
||||
return try_calloc();
|
||||
}
|
||||
|
||||
/** Allocate a memory block of type T, and set memory block to zero.
|
||||
*
|
||||
* @return Pointer to memory block that you can fill with mail or nullptr in case error.
|
||||
*
|
||||
* @note You may call this function from ISR context.
|
||||
* @note If blocking is required, use Mail::try_calloc_for or Mail::try_calloc_until
|
||||
*/
|
||||
T *try_calloc()
|
||||
{
|
||||
return _pool.try_calloc();
|
||||
}
|
||||
|
||||
/** Allocate a memory block of type T, optionally blocking, and set memory block to zero.
|
||||
|
|
@ -199,9 +227,9 @@ public:
|
|||
*
|
||||
* @note You may call this function from ISR context if the rel_time parameter is set to 0.
|
||||
*/
|
||||
T *calloc_for(Kernel::Clock::duration_u32 rel_time)
|
||||
T *try_calloc_for(Kernel::Clock::duration_u32 rel_time)
|
||||
{
|
||||
return _pool.alloc_for(rel_time);
|
||||
return _pool.try_calloc_for(rel_time);
|
||||
}
|
||||
|
||||
/** Allocate a memory block of type T, optionally blocking, and set memory block to zero.
|
||||
|
|
@ -216,7 +244,7 @@ public:
|
|||
MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Pass a chrono duration, not an integer millisecond count. For example use `5s` rather than `5000`.")
|
||||
T *calloc_for(uint32_t millisec)
|
||||
{
|
||||
return calloc_for(std::chrono::duration<uint32_t, std::milli>(millisec));
|
||||
return try_calloc_for(std::chrono::duration<uint32_t, std::milli>(millisec));
|
||||
}
|
||||
|
||||
/** Allocate a memory block of type T, blocking, and set memory block to zero.
|
||||
|
|
@ -231,9 +259,9 @@ public:
|
|||
* wait is <= 0x7fffffff milliseconds (~24 days). If the limit is exceeded,
|
||||
* the wait will time out earlier than specified.
|
||||
*/
|
||||
T *calloc_until(Kernel::Clock::time_point abs_time)
|
||||
T *try_calloc_until(Kernel::Clock::time_point abs_time)
|
||||
{
|
||||
return _pool.calloc_until(abs_time);
|
||||
return _pool.try_calloc_until(abs_time);
|
||||
}
|
||||
|
||||
/** Allocate a memory block of type T, blocking, and set memory block to zero.
|
||||
|
|
@ -253,7 +281,7 @@ public:
|
|||
MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Pass a chrono time_point, not an integer millisecond count. For example use `Kernel::Clock::now() + 5s` rather than `Kernel::get_ms_count() + 5000`.")
|
||||
T *calloc_until(uint64_t millisec)
|
||||
{
|
||||
return calloc_until(Kernel::Clock::time_point(std::chrono::duration<uint64_t, std::milli>(millisec)));
|
||||
return try_calloc_until(Kernel::Clock::time_point(std::chrono::duration<uint64_t, std::milli>(millisec)));
|
||||
}
|
||||
|
||||
/** Put a mail in the queue.
|
||||
|
|
|
|||
|
|
@ -88,10 +88,12 @@ public:
|
|||
@return address of the allocated memory block or nullptr in case of no memory available.
|
||||
|
||||
@note You may call this function from ISR context.
|
||||
@deprecated Replaced with try_alloc. In future alloc() will be an untimed blocking call.
|
||||
*/
|
||||
T *alloc(void)
|
||||
MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Replaced with try_alloc. In future alloc() will be an untimed blocking call.")
|
||||
T *alloc()
|
||||
{
|
||||
return (T *)osMemoryPoolAlloc(_id, 0);
|
||||
return try_alloc();
|
||||
}
|
||||
|
||||
/** Allocate a memory block from a memory pool, without blocking.
|
||||
|
|
@ -99,7 +101,7 @@ public:
|
|||
|
||||
@note You may call this function from ISR context.
|
||||
*/
|
||||
T *try_alloc(void)
|
||||
T *try_alloc()
|
||||
{
|
||||
return (T *)osMemoryPoolAlloc(_id, 0);
|
||||
}
|
||||
|
|
@ -123,7 +125,7 @@ public:
|
|||
|
||||
@note You may call this function from ISR context if the rel_time parameter is set to 0.
|
||||
*/
|
||||
T *alloc_for(Kernel::Clock::duration_u32 rel_time)
|
||||
T *try_alloc_for(Kernel::Clock::duration_u32 rel_time)
|
||||
{
|
||||
return (T *)osMemoryPoolAlloc(_id, rel_time.count());
|
||||
}
|
||||
|
|
@ -156,7 +158,7 @@ public:
|
|||
wait is <= 0x7fffffff milliseconds (~24 days). If the limit is exceeded,
|
||||
the wait will time out earlier than specified.
|
||||
*/
|
||||
T *alloc_until(Kernel::Clock::time_point abs_time)
|
||||
T *try_alloc_until(Kernel::Clock::time_point abs_time)
|
||||
{
|
||||
Kernel::Clock::time_point now = Kernel::Clock::now();
|
||||
Kernel::Clock::duration_u32 rel_time;
|
||||
|
|
@ -167,16 +169,28 @@ public:
|
|||
} else {
|
||||
rel_time = abs_time - now;
|
||||
}
|
||||
return alloc_for(rel_time);
|
||||
return try_alloc_for(rel_time);
|
||||
}
|
||||
/** Allocate a memory block from a memory pool, without blocking, and set memory block to zero.
|
||||
@return address of the allocated memory block or nullptr in case of no memory available.
|
||||
|
||||
@note You may call this function from ISR context.
|
||||
@deprecated Replaced with try_calloc. In future calloc() will be an untimed blocking call.
|
||||
*/
|
||||
T *calloc(void)
|
||||
MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Replaced with try_calloc. In future calloc() will be an untimed blocking call.")
|
||||
T *calloc()
|
||||
{
|
||||
T *item = alloc();
|
||||
return try_calloc();
|
||||
}
|
||||
|
||||
/** Allocate a memory block from a memory pool, without blocking, and set memory block to zero.
|
||||
@return address of the allocated memory block or nullptr in case of no memory available.
|
||||
|
||||
@note You may call this function from ISR context.
|
||||
*/
|
||||
T *try_calloc()
|
||||
{
|
||||
T *item = try_alloc();
|
||||
if (item != nullptr) {
|
||||
memset(item, 0, sizeof(T));
|
||||
}
|
||||
|
|
@ -202,7 +216,7 @@ public:
|
|||
|
||||
@note You may call this function from ISR context if the rel_time parameter is set to 0.
|
||||
*/
|
||||
T *calloc_for(Kernel::Clock::duration_u32 rel_time)
|
||||
T *try_calloc_for(Kernel::Clock::duration_u32 rel_time)
|
||||
{
|
||||
T *item = alloc_for(rel_time);
|
||||
if (item != nullptr) {
|
||||
|
|
@ -239,7 +253,7 @@ public:
|
|||
wait is <= 0x7fffffff milliseconds (~24 days). If the limit is exceeded,
|
||||
the wait will time out earlier than specified.
|
||||
*/
|
||||
T *calloc_until(Kernel::Clock::time_point abs_time)
|
||||
T *try_calloc_until(Kernel::Clock::time_point abs_time)
|
||||
{
|
||||
T *item = alloc_until(abs_time);
|
||||
if (item != nullptr) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue