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 "unity.h"
00019 #include "utest.h"
00020 #include "rtos.h"
00021 #include "SynchronizedIntegral.h"
00022 #include "LockGuard.h"
00023 
00024 #if defined(MBED_RTOS_SINGLE_THREAD)
00025   #error [NOT_SUPPORTED] test not supported
00026 #endif
00027 
00028 #define THREAD_STACK_SIZE 768
00029 
00030 using namespace utest::v1;
00031 
00032 // The counter type used accross all the tests
00033 // It is internall ysynchronized so read
00034 typedef SynchronizedIntegral<int> counter_t;
00035 
00036 // Tasks with different functions to test on threads
00037 void increment(counter_t* counter) {
00038     (*counter)++;
00039 }
00040 
00041 void increment_with_yield(counter_t* counter) {
00042     Thread::yield();
00043     (*counter)++;
00044 }
00045 
00046 void increment_with_wait(counter_t* counter) {
00047     Thread::wait(100);
00048     (*counter)++;
00049 }
00050 
00051 void increment_with_child(counter_t* counter) {
00052     Thread child(osPriorityNormal, THREAD_STACK_SIZE/2);
00053     child.start(callback(increment, counter));
00054     child.join();
00055 }
00056 
00057 void increment_with_murder(counter_t* counter) {
00058     {
00059         // take ownership of the counter mutex so it prevent the child to
00060         // modify counter.
00061         LockGuard lock(counter->internal_mutex());
00062         Thread child(osPriorityNormal, THREAD_STACK_SIZE);
00063         child.start(callback(increment, counter));
00064         child.terminate();
00065     }
00066 
00067     (*counter)++;
00068 }
00069 
00070 void self_terminate(Thread *self) {
00071     self->terminate();
00072     // Code should not get here
00073     TEST_ASSERT(0);
00074 }
00075 
00076 // Tests that spawn tasks in different configurations
00077 
00078 /** Template for tests: single thread, with yield, with wait, with child, with murder
00079 
00080     Testing single thread
00081     Given single thread is started
00082     when the thread increments the counter
00083     then the final value of the counter is equal to 1
00084 
00085     Testing single thread with yield
00086     Given single thread is started
00087     when the thread yields and then increments the counter
00088     then the final value of the counter is equal to 1
00089 
00090     Testing single thread with wait
00091     Given single thread is started
00092     when the thread waits for 100ms and then increments the counter
00093     then the final value of the counter is equal to 1
00094 
00095     Testing single thread with child
00096     Given single thread is started
00097     when the thread spawns another thread that increments the counter
00098     then the final value of the counter is equal to 1
00099 
00100     Testing serial threads with murder
00101     Given single thread is started
00102     when the parent thread is holding a lock
00103         and the parent thread spawns a child thread that waits for the lock before incrementing the counter
00104         and the parent terminates the child before releasing the lock
00105         and the parent increments the counter
00106     then the final value of the counter is equal to 1
00107 */
00108 template <void (*F)(counter_t *)>
00109 void test_single_thread() {
00110     counter_t counter(0);
00111     Thread thread(osPriorityNormal, THREAD_STACK_SIZE);
00112     thread.start(callback(F, &counter));
00113     thread.join();
00114     TEST_ASSERT_EQUAL(counter, 1);
00115 }
00116 
00117 /** Template for tests: parallel threads, with yield, with wait, with child, with murder
00118 
00119     Testing parallel threads
00120     Given multiple threads are started in parallel
00121     when each of the threads increments the counter
00122     then the final value of the counter is equal to number of threads
00123 
00124     Testing parallel threads with yield
00125     Given multiple threads are started in parallel
00126     when each of the threads yields and then increments the counter
00127     then the final value of the counter is equal to number of threads
00128 
00129     Testing parallel threads with wait
00130     Given multiple threads are started in parallel
00131     when each of the threads waits for 100ms and then increments the counter
00132     then the final value of the counter is equal to number of threads
00133 
00134     Testing parallel threads with child
00135     Given multiple threads are started in parallel
00136     when each of the threads spawns another thread that increments the counter
00137     then the final value of the counter is equal to number of parallel threads
00138 
00139     Testing parallel threads with murder
00140     Given multiple threads are started in parallel
00141     when the parent thread is holding a lock
00142         and the parent thread spawns a child thread that waits for the lock before incrementing the counter
00143         and the parent terminates the child before releasing the lock
00144         and the parent increments the counter
00145     then the final value of the counter is equal to number of parallel threads
00146 */
00147 template <int N, void (*F)(counter_t *)>
00148 void test_parallel_threads() {
00149     counter_t counter(0);
00150     Thread *threads[N];
00151 
00152     for (int i = 0; i < N; i++) {
00153         threads[i] = new Thread(osPriorityNormal, THREAD_STACK_SIZE);
00154         threads[i]->start(callback(F, &counter));
00155     }
00156 
00157     for (int i = 0; i < N; i++) {
00158         threads[i]->join();
00159         delete threads[i];
00160     }
00161 
00162     TEST_ASSERT_EQUAL(counter, N);
00163 }
00164 
00165 /** Template for tests: serial threads, with yield, with wait, with child, with murder
00166 
00167     Testing serial threads
00168     Given multiple threads are started serially
00169     when each of the threads increments the counter
00170     then the final value of the counter is equal to number of threads
00171 
00172     Testing serial threads with yield
00173     Given multiple threads are started serially
00174     when each of the threads yields and then increments the counter
00175     then the final value of the counter is equal to number of threads
00176 
00177     Testing serial threads with wait
00178     Given multiple threads are started serially
00179     when each of the threads waits for 100ms and then increments the counter
00180     then the final value of the counter is equal to number of threads
00181 
00182     Testing serial threads with child
00183     Given multiple threads are started serially
00184     when each of the threads spawns another thread that increments the counter
00185     then the final value of the counter is equal to number of serial threads
00186 
00187     Testing serial threads with murder
00188     Given multiple threads are started serially
00189     when the parent thread is holding a lock
00190         and the parent thread spawns a child thread that waits for the lock before incrementing the counter
00191         and the parent terminates the child before releasing the lock
00192         and the parent increments the counter
00193     then the final value of the counter is equal to number of serial threads
00194 */
00195 template <int N, void (*F)(counter_t *)>
00196 void test_serial_threads() {
00197     counter_t counter(0);
00198 
00199     for (int i = 0; i < N; i++) {
00200         Thread thread(osPriorityNormal, THREAD_STACK_SIZE);
00201         thread.start(callback(F, &counter));
00202         thread.join();
00203     }
00204 
00205     TEST_ASSERT_EQUAL(counter, N);
00206 }
00207 
00208 /** Testing thread self terminate
00209 
00210     Given the thread is running
00211     when the thread calls @a terminate on its self
00212     then the thread terminates execution cleanly
00213  */
00214 void test_self_terminate() {
00215     Thread *thread = new Thread(osPriorityNormal, THREAD_STACK_SIZE);
00216     thread->start(callback(self_terminate, thread));
00217     thread->join();
00218     delete thread;
00219 }
00220 
00221 void signal_wait()
00222 {
00223     osEvent evt = Thread::signal_wait(0x1);
00224     TEST_ASSERT_EQUAL(osEventSignal, evt.status);
00225     TEST_ASSERT_EQUAL(0x1, evt.value.signals);
00226 }
00227 
00228 void signal_wait_tout()
00229 {
00230     osEvent evt = Thread::signal_wait(0x2, 50);
00231     TEST_ASSERT_EQUAL(osEventTimeout, evt.status);
00232 }
00233 
00234 void signal_wait_multibit()
00235 {
00236     osEvent evt = Thread::signal_wait(0x1 | 0x2, 50);
00237     TEST_ASSERT_EQUAL(osEventSignal, evt.status);
00238     TEST_ASSERT_EQUAL(0x3, evt.value.signals);
00239 }
00240 
00241 void signal_wait_multibit_tout()
00242 {
00243     osEvent evt = Thread::signal_wait(0x1 | 0x2, 50);
00244     TEST_ASSERT_EQUAL(osEventTimeout, evt.status);
00245 }
00246 
00247 /**
00248     Testing thread signal: wait
00249     Given two threads (A & B) are started
00250     when thread A executes @a signal_wait(0x1)
00251         and thread B execute @a signal_set(0x1)
00252     then thread A exits the wait and continues execution
00253 
00254     Testing thread signal: timeout
00255     Given two threads (A & B) are started
00256     when thread A executes @a signal_wait(0x1 | 0x2, 50) with a timeout of 50ms
00257         and thread B execute @a signal_set(0x2)
00258     then thread A keeps waiting for correct signal until it timeouts
00259 
00260     Testing thread signal: multi-bit
00261     Given two threads (A & B) are started
00262     when thread A executes @a signal_wait(0x1 | 0x2)
00263         and thread B execute @a signal_set(0x1 | 0x2)
00264     then thread A exits the wait and continues execution
00265 
00266     Testing thread signal: multi-bit timeout
00267     Given two threads (A & B) are started
00268     when thread A executes @a signal_wait(0x1, 50) with a timeout of 50ms
00269         and thread B execute @a signal_set(0x2)
00270     then thread A keeps waiting for correct signal until it timeouts
00271 */
00272 template <int S, void (*F)()>
00273 void test_thread_signal()
00274 {
00275     Thread t_wait;
00276 
00277     t_wait.start(callback(F));
00278 
00279     Thread::yield();
00280 
00281     Thread::State state = t_wait.get_state();
00282     TEST_ASSERT_EQUAL(Thread::WaitingThreadFlag, state);
00283 
00284     int32_t res = t_wait.signal_set(S);
00285 
00286     t_wait.join();
00287 }
00288 
00289 void signal_clr()
00290 {
00291     Thread::yield();
00292 
00293     int32_t sig = Thread::signal_clr(0x1);
00294     TEST_ASSERT_EQUAL(0x1, sig);
00295 
00296     /* Signal cleared we should get timeout */
00297     osEvent evt = Thread::signal_wait(0x1, 0);
00298     TEST_ASSERT_EQUAL(osOK, evt.status);
00299 }
00300 
00301 /** Testing thread signals: signal clear
00302 
00303     Given two threads (A & B) are started
00304     when thread A executes @a signal_set(0x1)
00305         and thread B execute @a signal_clr(0x1)
00306         and thread B execute @a signal_wait(0x1, 0)
00307     then thread B @a signal_wait status should be osOK indicating a timeout
00308  */
00309 void test_thread_signal_clr()
00310 {
00311     Thread t_wait;
00312 
00313     t_wait.start(callback(signal_clr));
00314 
00315     int32_t res = t_wait.signal_set(0x1);
00316     TEST_ASSERT_EQUAL(0x1, res);
00317 
00318     t_wait.join();
00319 }
00320 
00321 void thread_wait_signal() {
00322     Thread::signal_wait(0x1);
00323 }
00324 
00325 void stack_info() {
00326     Thread::signal_wait(0x1);
00327 
00328     thread_wait_signal();
00329 
00330     Thread::signal_wait(0x1);
00331 }
00332 
00333 /** Testing thread stack info
00334 
00335     Given the thread is running
00336     when a function is called from the thread context
00337     then the stack usage goes up
00338         and the reported stack size is as requested in the constructor
00339         and the sum of free and used stack sizes is equal to the total stack size
00340     when the function returns
00341     then the stack usage goes down
00342         and the reported stack size is as requested in the constructor
00343         and the sum of free and used stack sizes is equal to the total stack size
00344  */
00345 void test_thread_stack_info() {
00346     Thread t(osPriorityNormal, THREAD_STACK_SIZE);
00347     t.start(callback(stack_info));
00348 
00349     Thread::yield();
00350 
00351     TEST_ASSERT_EQUAL(THREAD_STACK_SIZE, t.stack_size());
00352     TEST_ASSERT_EQUAL(THREAD_STACK_SIZE, t.free_stack() + t.used_stack());
00353     uint32_t last_stack = t.used_stack();
00354 
00355     t.signal_set(0x1);
00356     Thread::yield();
00357 
00358     TEST_ASSERT_EQUAL(THREAD_STACK_SIZE, t.free_stack() + t.used_stack());
00359     TEST_ASSERT(last_stack <= t.used_stack());
00360     last_stack = t.used_stack();
00361 
00362     t.signal_set(0x1);
00363     Thread::yield();
00364 
00365     TEST_ASSERT_EQUAL(THREAD_STACK_SIZE, t.free_stack() + t.used_stack());
00366     TEST_ASSERT(last_stack >= t.used_stack());
00367 
00368     t.signal_set(0x1);
00369 
00370     t.join();
00371 }
00372 
00373 /** Testing thread wait aka delay
00374 
00375     Given the thread is running
00376     when the @a wait function is called
00377     then the thread sleeps for given amount of time
00378  */
00379 void test_thread_wait() {
00380     Timer timer;
00381     timer.start();
00382 
00383     Thread::wait(150);
00384 
00385     TEST_ASSERT_UINT32_WITHIN(50000, 150000, timer.read_us());
00386 }
00387 
00388 /** Testing thread name
00389 
00390     Given a thread is started with a specified name
00391     when the name is queried using @a get_name
00392     then the returned name is as set
00393 */
00394 void test_thread_name() {
00395     const char tname[] = "Amazing thread";
00396     Thread t(osPriorityNormal, THREAD_STACK_SIZE, NULL, tname);
00397     t.start(callback(thread_wait_signal));
00398     TEST_ASSERT_EQUAL(strcmp(tname, t.get_name()), 0);
00399     t.signal_set(0x1);
00400     t.join();
00401 }
00402 
00403 void test_deleted_thread()
00404 {
00405 }
00406 
00407 /** Testing thread states: deleted
00408 
00409     Given the thread is not started
00410     then its state, as reported by @a get_state, is @a Deleted
00411     when the thread is started and finishes executing
00412     then its state, as reported by @a get_state, is @a Deleted
00413  */
00414 void test_deleted()
00415 {
00416     Thread t;
00417 
00418     TEST_ASSERT_EQUAL(Thread::Deleted, t.get_state());
00419 
00420     t.start(callback(test_deleted_thread));
00421 
00422     t.join();
00423     TEST_ASSERT_EQUAL(Thread::Deleted, t.get_state());
00424 }
00425 
00426 void test_delay_thread()
00427 {
00428     Thread::wait(50);
00429 }
00430 
00431 /** Testing thread states: wait delay
00432 
00433     Given the thread is running
00434     when thread calls @a wait
00435     then its state, as reported by @a get_state, is @a WaitingDelay
00436  */
00437 void test_delay()
00438 {
00439     Thread t;
00440 
00441     t.start(callback(test_delay_thread));
00442 
00443     Thread::yield();
00444 
00445     TEST_ASSERT_EQUAL(Thread::WaitingDelay, t.get_state());
00446 
00447     t.join();
00448     TEST_ASSERT_EQUAL(Thread::Deleted, t.get_state());
00449 }
00450 
00451 void test_signal_thread()
00452 {
00453     Thread::signal_wait(0x1);
00454 }
00455 
00456 /** Testing thread states: wait signal
00457 
00458     Given the thread is running
00459     when thread waits for a signal
00460     then its state, as reported by @a get_state, is @a WaitingSignal
00461  */
00462 void test_signal()
00463 {
00464     Thread t;
00465 
00466     t.start(callback(test_signal_thread));
00467 
00468     Thread::yield();
00469 
00470     TEST_ASSERT_EQUAL(Thread::WaitingThreadFlag, t.get_state());
00471 
00472     t.signal_set(0x1);
00473 }
00474 
00475 void test_evt_flag_thread(osEventFlagsId_t evtflg)
00476 {
00477     osEventFlagsWait(evtflg, 0x1, osFlagsWaitAny, osWaitForever);
00478 }
00479 
00480 /** Testing thread states: wait evt flag
00481 
00482     Given the thread is running
00483     when thread waits for an event flag
00484     then its state, as reported by @a get_state, is @a WaitingEventFlag
00485  */
00486 void test_evt_flag()
00487 {
00488     Thread t;
00489     mbed_rtos_storage_event_flags_t evtflg_mem;
00490     osEventFlagsAttr_t evtflg_attr;
00491     osEventFlagsId_t evtflg;
00492 
00493     evtflg_attr.cb_mem = &evtflg_mem;
00494     evtflg_attr.cb_size = sizeof(evtflg_mem);
00495     evtflg = osEventFlagsNew(&evtflg_attr);
00496     TEST_ASSERT_NOT_EQUAL(NULL, evtflg);
00497 
00498     t.start(callback(test_evt_flag_thread, evtflg));
00499 
00500     Thread::yield();
00501 
00502     TEST_ASSERT_EQUAL(Thread::WaitingEventFlag, t.get_state());
00503 
00504     osEventFlagsSet(evtflg, 0x1);
00505 }
00506 
00507 void test_mutex_thread(Mutex *mutex)
00508 {
00509     mutex->lock();
00510 }
00511 
00512 /** Testing thread states: wait mutex
00513 
00514     Given the thread is running
00515     when thread waits for a mutex
00516     then its state, as reported by @a get_state, is @a WaitingMutex
00517  */
00518 void test_mutex()
00519 {
00520     Thread t;
00521     Mutex mutex;
00522 
00523     mutex.lock();
00524 
00525     t.start(callback(test_mutex_thread, &mutex));
00526 
00527     Thread::yield();
00528 
00529     TEST_ASSERT_EQUAL(Thread::WaitingMutex, t.get_state());
00530 
00531     mutex.unlock();
00532 }
00533 
00534 void test_semaphore_thread(Semaphore *sem)
00535 {
00536     sem->wait();
00537 }
00538 
00539 /** Testing thread states: wait semaphore
00540 
00541     Given the thread is running
00542     when thread waits for a semaphore
00543     then its state, as reported by @a get_state, is @a WaitingSemaphore
00544  */
00545 void test_semaphore()
00546 {
00547     Thread t;
00548     Semaphore sem;
00549 
00550     t.start(callback(test_semaphore_thread, &sem));
00551 
00552     Thread::yield();
00553 
00554     TEST_ASSERT_EQUAL(Thread::WaitingSemaphore, t.get_state());
00555 
00556     sem.release();
00557 }
00558 
00559 void test_msg_get_thread(Queue<int32_t, 1> *queue)
00560 {
00561     queue->get();
00562 }
00563 
00564 /** Testing thread states: wait message get
00565 
00566     Given the thread is running
00567     when thread tries to get a message from an empty queue
00568     then its state, as reported by @a get_state, is @a WaitingMessageGet
00569  */
00570 void test_msg_get()
00571 {
00572     Thread t;
00573     Queue<int32_t, 1> queue;
00574 
00575     t.start(callback(test_msg_get_thread, &queue));
00576 
00577     Thread::yield();
00578 
00579     TEST_ASSERT_EQUAL(Thread::WaitingMessageGet, t.get_state());
00580 
00581     queue.put((int32_t *)0xE1EE7);
00582 }
00583 
00584 void test_msg_put_thread(Queue<int32_t, 1> *queue)
00585 {
00586     queue->put((int32_t *)0xDEADBEEF, osWaitForever);
00587 
00588 }
00589 
00590 /** Testing thread states: wait message put
00591 
00592     Given the thread is running
00593     when thread tries to put a message into a full queue
00594     then its state, as reported by @a get_state, is @a WaitingMessagePut
00595  */
00596 void test_msg_put()
00597 {
00598     Thread t;
00599     Queue<int32_t, 1> queue;
00600 
00601     queue.put((int32_t *)0xE1EE7);
00602 
00603     t.start(callback(test_msg_put_thread, &queue));
00604 
00605     Thread::yield();
00606 
00607     TEST_ASSERT_EQUAL(Thread::WaitingMessagePut, t.get_state());
00608     queue.get();
00609 }
00610 
00611 /** Utility function that places some date on the stack */
00612 void use_some_stack () {
00613     volatile uint32_t stack_filler[10] = {0xDEADBEEF};
00614 }
00615 
00616 /** Testing thread with external stack memory
00617 
00618     Given external buffer is supplied as stack to a thread
00619     when the thread executes
00620     then the supplies buffer is used as a stack
00621  */
00622 void test_thread_ext_stack() {
00623     char stack[512];
00624     Thread t(osPriorityNormal, sizeof(stack), (unsigned char*)stack);
00625 
00626     memset(&stack, 0, sizeof(stack));
00627     t.start(callback(use_some_stack));
00628     t.join();
00629 
00630     /* If buffer was used as a stack it was cleared with pattern and some data were placed in it */
00631     for(unsigned i = 0; i < sizeof(stack); i++) {
00632         if (stack[i] != 0)
00633             return;
00634     }
00635 
00636     TEST_FAIL_MESSAGE("External stack was not used.");
00637 }
00638 
00639 /** Testing thread priority operations
00640 
00641     Given thread running with osPriorityNormal
00642     when new priority is set using @a set_priority
00643     then priority is changed and can be retrieved using @a get_priority
00644  */
00645 void test_thread_prio() {
00646     Thread t(osPriorityNormal);
00647     t.start(callback(thread_wait_signal));
00648 
00649     TEST_ASSERT_EQUAL(osPriorityNormal, t.get_priority());
00650 
00651     t.set_priority(osPriorityHigh);
00652 
00653     TEST_ASSERT_EQUAL(osPriorityHigh, t.get_priority());
00654 
00655     t.signal_set(0x1);
00656     t.join();
00657 }
00658 
00659 utest::v1::status_t test_setup(const size_t number_of_cases) {
00660     GREENTEA_SETUP(20, "default_auto");
00661     return verbose_test_setup_handler(number_of_cases);
00662 }
00663 
00664 #define DEFAULT_HANDLERS NULL,NULL,greentea_case_setup_handler,greentea_case_teardown_handler,greentea_case_failure_abort_handler
00665 
00666 // Test cases. It's spelled out rather than constructed with macro because
00667 // macros don't play nicely with the templates (extra comma).
00668 static const case_t cases[] = {
00669     {"Testing single thread", test_single_thread<increment>, DEFAULT_HANDLERS},
00670     {"Testing parallel threads", test_parallel_threads<3, increment> , DEFAULT_HANDLERS},
00671     {"Testing serial threads", test_serial_threads<10, increment> , DEFAULT_HANDLERS},
00672 
00673     {"Testing single thread with yield", test_single_thread<increment_with_yield>, DEFAULT_HANDLERS},
00674     {"Testing parallel threads with yield", test_parallel_threads<3, increment_with_yield>, DEFAULT_HANDLERS},
00675     {"Testing serial threads with yield", test_serial_threads<10, increment_with_yield>, DEFAULT_HANDLERS},
00676 
00677     {"Testing single thread with wait", test_single_thread<increment_with_wait>, DEFAULT_HANDLERS},
00678     {"Testing parallel threads with wait", test_parallel_threads<3, increment_with_wait>, DEFAULT_HANDLERS},
00679     {"Testing serial threads with wait", test_serial_threads<10, increment_with_wait>, DEFAULT_HANDLERS},
00680 
00681     {"Testing single thread with child", test_single_thread<increment_with_child>, DEFAULT_HANDLERS},
00682     {"Testing parallel threads with child", test_parallel_threads<3, increment_with_child>, DEFAULT_HANDLERS},
00683     {"Testing serial threads with child", test_serial_threads<10, increment_with_child>, DEFAULT_HANDLERS},
00684 
00685     {"Testing single thread with murder", test_single_thread<increment_with_murder>, DEFAULT_HANDLERS},
00686     {"Testing parallel threads with murder", test_parallel_threads<3, increment_with_murder>, DEFAULT_HANDLERS},
00687     {"Testing serial threads with murder", test_serial_threads<10, increment_with_murder>, DEFAULT_HANDLERS},
00688 
00689     {"Testing thread self terminate", test_self_terminate, DEFAULT_HANDLERS},
00690 
00691     {"Testing thread signals: wait", test_thread_signal<0x1, signal_wait>, DEFAULT_HANDLERS},
00692     {"Testing thread signals: timeout", test_thread_signal<0x1, signal_wait_tout>, DEFAULT_HANDLERS},
00693     {"Testing thread signals: multi-bit", test_thread_signal<0x3, signal_wait_multibit>, DEFAULT_HANDLERS},
00694     {"Testing thread signals: multi-bit timeout", test_thread_signal<0x1, signal_wait_multibit_tout>, DEFAULT_HANDLERS},
00695     {"Testing thread signals: signal clear", test_thread_signal_clr, DEFAULT_HANDLERS},
00696 
00697 
00698     {"Testing thread stack info", test_thread_stack_info, DEFAULT_HANDLERS},
00699     {"Testing thread wait", test_thread_wait, DEFAULT_HANDLERS},
00700     {"Testing thread name", test_thread_name, DEFAULT_HANDLERS},
00701 
00702     {"Testing thread states: deleted", test_deleted, DEFAULT_HANDLERS},
00703     {"Testing thread states: wait delay", test_delay, DEFAULT_HANDLERS},
00704     {"Testing thread states: wait signal", test_signal, DEFAULT_HANDLERS},
00705     {"Testing thread states: wait event flag", test_evt_flag, DEFAULT_HANDLERS},
00706     {"Testing thread states: wait mutex", test_mutex, DEFAULT_HANDLERS},
00707     {"Testing thread states: wait semaphore", test_semaphore, DEFAULT_HANDLERS},
00708     {"Testing thread states: wait message get", test_msg_get, DEFAULT_HANDLERS},
00709     {"Testing thread states: wait message put", test_msg_put, DEFAULT_HANDLERS},
00710 
00711     {"Testing thread with external stack memory", test_thread_ext_stack, DEFAULT_HANDLERS},
00712     {"Testing thread priority ops", test_thread_prio, DEFAULT_HANDLERS}
00713 };
00714 
00715 Specification specification(test_setup, cases);
00716 
00717 int main() {
00718     return !Harness::run(specification);
00719 }