Rtos API example

Committer:
marcozecchini
Date:
Sat Feb 23 12:13:36 2019 +0000
Revision:
0:9fca2b23d0ba
final commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
marcozecchini 0:9fca2b23d0ba 1 /* mbed Microcontroller Library
marcozecchini 0:9fca2b23d0ba 2 * Copyright (c) 2017 ARM Limited
marcozecchini 0:9fca2b23d0ba 3 *
marcozecchini 0:9fca2b23d0ba 4 * Licensed under the Apache License, Version 2.0 (the "License");
marcozecchini 0:9fca2b23d0ba 5 * you may not use this file except in compliance with the License.
marcozecchini 0:9fca2b23d0ba 6 * You may obtain a copy of the License at
marcozecchini 0:9fca2b23d0ba 7 *
marcozecchini 0:9fca2b23d0ba 8 * http://www.apache.org/licenses/LICENSE-2.0
marcozecchini 0:9fca2b23d0ba 9 *
marcozecchini 0:9fca2b23d0ba 10 * Unless required by applicable law or agreed to in writing, software
marcozecchini 0:9fca2b23d0ba 11 * distributed under the License is distributed on an "AS IS" BASIS,
marcozecchini 0:9fca2b23d0ba 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
marcozecchini 0:9fca2b23d0ba 13 * See the License for the specific language governing permissions and
marcozecchini 0:9fca2b23d0ba 14 * limitations under the License.
marcozecchini 0:9fca2b23d0ba 15 */
marcozecchini 0:9fca2b23d0ba 16 #include "mbed.h"
marcozecchini 0:9fca2b23d0ba 17 #include "greentea-client/test_env.h"
marcozecchini 0:9fca2b23d0ba 18 #include "utest/utest.h"
marcozecchini 0:9fca2b23d0ba 19 #include "unity/unity.h"
marcozecchini 0:9fca2b23d0ba 20
marcozecchini 0:9fca2b23d0ba 21
marcozecchini 0:9fca2b23d0ba 22 #if defined(MBED_RTOS_SINGLE_THREAD)
marcozecchini 0:9fca2b23d0ba 23 #error [NOT_SUPPORTED] test not supported
marcozecchini 0:9fca2b23d0ba 24 #endif
marcozecchini 0:9fca2b23d0ba 25
marcozecchini 0:9fca2b23d0ba 26 using utest::v1::Case;
marcozecchini 0:9fca2b23d0ba 27
marcozecchini 0:9fca2b23d0ba 28 extern uint32_t mbed_heap_size;
marcozecchini 0:9fca2b23d0ba 29 static const int test_timeout = 25;
marcozecchini 0:9fca2b23d0ba 30 volatile bool thread_should_continue = true;
marcozecchini 0:9fca2b23d0ba 31 #define NUM_THREADS 4
marcozecchini 0:9fca2b23d0ba 32 #define THREAD_MALLOC_SIZE 100
marcozecchini 0:9fca2b23d0ba 33
marcozecchini 0:9fca2b23d0ba 34 #if defined(__CORTEX_A9)
marcozecchini 0:9fca2b23d0ba 35 #define THREAD_STACK_SIZE DEFAULT_STACK_SIZE
marcozecchini 0:9fca2b23d0ba 36 #else
marcozecchini 0:9fca2b23d0ba 37 #define THREAD_STACK_SIZE 256
marcozecchini 0:9fca2b23d0ba 38 #endif
marcozecchini 0:9fca2b23d0ba 39
marcozecchini 0:9fca2b23d0ba 40
marcozecchini 0:9fca2b23d0ba 41 void task_using_malloc(void)
marcozecchini 0:9fca2b23d0ba 42 {
marcozecchini 0:9fca2b23d0ba 43 void *data = NULL;
marcozecchini 0:9fca2b23d0ba 44
marcozecchini 0:9fca2b23d0ba 45 while (thread_should_continue) {
marcozecchini 0:9fca2b23d0ba 46 // Repeatedly allocate and free memory
marcozecchini 0:9fca2b23d0ba 47 data = malloc(THREAD_MALLOC_SIZE);
marcozecchini 0:9fca2b23d0ba 48 TEST_ASSERT_NOT_NULL(data);
marcozecchini 0:9fca2b23d0ba 49
marcozecchini 0:9fca2b23d0ba 50 // test whole allocated memory
marcozecchini 0:9fca2b23d0ba 51 memset(data, 0, THREAD_MALLOC_SIZE);
marcozecchini 0:9fca2b23d0ba 52
marcozecchini 0:9fca2b23d0ba 53 free(data);
marcozecchini 0:9fca2b23d0ba 54 }
marcozecchini 0:9fca2b23d0ba 55 }
marcozecchini 0:9fca2b23d0ba 56
marcozecchini 0:9fca2b23d0ba 57 /** Test for multithreaded heap allocations
marcozecchini 0:9fca2b23d0ba 58
marcozecchini 0:9fca2b23d0ba 59 Given multiple threads are started in parallel
marcozecchini 0:9fca2b23d0ba 60 When each of the threads allocate memory
marcozecchini 0:9fca2b23d0ba 61 Then the memory allocation succeed and @a malloc return valid memory
marcozecchini 0:9fca2b23d0ba 62 */
marcozecchini 0:9fca2b23d0ba 63 void test_multithread_allocation(void)
marcozecchini 0:9fca2b23d0ba 64 {
marcozecchini 0:9fca2b23d0ba 65 // static stack for threads to reduce heap usage on devices with small RAM
marcozecchini 0:9fca2b23d0ba 66 // and eliminate run out of heap memory problem
marcozecchini 0:9fca2b23d0ba 67 uint8_t stack[NUM_THREADS][THREAD_STACK_SIZE];
marcozecchini 0:9fca2b23d0ba 68
marcozecchini 0:9fca2b23d0ba 69 bool thread_alloc_failure = false;
marcozecchini 0:9fca2b23d0ba 70 Thread *thread_list[NUM_THREADS];
marcozecchini 0:9fca2b23d0ba 71 int test_time = 20;
marcozecchini 0:9fca2b23d0ba 72
marcozecchini 0:9fca2b23d0ba 73 // Allocate threads for the test
marcozecchini 0:9fca2b23d0ba 74 for (int i = 0; i < NUM_THREADS; i++) {
marcozecchini 0:9fca2b23d0ba 75 thread_list[i] = new Thread(osPriorityNormal, THREAD_STACK_SIZE, stack[i]);
marcozecchini 0:9fca2b23d0ba 76 if (NULL == thread_list[i]) {
marcozecchini 0:9fca2b23d0ba 77 thread_alloc_failure = true;
marcozecchini 0:9fca2b23d0ba 78 } else {
marcozecchini 0:9fca2b23d0ba 79 thread_list[i]->start(task_using_malloc);
marcozecchini 0:9fca2b23d0ba 80 }
marcozecchini 0:9fca2b23d0ba 81 }
marcozecchini 0:9fca2b23d0ba 82
marcozecchini 0:9fca2b23d0ba 83 // Give the test time to run
marcozecchini 0:9fca2b23d0ba 84 while (test_time--) {
marcozecchini 0:9fca2b23d0ba 85 Thread::wait(1000);
marcozecchini 0:9fca2b23d0ba 86 }
marcozecchini 0:9fca2b23d0ba 87
marcozecchini 0:9fca2b23d0ba 88 // Join and delete all threads
marcozecchini 0:9fca2b23d0ba 89 thread_should_continue = false;
marcozecchini 0:9fca2b23d0ba 90 for (int i = 0; i < NUM_THREADS; i++) {
marcozecchini 0:9fca2b23d0ba 91 if (NULL != thread_list[i]) {
marcozecchini 0:9fca2b23d0ba 92 thread_list[i]->join();
marcozecchini 0:9fca2b23d0ba 93 delete thread_list[i];
marcozecchini 0:9fca2b23d0ba 94 thread_list[i] = NULL;
marcozecchini 0:9fca2b23d0ba 95 }
marcozecchini 0:9fca2b23d0ba 96 }
marcozecchini 0:9fca2b23d0ba 97 TEST_ASSERT_FALSE(thread_alloc_failure);
marcozecchini 0:9fca2b23d0ba 98 }
marcozecchini 0:9fca2b23d0ba 99
marcozecchini 0:9fca2b23d0ba 100 /** Test for large heap allocation
marcozecchini 0:9fca2b23d0ba 101
marcozecchini 0:9fca2b23d0ba 102 Given a heap of size mbed_heap_size
marcozecchini 0:9fca2b23d0ba 103 When try to allocate memory of size mbed_heap_size/5 (20% of whole heap)
marcozecchini 0:9fca2b23d0ba 104 Then the memory is allocated and @a malloc return valid memory
marcozecchini 0:9fca2b23d0ba 105 */
marcozecchini 0:9fca2b23d0ba 106 void test_big_allocation(void)
marcozecchini 0:9fca2b23d0ba 107 {
marcozecchini 0:9fca2b23d0ba 108 const uint32_t alloc_size = mbed_heap_size / 5;
marcozecchini 0:9fca2b23d0ba 109 void *data = NULL;
marcozecchini 0:9fca2b23d0ba 110
marcozecchini 0:9fca2b23d0ba 111 data = malloc(alloc_size);
marcozecchini 0:9fca2b23d0ba 112 TEST_ASSERT_NOT_NULL(data);
marcozecchini 0:9fca2b23d0ba 113
marcozecchini 0:9fca2b23d0ba 114 // test whole allocated memory
marcozecchini 0:9fca2b23d0ba 115 memset(data, 0, alloc_size);
marcozecchini 0:9fca2b23d0ba 116
marcozecchini 0:9fca2b23d0ba 117 free(data);
marcozecchini 0:9fca2b23d0ba 118 }
marcozecchini 0:9fca2b23d0ba 119
marcozecchini 0:9fca2b23d0ba 120 /** Test if allocation of zero size does not cause any undefined behaviour
marcozecchini 0:9fca2b23d0ba 121
marcozecchini 0:9fca2b23d0ba 122 Given a heap
marcozecchini 0:9fca2b23d0ba 123 When try to allocate memory of size 0
marcozecchini 0:9fca2b23d0ba 124 Then the return value of @a malloc depends on the particular library implementation
marcozecchini 0:9fca2b23d0ba 125 (NULL or smallest possible allocation) and no undefined behaviour happens
marcozecchini 0:9fca2b23d0ba 126
marcozecchini 0:9fca2b23d0ba 127 @note If allocation size is zero, the return value depends on the particular library implementation
marcozecchini 0:9fca2b23d0ba 128 (it may or may not be a null pointer), but the returned pointer shall not be dereferenced
marcozecchini 0:9fca2b23d0ba 129 */
marcozecchini 0:9fca2b23d0ba 130 void test_zero_allocation(void)
marcozecchini 0:9fca2b23d0ba 131 {
marcozecchini 0:9fca2b23d0ba 132 void *data = NULL;
marcozecchini 0:9fca2b23d0ba 133
marcozecchini 0:9fca2b23d0ba 134 data = malloc(0);
marcozecchini 0:9fca2b23d0ba 135 if(data != NULL) {
marcozecchini 0:9fca2b23d0ba 136 free(data);
marcozecchini 0:9fca2b23d0ba 137 }
marcozecchini 0:9fca2b23d0ba 138 TEST_ASSERT_MESSAGE(true, "malloc(0) succeed - no undefined behaviour happens");
marcozecchini 0:9fca2b23d0ba 139 }
marcozecchini 0:9fca2b23d0ba 140
marcozecchini 0:9fca2b23d0ba 141 /** Test if free on NULL pointer does not cause any undefined behaviour
marcozecchini 0:9fca2b23d0ba 142
marcozecchini 0:9fca2b23d0ba 143 Given a NULL pointer
marcozecchini 0:9fca2b23d0ba 144 When try to free it
marcozecchini 0:9fca2b23d0ba 145 Then the function @a free does nothing and no undefined behaviour happens
marcozecchini 0:9fca2b23d0ba 146 */
marcozecchini 0:9fca2b23d0ba 147 void test_null_free(void)
marcozecchini 0:9fca2b23d0ba 148 {
marcozecchini 0:9fca2b23d0ba 149 void *data = NULL;
marcozecchini 0:9fca2b23d0ba 150 free(data);
marcozecchini 0:9fca2b23d0ba 151
marcozecchini 0:9fca2b23d0ba 152 TEST_ASSERT_MESSAGE(true, "free(NULL) succeed - no undefined behaviour happens");
marcozecchini 0:9fca2b23d0ba 153 }
marcozecchini 0:9fca2b23d0ba 154
marcozecchini 0:9fca2b23d0ba 155 // Test cases
marcozecchini 0:9fca2b23d0ba 156 Case cases[] = {
marcozecchini 0:9fca2b23d0ba 157 Case("Test 0 size allocation", test_zero_allocation),
marcozecchini 0:9fca2b23d0ba 158 Case("Test NULL pointer free", test_null_free),
marcozecchini 0:9fca2b23d0ba 159 Case("Test multithreaded allocations", test_multithread_allocation),
marcozecchini 0:9fca2b23d0ba 160 Case("Test large allocation", test_big_allocation)
marcozecchini 0:9fca2b23d0ba 161 };
marcozecchini 0:9fca2b23d0ba 162
marcozecchini 0:9fca2b23d0ba 163 utest::v1::status_t greentea_test_setup(const size_t number_of_cases)
marcozecchini 0:9fca2b23d0ba 164 {
marcozecchini 0:9fca2b23d0ba 165 GREENTEA_SETUP(test_timeout, "timing_drift_auto");
marcozecchini 0:9fca2b23d0ba 166 return utest::v1::greentea_test_setup_handler(number_of_cases);
marcozecchini 0:9fca2b23d0ba 167 }
marcozecchini 0:9fca2b23d0ba 168
marcozecchini 0:9fca2b23d0ba 169 utest::v1::Specification specification(greentea_test_setup, cases);
marcozecchini 0:9fca2b23d0ba 170
marcozecchini 0:9fca2b23d0ba 171 int main()
marcozecchini 0:9fca2b23d0ba 172 {
marcozecchini 0:9fca2b23d0ba 173 return !utest::v1::Harness::run(specification);
marcozecchini 0:9fca2b23d0ba 174 }