Rtos API example

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /* mbed Microcontroller Library
00002  * Copyright (c) 2017 ARM Limited
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 #include "mbed.h"
00017 #include "greentea-client/test_env.h"
00018 #include "utest/utest.h"
00019 #include "unity/unity.h"
00020 
00021 
00022 #if defined(MBED_RTOS_SINGLE_THREAD)
00023   #error [NOT_SUPPORTED] test not supported
00024 #endif
00025 
00026 using utest::v1::Case;
00027 
00028 extern uint32_t mbed_heap_size;
00029 static const int test_timeout = 25;
00030 volatile bool thread_should_continue = true;
00031 #define NUM_THREADS         4
00032 #define THREAD_MALLOC_SIZE  100
00033 
00034 #if defined(__CORTEX_A9)
00035 #define THREAD_STACK_SIZE   DEFAULT_STACK_SIZE
00036 #else
00037 #define THREAD_STACK_SIZE   256
00038 #endif
00039 
00040 
00041 void task_using_malloc(void)
00042 {
00043     void *data = NULL;
00044 
00045     while (thread_should_continue) {
00046         // Repeatedly allocate and free memory
00047         data = malloc(THREAD_MALLOC_SIZE);
00048         TEST_ASSERT_NOT_NULL(data);
00049 
00050         // test whole allocated memory
00051         memset(data, 0, THREAD_MALLOC_SIZE);
00052 
00053         free(data);
00054     }
00055 }
00056 
00057 /** Test for multithreaded heap allocations
00058 
00059     Given multiple threads are started in parallel
00060     When each of the threads allocate memory
00061     Then the memory allocation succeed and @a malloc return valid memory
00062  */
00063 void test_multithread_allocation(void)
00064 {
00065     // static stack for threads to reduce heap usage on devices with small RAM
00066     // and eliminate run out of heap memory problem
00067     uint8_t stack[NUM_THREADS][THREAD_STACK_SIZE];
00068 
00069     bool thread_alloc_failure = false;
00070     Thread *thread_list[NUM_THREADS];
00071     int test_time = 20;
00072 
00073     // Allocate threads for the test
00074     for (int i = 0; i < NUM_THREADS; i++) {
00075         thread_list[i] = new Thread(osPriorityNormal, THREAD_STACK_SIZE, stack[i]);
00076         if (NULL == thread_list[i]) {
00077             thread_alloc_failure = true;
00078         } else {
00079             thread_list[i]->start(task_using_malloc);
00080         }
00081     }
00082 
00083     // Give the test time to run
00084     while (test_time--) {
00085         Thread::wait(1000);
00086     }
00087 
00088     // Join and delete all threads
00089     thread_should_continue = false;
00090     for (int i = 0; i < NUM_THREADS; i++) {
00091         if (NULL != thread_list[i]) {
00092             thread_list[i]->join();
00093             delete thread_list[i];
00094             thread_list[i] = NULL;
00095         }
00096     }
00097     TEST_ASSERT_FALSE(thread_alloc_failure);
00098 }
00099 
00100 /** Test for large heap allocation
00101 
00102     Given a heap of size mbed_heap_size
00103     When try to allocate memory of size mbed_heap_size/5 (20% of whole heap)
00104     Then the memory is allocated and @a malloc return valid memory
00105  */
00106 void test_big_allocation(void)
00107 {
00108     const uint32_t alloc_size = mbed_heap_size / 5;
00109     void *data = NULL;
00110 
00111     data = malloc(alloc_size);
00112     TEST_ASSERT_NOT_NULL(data);
00113 
00114     // test whole allocated memory
00115     memset(data, 0, alloc_size);
00116 
00117     free(data);
00118 }
00119 
00120 /** Test if allocation of zero size does not cause any undefined behaviour
00121 
00122     Given a heap
00123     When try to allocate memory of size 0
00124     Then the return value of @a malloc depends on the particular library implementation
00125      (NULL or smallest possible allocation) and no undefined behaviour happens
00126 
00127     @note If allocation size is zero, the return value depends on the particular library implementation
00128     (it may or may not be a null pointer), but the returned pointer shall not be dereferenced
00129  */
00130 void test_zero_allocation(void)
00131 {
00132     void *data = NULL;
00133 
00134     data = malloc(0);
00135     if(data != NULL) {
00136         free(data);
00137     }
00138     TEST_ASSERT_MESSAGE(true, "malloc(0) succeed - no undefined behaviour happens");
00139 }
00140 
00141 /** Test if free on NULL pointer does not cause any undefined behaviour
00142 
00143     Given a NULL pointer
00144     When try to free it
00145     Then the function @a free does nothing and no undefined behaviour happens
00146  */
00147 void test_null_free(void)
00148 {
00149     void *data = NULL;
00150     free(data);
00151 
00152     TEST_ASSERT_MESSAGE(true, "free(NULL) succeed - no undefined behaviour happens");
00153 }
00154 
00155 // Test cases
00156 Case cases[] = {
00157     Case("Test 0 size allocation", test_zero_allocation),
00158     Case("Test NULL pointer free", test_null_free),
00159     Case("Test multithreaded allocations", test_multithread_allocation),
00160     Case("Test large allocation", test_big_allocation)
00161 };
00162 
00163 utest::v1::status_t greentea_test_setup(const size_t number_of_cases)
00164 {
00165     GREENTEA_SETUP(test_timeout, "timing_drift_auto");
00166     return utest::v1::greentea_test_setup_handler(number_of_cases);
00167 }
00168 
00169 utest::v1::Specification specification(greentea_test_setup, cases);
00170 
00171 int main()
00172 {
00173     return !utest::v1::Harness::run(specification);
00174 }