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 "unity.h"
marcozecchini 0:9fca2b23d0ba 19 #include "utest.h"
marcozecchini 0:9fca2b23d0ba 20 #include "rtos.h"
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 namespace utest::v1;
marcozecchini 0:9fca2b23d0ba 27
marcozecchini 0:9fca2b23d0ba 28 #define TEST_STACK_SIZE 512
marcozecchini 0:9fca2b23d0ba 29 #define TEST_DELAY 10
marcozecchini 0:9fca2b23d0ba 30
marcozecchini 0:9fca2b23d0ba 31 static int change_counter = 0;
marcozecchini 0:9fca2b23d0ba 32 static Mutex mutex;
marcozecchini 0:9fca2b23d0ba 33 static ConditionVariable cond(mutex);
marcozecchini 0:9fca2b23d0ba 34
marcozecchini 0:9fca2b23d0ba 35 void increment_on_signal()
marcozecchini 0:9fca2b23d0ba 36 {
marcozecchini 0:9fca2b23d0ba 37 mutex.lock();
marcozecchini 0:9fca2b23d0ba 38
marcozecchini 0:9fca2b23d0ba 39 cond.wait();
marcozecchini 0:9fca2b23d0ba 40 change_counter++;
marcozecchini 0:9fca2b23d0ba 41
marcozecchini 0:9fca2b23d0ba 42 mutex.unlock();
marcozecchini 0:9fca2b23d0ba 43 }
marcozecchini 0:9fca2b23d0ba 44
marcozecchini 0:9fca2b23d0ba 45 void test_notify_one()
marcozecchini 0:9fca2b23d0ba 46 {
marcozecchini 0:9fca2b23d0ba 47 Thread t1(osPriorityNormal, TEST_STACK_SIZE);
marcozecchini 0:9fca2b23d0ba 48 Thread t2(osPriorityNormal, TEST_STACK_SIZE);
marcozecchini 0:9fca2b23d0ba 49
marcozecchini 0:9fca2b23d0ba 50 change_counter = 0;
marcozecchini 0:9fca2b23d0ba 51 t1.start(increment_on_signal);
marcozecchini 0:9fca2b23d0ba 52 t2.start(increment_on_signal);
marcozecchini 0:9fca2b23d0ba 53
marcozecchini 0:9fca2b23d0ba 54 wait_ms(TEST_DELAY);
marcozecchini 0:9fca2b23d0ba 55 TEST_ASSERT_EQUAL(0, change_counter);
marcozecchini 0:9fca2b23d0ba 56
marcozecchini 0:9fca2b23d0ba 57 mutex.lock();
marcozecchini 0:9fca2b23d0ba 58 cond.notify_one();
marcozecchini 0:9fca2b23d0ba 59 mutex.unlock();
marcozecchini 0:9fca2b23d0ba 60
marcozecchini 0:9fca2b23d0ba 61 wait_ms(TEST_DELAY);
marcozecchini 0:9fca2b23d0ba 62 TEST_ASSERT_EQUAL(1, change_counter);
marcozecchini 0:9fca2b23d0ba 63
marcozecchini 0:9fca2b23d0ba 64 mutex.lock();
marcozecchini 0:9fca2b23d0ba 65 cond.notify_one();
marcozecchini 0:9fca2b23d0ba 66 mutex.unlock();
marcozecchini 0:9fca2b23d0ba 67
marcozecchini 0:9fca2b23d0ba 68 t1.join();
marcozecchini 0:9fca2b23d0ba 69 t2.join();
marcozecchini 0:9fca2b23d0ba 70 }
marcozecchini 0:9fca2b23d0ba 71
marcozecchini 0:9fca2b23d0ba 72 void test_notify_all()
marcozecchini 0:9fca2b23d0ba 73 {
marcozecchini 0:9fca2b23d0ba 74 Thread t1(osPriorityNormal, TEST_STACK_SIZE);
marcozecchini 0:9fca2b23d0ba 75 Thread t2(osPriorityNormal, TEST_STACK_SIZE);
marcozecchini 0:9fca2b23d0ba 76
marcozecchini 0:9fca2b23d0ba 77 change_counter = 0;
marcozecchini 0:9fca2b23d0ba 78 t1.start(increment_on_signal);
marcozecchini 0:9fca2b23d0ba 79 t2.start(increment_on_signal);
marcozecchini 0:9fca2b23d0ba 80
marcozecchini 0:9fca2b23d0ba 81 wait_ms(TEST_DELAY);
marcozecchini 0:9fca2b23d0ba 82 TEST_ASSERT_EQUAL(0, change_counter);
marcozecchini 0:9fca2b23d0ba 83
marcozecchini 0:9fca2b23d0ba 84 mutex.lock();
marcozecchini 0:9fca2b23d0ba 85 cond.notify_all();
marcozecchini 0:9fca2b23d0ba 86 mutex.unlock();
marcozecchini 0:9fca2b23d0ba 87
marcozecchini 0:9fca2b23d0ba 88 wait_ms(TEST_DELAY);
marcozecchini 0:9fca2b23d0ba 89 TEST_ASSERT_EQUAL(2, change_counter);
marcozecchini 0:9fca2b23d0ba 90
marcozecchini 0:9fca2b23d0ba 91 t1.join();
marcozecchini 0:9fca2b23d0ba 92 t2.join();
marcozecchini 0:9fca2b23d0ba 93 }
marcozecchini 0:9fca2b23d0ba 94
marcozecchini 0:9fca2b23d0ba 95
marcozecchini 0:9fca2b23d0ba 96 class TestConditionVariable : public ConditionVariable {
marcozecchini 0:9fca2b23d0ba 97
marcozecchini 0:9fca2b23d0ba 98 public:
marcozecchini 0:9fca2b23d0ba 99 static void test_linked_list(void)
marcozecchini 0:9fca2b23d0ba 100 {
marcozecchini 0:9fca2b23d0ba 101 Waiter *list = NULL;
marcozecchini 0:9fca2b23d0ba 102 Waiter w1;
marcozecchini 0:9fca2b23d0ba 103 Waiter w2;
marcozecchini 0:9fca2b23d0ba 104 Waiter w3;
marcozecchini 0:9fca2b23d0ba 105 Waiter w4;
marcozecchini 0:9fca2b23d0ba 106
marcozecchini 0:9fca2b23d0ba 107 TEST_ASSERT_EQUAL(0, validate_and_get_size(&list));
marcozecchini 0:9fca2b23d0ba 108
marcozecchini 0:9fca2b23d0ba 109 // Add 4 nodes
marcozecchini 0:9fca2b23d0ba 110 _add_wait_list(&list, &w1);
marcozecchini 0:9fca2b23d0ba 111 TEST_ASSERT_EQUAL(1, validate_and_get_size(&list));
marcozecchini 0:9fca2b23d0ba 112 _add_wait_list(&list, &w2);
marcozecchini 0:9fca2b23d0ba 113 TEST_ASSERT_EQUAL(2, validate_and_get_size(&list));
marcozecchini 0:9fca2b23d0ba 114 _add_wait_list(&list, &w3);
marcozecchini 0:9fca2b23d0ba 115 TEST_ASSERT_EQUAL(3, validate_and_get_size(&list));
marcozecchini 0:9fca2b23d0ba 116 _add_wait_list(&list, &w4);
marcozecchini 0:9fca2b23d0ba 117 TEST_ASSERT_EQUAL(4, validate_and_get_size(&list));
marcozecchini 0:9fca2b23d0ba 118
marcozecchini 0:9fca2b23d0ba 119 // Remove a middle node
marcozecchini 0:9fca2b23d0ba 120 _remove_wait_list(&list, &w2);
marcozecchini 0:9fca2b23d0ba 121 TEST_ASSERT_EQUAL(3, validate_and_get_size(&list));
marcozecchini 0:9fca2b23d0ba 122
marcozecchini 0:9fca2b23d0ba 123 // Remove front node
marcozecchini 0:9fca2b23d0ba 124 _remove_wait_list(&list, &w1);
marcozecchini 0:9fca2b23d0ba 125 TEST_ASSERT_EQUAL(2, validate_and_get_size(&list));
marcozecchini 0:9fca2b23d0ba 126
marcozecchini 0:9fca2b23d0ba 127 // remove back node
marcozecchini 0:9fca2b23d0ba 128 _remove_wait_list(&list, &w4);
marcozecchini 0:9fca2b23d0ba 129 TEST_ASSERT_EQUAL(1, validate_and_get_size(&list));
marcozecchini 0:9fca2b23d0ba 130
marcozecchini 0:9fca2b23d0ba 131 // remove last node
marcozecchini 0:9fca2b23d0ba 132 _remove_wait_list(&list, &w3);
marcozecchini 0:9fca2b23d0ba 133 TEST_ASSERT_EQUAL(0, validate_and_get_size(&list));
marcozecchini 0:9fca2b23d0ba 134
marcozecchini 0:9fca2b23d0ba 135 TEST_ASSERT_EQUAL_PTR(NULL, list);
marcozecchini 0:9fca2b23d0ba 136 }
marcozecchini 0:9fca2b23d0ba 137
marcozecchini 0:9fca2b23d0ba 138 /**
marcozecchini 0:9fca2b23d0ba 139 * Validate the linked list an return the number of elements
marcozecchini 0:9fca2b23d0ba 140 *
marcozecchini 0:9fca2b23d0ba 141 * If this list is invalid then this function asserts and does not
marcozecchini 0:9fca2b23d0ba 142 * return.
marcozecchini 0:9fca2b23d0ba 143 *
marcozecchini 0:9fca2b23d0ba 144 * Every node in a valid linked list has the properties:
marcozecchini 0:9fca2b23d0ba 145 * 1. node->prev->next == node
marcozecchini 0:9fca2b23d0ba 146 * 2. node->next->prev == node
marcozecchini 0:9fca2b23d0ba 147 */
marcozecchini 0:9fca2b23d0ba 148 static int validate_and_get_size(Waiter **list)
marcozecchini 0:9fca2b23d0ba 149 {
marcozecchini 0:9fca2b23d0ba 150 Waiter *first = *list;
marcozecchini 0:9fca2b23d0ba 151 if (NULL == first) {
marcozecchini 0:9fca2b23d0ba 152 // List is empty
marcozecchini 0:9fca2b23d0ba 153 return 0;
marcozecchini 0:9fca2b23d0ba 154 }
marcozecchini 0:9fca2b23d0ba 155
marcozecchini 0:9fca2b23d0ba 156 int size = 0;
marcozecchini 0:9fca2b23d0ba 157 Waiter *current = first;
marcozecchini 0:9fca2b23d0ba 158 do {
marcozecchini 0:9fca2b23d0ba 159 TEST_ASSERT_EQUAL_PTR(current, current->prev->next);
marcozecchini 0:9fca2b23d0ba 160 TEST_ASSERT_EQUAL_PTR(current, current->next->prev);
marcozecchini 0:9fca2b23d0ba 161 current = current->next;
marcozecchini 0:9fca2b23d0ba 162 size++;
marcozecchini 0:9fca2b23d0ba 163 } while (current != first);
marcozecchini 0:9fca2b23d0ba 164 return size;
marcozecchini 0:9fca2b23d0ba 165 }
marcozecchini 0:9fca2b23d0ba 166
marcozecchini 0:9fca2b23d0ba 167 };
marcozecchini 0:9fca2b23d0ba 168
marcozecchini 0:9fca2b23d0ba 169 utest::v1::status_t test_setup(const size_t number_of_cases)
marcozecchini 0:9fca2b23d0ba 170 {
marcozecchini 0:9fca2b23d0ba 171 GREENTEA_SETUP(10, "default_auto");
marcozecchini 0:9fca2b23d0ba 172 return verbose_test_setup_handler(number_of_cases);
marcozecchini 0:9fca2b23d0ba 173 }
marcozecchini 0:9fca2b23d0ba 174
marcozecchini 0:9fca2b23d0ba 175 Case cases[] = {
marcozecchini 0:9fca2b23d0ba 176 Case("Test notify one", test_notify_one),
marcozecchini 0:9fca2b23d0ba 177 Case("Test notify all", test_notify_all),
marcozecchini 0:9fca2b23d0ba 178 Case("Test linked list", TestConditionVariable::test_linked_list),
marcozecchini 0:9fca2b23d0ba 179 };
marcozecchini 0:9fca2b23d0ba 180
marcozecchini 0:9fca2b23d0ba 181 Specification specification(test_setup, cases);
marcozecchini 0:9fca2b23d0ba 182
marcozecchini 0:9fca2b23d0ba 183 int main()
marcozecchini 0:9fca2b23d0ba 184 {
marcozecchini 0:9fca2b23d0ba 185 return !Harness::run(specification);
marcozecchini 0:9fca2b23d0ba 186 }