diff --git a/TESTS/mbedmicro-rtos-mbed/MemoryPool/main.cpp b/TESTS/mbedmicro-rtos-mbed/MemoryPool/main.cpp index 5c828277ce8..58fdf1dbb81 100644 --- a/TESTS/mbedmicro-rtos-mbed/MemoryPool/main.cpp +++ b/TESTS/mbedmicro-rtos-mbed/MemoryPool/main.cpp @@ -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; \ + 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; \ + using ct = std::common_type_t; \ + 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), - Case("Test: alloc()/calloc() - success, 4 bytes b_type, q_size equal to 3.", test_mem_pool_alloc_success_wrapper), - Case("Test: alloc()/calloc() - success, 1 bytes b_type, q_size equal to 1.", test_mem_pool_alloc_success_wrapper), - Case("Test: alloc()/calloc() - success, 1 bytes b_type, q_size equal to 3.", test_mem_pool_alloc_success_wrapper), - Case("Test: alloc()/calloc() - success, complex b_type, q_size equal to 1.", test_mem_pool_alloc_success_complex_wrapper), - Case("Test: alloc()/calloc() - success, complex b_type, q_size equal to 3.", test_mem_pool_alloc_success_complex_wrapper), + Case("Test: try_alloc()/try_calloc() - success, 4 bytes b_type, q_size equal to 1.", test_mem_pool_alloc_success_wrapper), + Case("Test: try_alloc()/try_calloc() - success, 4 bytes b_type, q_size equal to 3.", test_mem_pool_alloc_success_wrapper), + Case("Test: try_alloc()/try_calloc() - success, 1 bytes b_type, q_size equal to 1.", test_mem_pool_alloc_success_wrapper), + Case("Test: try_alloc()/try_calloc() - success, 1 bytes b_type, q_size equal to 3.", test_mem_pool_alloc_success_wrapper), + Case("Test: try_alloc()/try_calloc() - success, complex b_type, q_size equal to 1.", test_mem_pool_alloc_success_complex_wrapper), + Case("Test: try_alloc()/try_calloc() - success, complex b_type, q_size equal to 3.", test_mem_pool_alloc_success_complex_wrapper), Case("Test: free() - success, 4 bytes b_type, q_size equal to 1.", test_mem_pool_free_success_wrapper), Case("Test: free() - success, 4 bytes b_type, q_size equal to 3.", test_mem_pool_free_success_wrapper), diff --git a/TESTS/mbedmicro-rtos-mbed/mail/main.cpp b/TESTS/mbedmicro-rtos-mbed/mail/main.cpp index 5bf0bf3d6d5..1c22f61ba5b 100644 --- a/TESTS/mbedmicro-rtos-mbed/mail/main.cpp +++ b/TESTS/mbedmicro-rtos-mbed/mail/main.cpp @@ -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; \ + 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,31 +62,29 @@ typedef struct { } mail_t; -template -void send_thread(Mail *m) +void send_thread(Mail *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 -void receive_thread(Mail *m) +template +void receive_thread(Mail *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) { - mail_t *mail = (mail_t *)evt.value.p; + mail_t *mail = m->try_get_for(Kernel::wait_for_u32_forever); + if (mail) { const uint8_t id = mail->thread_id; // verify thread id @@ -108,16 +113,15 @@ void test_single_thread_order(void) // mail send thread creation Thread thread(osPriorityNormal, THREAD_STACK_SIZE); - thread.start(callback(send_thread, &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) - osEvent evt = mail_box.get(); - if (evt.status == osEventMail) { - mail_t *mail = (mail_t *)evt.value.p; + mail_t *mail = mail_box.try_get_for(Kernel::wait_for_u32_forever); + if (mail) { const uint8_t id = mail->thread_id; // verify thread id @@ -148,18 +152,17 @@ 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, &mail_box)); - thread2.start(callback(send_thread, &mail_box)); - thread3.start(callback(send_thread, &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) - osEvent evt = mail_box.get(); - if (evt.status == osEventMail) { - mail_t *mail = (mail_t *)evt.value.p; + mail_t *mail = mail_box.try_get_for(Kernel::wait_for_u32_forever); + if (mail) { const uint8_t id = mail->thread_id; // verify thread id @@ -191,30 +194,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, mail_box + 1)); - thread2.start(callback(receive_thread, mail_box + 2)); - thread3.start(callback(receive_thread, 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 +241,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 +265,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; @@ -273,8 +276,8 @@ void test_free_null() /** Test get from empty mailbox with timeout set Given an empty mailbox - When @a get is called on the mailbox with timeout of 50 - Then mailbox returns status of osOK, but no data after specified amount of time + When @a try_get_for is called on the mailbox with timeout of 50ms + Then mailbox returns no data */ void test_get_empty_timeout() { @@ -282,23 +285,23 @@ void test_get_empty_timeout() Timer timer; timer.start(); - osEvent evt = mail_box.get(50); - TEST_ASSERT_UINT32_WITHIN(5000, 50000, timer.read_us()); - TEST_ASSERT_EQUAL(osEventTimeout, evt.status); + uint32_t *mail = mail_box.try_get_for(50ms); + TEST_ASSERT_DURATION_WITHIN(5ms, 50ms, timer.elapsed_time()); + TEST_ASSERT_NULL(mail); } /** Test get from empty mailbox with 0 timeout Given an empty mailbox - When @a get is called on the mailbox with timeout of 0 - Then mailbox returns status of osOK, but no data + When @a try_get is called on the mailbox + Then mailbox returns no data */ void test_get_empty_no_timeout() { Mail mail_box; - osEvent evt = mail_box.get(0); - TEST_ASSERT_EQUAL(osOK, evt.status); + uint32_t *mail = mail_box.try_get(); + TEST_ASSERT_NULL(mail); } /** Test mail order @@ -311,36 +314,29 @@ void test_get_empty_no_timeout() void test_order(void) { osStatus status; - osEvent evt; Mail mail_box; 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); + mail_box.put(mail1); - int32_t *mail2 = mail_box.alloc(); + int32_t *mail2 = mail_box.try_alloc(); TEST_ASSERT_NOT_EQUAL(NULL, mail2); *mail2 = TEST_VAL2; - status = mail_box.put(mail2); - TEST_ASSERT_EQUAL(osOK, status); - + mail_box.put(mail2); - evt = mail_box.get(); - TEST_ASSERT_EQUAL(evt.status, osEventMail); - mail1 = (int32_t *)evt.value.p; + mail1 = mail_box.try_get_for(Kernel::wait_for_u32_forever); + TEST_ASSERT_NOT_NULL(mail1); TEST_ASSERT_EQUAL(TEST_VAL1, *mail1); - evt = mail_box.get(); - TEST_ASSERT_EQUAL(evt.status, osEventMail); - - mail2 = (int32_t *)evt.value.p; + mail2 = mail_box.try_get_for(Kernel::wait_for_u32_forever); + TEST_ASSERT_NOT_NULL(mail2); TEST_ASSERT_EQUAL(TEST_VAL2, *mail2); @@ -354,35 +350,34 @@ 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() { osStatus status; Mail mail_box; - 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,17 +407,14 @@ void test_data_type(void) Mail 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; - status = mail_box.put(mail); - TEST_ASSERT_EQUAL(osOK, status); - - osEvent evt = mail_box.get(); - TEST_ASSERT_EQUAL(evt.status, osEventMail); + mail_box.put(mail); - mail = (T *)evt.value.p; + mail = mail_box.try_get_for(Kernel::wait_for_u32_forever); + TEST_ASSERT_NOT_NULL(mail); TEST_ASSERT_EQUAL(TEST_VAL, *mail); @@ -430,17 +422,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 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 +447,7 @@ void test_mail_empty() { Mail m; - mail_t *mail = m.alloc(); + mail_t *mail = m.try_alloc(); TEST_ASSERT_EQUAL(true, m.empty()); @@ -474,7 +466,7 @@ void test_mail_full() { Mail m; - mail_t *mail = m.alloc(); + mail_t *mail = m.try_alloc(); TEST_ASSERT_EQUAL(false, m.full()); @@ -490,7 +482,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), Case("Test message type uint16", test_data_type), Case("Test message type uint32", test_data_type), diff --git a/TESTS/mbedmicro-rtos-mbed/queue/main.cpp b/TESTS/mbedmicro-rtos-mbed/queue/main.cpp index 51ae05dadf3..822fa48a73c 100644 --- a/TESTS/mbedmicro-rtos-mbed/queue/main.cpp +++ b/TESTS/mbedmicro-rtos-mbed/queue/main.cpp @@ -38,44 +38,47 @@ using namespace std::chrono; } while (0) #define THREAD_STACK_SIZE 512 -#define TEST_UINT_MSG 0xDEADBEEF -#define TEST_UINT_MSG2 0xE1EE7 #define TEST_TIMEOUT 50ms +static uint32_t msg; +static uint32_t msg2; + void thread_put_uint_msg(Queue *q) { ThisThread::sleep_for(TEST_TIMEOUT); - osStatus stat = q->put((uint32_t *) TEST_UINT_MSG); - TEST_ASSERT_EQUAL(osOK, stat); + bool stat = q->try_put(&msg); + TEST_ASSERT_TRUE(stat); } void thread_get_uint_msg(Queue *q) { ThisThread::sleep_for(TEST_TIMEOUT); - osEvent evt = q->get(); - TEST_ASSERT_EQUAL(osEventMessage, evt.status); - TEST_ASSERT_EQUAL(TEST_UINT_MSG, evt.value.v); + uint32_t *v; + bool stat = q->try_get_for(Kernel::wait_for_u32_forever, &v); + TEST_ASSERT_TRUE(stat) + TEST_ASSERT_EQUAL(&msg, v); } -/** Test pass uint msg +/** Test pass msg Given a queue for uint32_t messages with one slot When a uin32_t value is inserted into the queue and a message is extracted from the queue Then the extracted message is the same as previously inserted message */ -void test_pass_uint() +void test_pass() { Queue q; - osStatus stat = q.put((uint32_t *)TEST_UINT_MSG); - TEST_ASSERT_EQUAL(osOK, stat); + bool stat = q.try_put(&msg); + TEST_ASSERT_TRUE(stat) - osEvent evt = q.get(); - TEST_ASSERT_EQUAL(osEventMessage, evt.status); - TEST_ASSERT_EQUAL(TEST_UINT_MSG, evt.value.v); + uint32_t *v; + stat = q.try_get_for(Kernel::wait_for_u32_forever, &v); + TEST_ASSERT_TRUE(stat) + TEST_ASSERT_EQUAL(&msg, v); } -/** Test pass uint msg twice +/** Test pass msg twice Given a queue for uint32_t messages with one slot When a uin32_t value is inserted into the queue @@ -84,56 +87,38 @@ void test_pass_uint() Then the extracted message is the same as previously inserted message for both iterations */ -void test_pass_uint_twice() +void test_pass_twice() { Queue q; - osStatus stat = q.put((uint32_t *)TEST_UINT_MSG); - TEST_ASSERT_EQUAL(osOK, stat); - - osEvent evt = q.get(); - TEST_ASSERT_EQUAL(osEventMessage, evt.status); - TEST_ASSERT_EQUAL(TEST_UINT_MSG, evt.value.v); - - stat = q.put((uint32_t *)TEST_UINT_MSG2); - TEST_ASSERT_EQUAL(osOK, stat); - - evt = q.get(); - TEST_ASSERT_EQUAL(osEventMessage, evt.status); - TEST_ASSERT_EQUAL(TEST_UINT_MSG2, evt.value.v); -} - -/** Test pass ptr msg + bool stat = q.try_put(&msg); + TEST_ASSERT_TRUE(stat); - Given a queue for pointers to uint32_t messages with one slot - When a pointer to an uint32_t is inserted into the queue - and a message is extracted from the queue - Then the extracted message is the same as previously inserted message - */ -void test_pass_ptr() -{ - Queue q; - uint32_t msg = TEST_UINT_MSG; + uint32_t *v; + stat = q.try_get_for(Kernel::wait_for_u32_forever, &v); + TEST_ASSERT_TRUE(stat); + TEST_ASSERT_EQUAL(&msg, v); - osStatus stat = q.put(&msg); - TEST_ASSERT_EQUAL(osOK, stat); + stat = q.try_put(&msg2); + TEST_ASSERT_TRUE(stat); - osEvent evt = q.get(); - TEST_ASSERT_EQUAL(osEventMessage, evt.status); - TEST_ASSERT_EQUAL(&msg, evt.value.p); + stat = q.try_get_for(Kernel::wait_for_u32_forever, &v); + TEST_ASSERT_TRUE(stat); + TEST_ASSERT_EQUAL(&msg2, v); } /** Test get from empty queue Given an empty queue for uint32_t values When @a get is called on the queue with timeout of 0 - Then queue returns status of osOK, but no data + Then queue returns status of false */ void test_get_empty_no_timeout() { Queue q; - osEvent evt = q.get(0ms); - TEST_ASSERT_EQUAL(osOK, evt.status); + uint32_t *v; + bool stat = q.try_get(&v); + TEST_ASSERT_FALSE(stat); } /** Test get from empty queue with timeout @@ -148,8 +133,9 @@ void test_get_empty_timeout() Timer timer; timer.start(); - osEvent evt = q.get(50ms); - TEST_ASSERT_EQUAL(osEventTimeout, evt.status); + uint32_t *v; + bool stat = q.try_get_for(50ms, &v); + TEST_ASSERT_FALSE(stat); TEST_ASSERT_DURATION_WITHIN(5ms, 50ms, timer.elapsed_time()); } @@ -171,9 +157,10 @@ void test_get_empty_wait_forever() Timer timer; timer.start(); - osEvent evt = q.get(); - TEST_ASSERT_EQUAL(osEventMessage, evt.status); - TEST_ASSERT_EQUAL(TEST_UINT_MSG, evt.value.v); + uint32_t *v; + bool stat = q.try_get_for(Kernel::wait_for_u32_forever, &v); + TEST_ASSERT_TRUE(stat); + TEST_ASSERT_EQUAL(&msg, v); TEST_ASSERT_DURATION_WITHIN(TEST_TIMEOUT / 10, TEST_TIMEOUT, timer.elapsed_time()); } @@ -181,37 +168,37 @@ void test_get_empty_wait_forever() * * Given a queue with one slot for uint32_t data * When a thread tries to insert two messages - * Then first operation succeeds and second fails with @a osErrorResource + * Then first operation succeeds and second fails */ void test_put_full_no_timeout() { Queue q; - osStatus stat = q.put((uint32_t *) TEST_UINT_MSG); - TEST_ASSERT_EQUAL(osOK, stat); + bool stat = q.try_put(&msg); + TEST_ASSERT_TRUE(stat); - stat = q.put((uint32_t *) TEST_UINT_MSG); - TEST_ASSERT_EQUAL(osErrorResource, stat); + stat = q.try_put(&msg); + TEST_ASSERT_FALSE(stat); } /** Test put full timeout * * Given a queue with one slot for uint32_t data * When a thread tries to insert two messages with @ TEST_TIMEOUT timeout - * Then first operation succeeds and second fails with @a osErrorTimeout + * Then first operation succeeds and second fails */ void test_put_full_timeout() { Queue q; - osStatus stat = q.put((uint32_t *) TEST_UINT_MSG, TEST_TIMEOUT); - TEST_ASSERT_EQUAL(osOK, stat); + bool stat = q.try_put_for(TEST_TIMEOUT, &msg); + TEST_ASSERT_TRUE(stat); Timer timer; timer.start(); - stat = q.put((uint32_t *) TEST_UINT_MSG, TEST_TIMEOUT); - TEST_ASSERT_EQUAL(osErrorTimeout, stat); + stat = q.try_put_for(TEST_TIMEOUT, &msg); + TEST_ASSERT_FALSE(stat); TEST_ASSERT_DURATION_WITHIN(TEST_TIMEOUT / 10, TEST_TIMEOUT, timer.elapsed_time()); } @@ -230,13 +217,13 @@ void test_put_full_waitforever() t.start(callback(thread_get_uint_msg, &q)); - osStatus stat = q.put((uint32_t *) TEST_UINT_MSG); - TEST_ASSERT_EQUAL(osOK, stat); + bool stat = q.try_put(&msg); + TEST_ASSERT_TRUE(stat); Timer timer; timer.start(); - stat = q.put((uint32_t *) TEST_UINT_MSG, Kernel::wait_for_u32_forever); - TEST_ASSERT_EQUAL(osOK, stat); + stat = q.try_put_for(Kernel::wait_for_u32_forever, &msg); + TEST_ASSERT_TRUE(stat); TEST_ASSERT_DURATION_WITHIN(TEST_TIMEOUT / 10, TEST_TIMEOUT, timer.elapsed_time()); t.join(); @@ -252,19 +239,20 @@ void test_msg_order() { Queue q; - osStatus stat = q.put((uint32_t *) TEST_UINT_MSG, TEST_TIMEOUT); - TEST_ASSERT_EQUAL(osOK, stat); + bool stat = q.try_put_for(TEST_TIMEOUT, &msg); + TEST_ASSERT_TRUE(stat); - stat = q.put((uint32_t *) TEST_UINT_MSG2, TEST_TIMEOUT); - TEST_ASSERT_EQUAL(osOK, stat); + stat = q.try_put_for(TEST_TIMEOUT, &msg2); + TEST_ASSERT_TRUE(stat); - osEvent evt = q.get(); - TEST_ASSERT_EQUAL(osEventMessage, evt.status); - TEST_ASSERT_EQUAL(TEST_UINT_MSG, evt.value.v); + uint32_t *v; + stat = q.try_get(&v); + TEST_ASSERT_TRUE(stat); + TEST_ASSERT_EQUAL(&msg, v); - evt = q.get(); - TEST_ASSERT_EQUAL(osEventMessage, evt.status); - TEST_ASSERT_EQUAL(TEST_UINT_MSG2, evt.value.v); + stat = q.try_get(&v); + TEST_ASSERT_TRUE(stat); + TEST_ASSERT_EQUAL(&msg2, v); } /** Test message priority @@ -277,19 +265,20 @@ void test_msg_prio() { Queue q; - osStatus stat = q.put((uint32_t *) TEST_UINT_MSG, TEST_TIMEOUT, 0); - TEST_ASSERT_EQUAL(osOK, stat); + bool stat = q.try_put_for(TEST_TIMEOUT, &msg, 0); + TEST_ASSERT_TRUE(stat); - stat = q.put((uint32_t *) TEST_UINT_MSG2, TEST_TIMEOUT, 1); - TEST_ASSERT_EQUAL(osOK, stat); + stat = q.try_put_for(TEST_TIMEOUT, &msg2, 1); + TEST_ASSERT_TRUE(stat); - osEvent evt = q.get(); - TEST_ASSERT_EQUAL(osEventMessage, evt.status); - TEST_ASSERT_EQUAL(TEST_UINT_MSG2, evt.value.v); + uint32_t *v; + stat = q.try_get(&v); + TEST_ASSERT_TRUE(stat); + TEST_ASSERT_EQUAL(&msg2, v); - evt = q.get(); - TEST_ASSERT_EQUAL(osEventMessage, evt.status); - TEST_ASSERT_EQUAL(TEST_UINT_MSG, evt.value.v); + stat = q.try_get(&v); + TEST_ASSERT_TRUE(stat); + TEST_ASSERT_EQUAL(&msg, v); } /** Test queue empty @@ -302,11 +291,11 @@ void test_queue_empty() { Queue q; - TEST_ASSERT_EQUAL(true, q.empty()); + TEST_ASSERT_TRUE(q.empty()); - q.put((uint32_t *) TEST_UINT_MSG, TEST_TIMEOUT, 1); + q.try_put_for(TEST_TIMEOUT, &msg, 1); - TEST_ASSERT_EQUAL(false, q.empty()); + TEST_ASSERT_FALSE(q.empty()); } /** Test queue empty @@ -319,11 +308,11 @@ void test_queue_full() { Queue q; - TEST_ASSERT_EQUAL(false, q.full()); + TEST_ASSERT_FALSE(q.full()); - q.put((uint32_t *) TEST_UINT_MSG, TEST_TIMEOUT, 1); + q.try_put_for(TEST_TIMEOUT, &msg, 1); - TEST_ASSERT_EQUAL(true, q.full()); + TEST_ASSERT_TRUE(q.full()); } utest::v1::status_t test_setup(const size_t number_of_cases) @@ -333,9 +322,8 @@ utest::v1::status_t test_setup(const size_t number_of_cases) } Case cases[] = { - Case("Test pass uint msg", test_pass_uint), - Case("Test pass uint msg twice", test_pass_uint_twice), - Case("Test pass ptr msg", test_pass_ptr), + Case("Test pass msg", test_pass), + Case("Test pass msg twice", test_pass_twice), Case("Test get from empty queue no timeout", test_get_empty_no_timeout), Case("Test get from empty queue timeout", test_get_empty_timeout), Case("Test get empty wait forever", test_get_empty_wait_forever), diff --git a/TESTS/mbedmicro-rtos-mbed/threads/main.cpp b/TESTS/mbedmicro-rtos-mbed/threads/main.cpp index b637ecc0d80..a96bf04f433 100644 --- a/TESTS/mbedmicro-rtos-mbed/threads/main.cpp +++ b/TESTS/mbedmicro-rtos-mbed/threads/main.cpp @@ -705,12 +705,12 @@ void test_msg_get() TEST_ASSERT_EQUAL(Thread::WaitingMessageGet, t.get_state()); - queue.put((int32_t *)0xE1EE7); + queue.try_put((int32_t *)0xE1EE7); } void test_msg_put_thread(Queue *queue) { - queue->put((int32_t *)0xDEADBEEF, Kernel::wait_for_u32_forever); + queue->try_put_for(Kernel::wait_for_u32_forever, (int32_t *)0xDEADBEEF); } @@ -729,7 +729,7 @@ void test_msg_put() Thread t(osPriorityNormal, THREAD_STACK_SIZE); Queue queue; - queue.put((int32_t *)0xE1EE7); + queue.try_put((int32_t *)0xE1EE7); t.start(callback(test_msg_put_thread, &queue)); diff --git a/rtos/Mail.h b/rtos/Mail.h index af9ce312e72..7929a17c7b8 100644 --- a/rtos/Mail.h +++ b/rtos/Mail.h @@ -33,6 +33,7 @@ #include "rtos/mbed_rtos1_types.h" #include "platform/mbed_toolchain.h" +#include "platform/mbed_assert.h" #include "platform/NonCopyable.h" #ifndef MBED_NO_GLOBAL_USING_DIRECTIVE @@ -105,11 +106,25 @@ class Mail : private mbed::NonCopyable > { * @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 +135,9 @@ class Mail : private mbed::NonCopyable > { * * @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 +152,7 @@ class Mail : private mbed::NonCopyable > { 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(millisec)); + return try_alloc_for(std::chrono::duration(millisec)); } /** Allocate a memory block of type T, blocking. @@ -152,9 +167,9 @@ class Mail : private mbed::NonCopyable > { * 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 +189,7 @@ class Mail : private mbed::NonCopyable > { 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(millisec))); + return try_alloc_until(Kernel::Clock::time_point(std::chrono::duration(millisec))); } /** Allocate a memory block of type T, and set memory block to zero. @@ -183,12 +198,26 @@ class Mail : private mbed::NonCopyable > { * * @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 +228,9 @@ class Mail : private mbed::NonCopyable > { * * @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 +245,7 @@ class Mail : private mbed::NonCopyable > { 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(millisec)); + return try_calloc_for(std::chrono::duration(millisec)); } /** Allocate a memory block of type T, blocking, and set memory block to zero. @@ -231,9 +260,9 @@ class Mail : private mbed::NonCopyable > { * 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 +282,7 @@ class Mail : private mbed::NonCopyable > { 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(millisec))); + return try_calloc_until(Kernel::Clock::time_point(std::chrono::duration(millisec))); } /** Put a mail in the queue. @@ -261,31 +290,19 @@ class Mail : private mbed::NonCopyable > { * @param mptr Memory block previously allocated with Mail::alloc or Mail::calloc. * * @return Status code that indicates the execution status of the function (osOK on success). + * See note. * * @note You may call this function from ISR context. + * @note As the mail should have already been allocated, and the memory pool is the same size + * as the queue, the put operation should always succeed, despite being implemented with + * Queue::try_put - there is room in the queue for every mail from the pool. Therefore + * use of the return value is deprecated, and the function will return void in future. */ osStatus put(T *mptr) { - return _queue.put(mptr); - } - - /** Get a mail from the queue. - * - * @param millisec Timeout value. - * - * @return Event that contains mail information or error code. - * @retval osEventMessage Message received. - * @retval osOK No mail is available (and no timeout was specified). - * @retval osEventTimeout No mail has arrived during the given timeout period. - * @retval osErrorParameter A parameter is invalid or outside of a permitted range. - * - * @note You may call this function from ISR context if the millisec parameter is set to 0. - * @deprecated Pass a chrono duration, not an integer millisecond count. For example use `5s` rather than `5000`. - */ - MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Pass a chrono duration, not an integer millisecond count. For example use `5s` rather than `5000`.") - osEvent get(uint32_t millisec) - { - return get(std::chrono::duration(millisec)); + bool ok = _queue.try_put(mptr); + MBED_ASSERT(ok); + return ok ? osOK : osErrorResource; } /** Get a mail from the queue. @@ -300,16 +317,46 @@ class Mail : private mbed::NonCopyable > { * @a osErrorParameter A parameter is invalid or outside of a permitted range. * * @note You may call this function from ISR context if the millisec parameter is set to 0. + * @deprecated Replaced with try_get and try_get_for. In future get will be an untimed blocking call. */ - osEvent get(Kernel::Clock::duration_u32 rel_time = Kernel::wait_for_u32_forever) + MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Replaced with try_get and try_get_for. In future get will be an untimed blocking call.") + osEvent get(uint32_t millisec = osWaitForever) { - osEvent evt = _queue.get(rel_time); + osEvent evt = _queue.get(millisec); if (evt.status == osEventMessage) { evt.status = osEventMail; } return evt; } + /** Get a mail from the queue. + * + * @return Pointer to received mail, or nullptr if none was received. + * + * @note You may call this function from ISR context. + */ + T *try_get() + { + T *mptr = nullptr; + _queue.try_get(&mptr); + return mptr; + } + + /** Get a mail from the queue. + * + * @param rel_time Timeout value or Kernel::wait_for_u32_forever. + * + * @return Pointer to received mail, or nullptr if none was received. + * + * @note You may call this function from ISR context if the millisec parameter is set to 0. + */ + T *try_get_for(Kernel::Clock::duration_u32 rel_time) + { + T *mptr = nullptr; + _queue.try_get_for(rel_time, &mptr); + return mptr; + } + /** Free a memory block from a mail. * * @param mptr Pointer to the memory block that was obtained with Mail::get. diff --git a/rtos/MemoryPool.h b/rtos/MemoryPool.h index 81456eddd6a..9b247d19622 100644 --- a/rtos/MemoryPool.h +++ b/rtos/MemoryPool.h @@ -88,10 +88,12 @@ class MemoryPool : private mbed::NonCopyable > { @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 @@ class MemoryPool : private mbed::NonCopyable > { @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 @@ class MemoryPool : private mbed::NonCopyable > { @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 @@ class MemoryPool : private mbed::NonCopyable > { 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 @@ class MemoryPool : private mbed::NonCopyable > { } 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. + */ + MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Replaced with try_calloc. In future calloc() will be an untimed blocking call.") + T *calloc() + { + 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 *calloc(void) + T *try_calloc() { - T *item = alloc(); + T *item = try_alloc(); if (item != nullptr) { memset(item, 0, sizeof(T)); } @@ -202,7 +216,7 @@ class MemoryPool : private mbed::NonCopyable > { @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 @@ class MemoryPool : private mbed::NonCopyable > { 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) { diff --git a/rtos/Queue.h b/rtos/Queue.h index a3a51983204..203d1227272 100644 --- a/rtos/Queue.h +++ b/rtos/Queue.h @@ -122,6 +122,27 @@ class Queue : private mbed::NonCopyable > { return osMessageQueueGetCount(_id); } + /** Inserts the given element to the end of the queue. + * + * This function puts the message pointed to by `data` into the queue. The + * parameter `prio` is used to sort the message according to their priority + * (higher numbers indicate higher priority) on insertion. + * + * The function does not block, and returns immediately if the queue is full. + * + * @param data Pointer to the element to insert into the queue. + * @param prio Priority of the operation or 0 in case of default. + * (default: 0) + * + * @return true if the element was inserted, false otherwise. + * + * @note You may call this function from ISR context. + */ + bool try_put(T *data, uint8_t prio = 0) + { + return try_put_for(Kernel::Clock::duration_u32::zero(), data, prio); + } + /** Inserts the given element to the end of the queue. * * This function puts the message pointed to by `data` into the queue. The @@ -133,34 +154,27 @@ class Queue : private mbed::NonCopyable > { * queue. * * The parameter `rel_time` can have the following values: - * - When the duration is 0 (the default), the function returns instantly. + * - When the duration is 0, the function returns instantly. You could use + * `try_put` instead. * - When the duration is Kernel::wait_for_u32_forever, the function waits for an * infinite time. * - For all other values, the function waits for the given duration. * + * @param rel_time Timeout for the operation to be executed. * @param data Pointer to the element to insert into the queue. - * @param rel_time Timeout for the operation to be executed, or 0 in case - * of no timeout. (default: 0) * @param prio Priority of the operation or 0 in case of default. * (default: 0) * - * @return Status code that indicates the execution status of the function: - * @a osOK The message has been successfully inserted - * into the queue. - * @a osErrorTimeout The message could not be inserted into the - * queue in the given time. - * @a osErrorResource The message could not be inserted because - * the queue is full. - * @a osErrorParameter Internal error or nonzero timeout specified - * in an ISR. + * @return true if the element was inserted, false otherwise. * * @note You may call this function from ISR context if the rel_time * parameter is set to 0. * */ - osStatus put(T *data, Kernel::Clock::duration_u32 rel_time = Kernel::Clock::duration_u32::zero(), uint8_t prio = 0) + bool try_put_for(Kernel::Clock::duration_u32 rel_time, T *data, uint8_t prio = 0) { - return osMessageQueuePut(_id, &data, prio, rel_time.count()); + osStatus status = osMessageQueuePut(_id, &data, prio, rel_time.count()); + return status == osOK; } /** Inserts the given element to the end of the queue. @@ -198,25 +212,43 @@ class Queue : private mbed::NonCopyable > { * * @note You may call this function from ISR context if the millisec * parameter is set to 0. - * @deprecated Pass a chrono duration, not an integer millisecond count. For example use `5s` rather than `5000`. + * @deprecated Replaced with try_put and try_put_for. In future put will be an untimed blocking call. + */ + MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Replaced with try_put and try_put_for. In future put will be an untimed blocking call.") + osStatus put(T *data, uint32_t millisec = 0, uint8_t prio = 0) + { + return osMessageQueuePut(_id, &data, prio, millisec); + } + + /** Get a message from the queue. + * + * This function retrieves a message from the queue. The message is stored + * in the location pointed to be the parameter `data_out`. + * + * The function does not block, and returns immediately if the queue is empty. + * + * @param[out] data_out Pointer to location to write the element retrieved from the queue. + * + * @return true if an element was received and written to data_out. + * + * @note You may call this function from ISR context. */ - MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Pass a chrono duration, not an integer millisecond count. For example use `5s` rather than `5000`.") - osStatus put(T *data, uint32_t millisec, uint8_t prio = 0) + bool try_get(T **data_out) { - return put(data, std::chrono::duration(millisec), prio); + return try_get_for(Kernel::Clock::duration_u32::zero(), data_out); } /** Get a message or wait for a message from the queue. * * This function retrieves a message from the queue. The message is stored - * in the value field of the returned `osEvent` object. + * in the location pointed to be the parameter `data_out`. * * The timeout specified by the parameter `rel_time` specifies how long the * function waits to retrieve the message from the queue. * * The timeout parameter can have the following values: * - When the timeout is 0, the function returns instantly. - * - When the timeout is Kernel::wait_for_u32_forever (default), the function waits + * - When the timeout is Kernel::wait_for_u32_forever, the function waits * infinite time until the message is retrieved. * - When the timeout is any other value, the function waits for the * specified time before returning a timeout error. @@ -226,46 +258,17 @@ class Queue : private mbed::NonCopyable > { * (FIFO) order. * * @param rel_time Timeout value. - * (default: Kernel::wait_for_u32_forever). + * @param[out] data_out Pointer to location to write the element retrieved from the queue. * - * @return Event information that includes the message in event. Message - * value and the status code in event.status: - * @a osEventMessage Message successfully received. - * @a osOK No message is available in the queue, and no - * timeout was specified. - * @a osEventTimeout No message was received before a timeout - * event occurred. - * @a osErrorParameter A parameter is invalid or outside of a - * permitted range. + * @return true if an element was received and written to data_out. * * @note You may call this function from ISR context if the rel_time * parameter is set to 0. */ - osEvent get(Kernel::Clock::duration_u32 rel_time = Kernel::wait_for_u32_forever) + bool try_get_for(Kernel::Clock::duration_u32 rel_time, T **data_out) { - osEvent event; - T *data = nullptr; - osStatus_t res = osMessageQueueGet(_id, &data, nullptr, rel_time.count()); - - switch (res) { - case osOK: - event.status = (osStatus)osEventMessage; - event.value.p = data; - break; - case osErrorResource: - event.status = osOK; - break; - case osErrorTimeout: - event.status = (osStatus)osEventTimeout; - break; - case osErrorParameter: - default: - event.status = osErrorParameter; - break; - } - event.def.message_id = _id; - - return event; + osStatus status = osMessageQueueGet(_id, data_out, nullptr, rel_time.count()); + return status == osOK; } /** Get a message or wait for a message from the queue. @@ -301,12 +304,34 @@ class Queue : private mbed::NonCopyable > { * * @note You may call this function from ISR context if the millisec * parameter is set to 0. - * @deprecated Pass a chrono duration, not an integer millisecond count. For example use `5s` rather than `5000`. + * @deprecated Replaced with try_get and try_get_for. In future get will be an untimed blocking call. */ - MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Pass a chrono duration, not an integer millisecond count. For example use `5s` rather than `5000`.") - osEvent get(uint32_t millisec) + MBED_DEPRECATED_SINCE("mbed-os-6.0.0", "Replaced with try_get and try_get_for. In future get will be an untimed blocking call.") + osEvent get(uint32_t millisec = osWaitForever) { - return get(std::chrono::duration(millisec)); + osEvent event; + T *data = nullptr; + osStatus_t res = osMessageQueueGet(_id, &data, nullptr, millisec); + + switch (res) { + case osOK: + event.status = (osStatus)osEventMessage; + event.value.p = data; + break; + case osErrorResource: + event.status = osOK; + break; + case osErrorTimeout: + event.status = (osStatus)osEventTimeout; + break; + case osErrorParameter: + default: + event.status = osErrorParameter; + break; + } + event.def.message_id = _id; + + return event; } private: osMessageQueueId_t _id;