ChibiOS/RT Architecture - Reference Manual - Guides |
00001 /* 00002 ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio. 00003 00004 This file is part of ChibiOS/RT. 00005 00006 ChibiOS/RT is free software; you can redistribute it and/or modify 00007 it under the terms of the GNU General Public License as published by 00008 the Free Software Foundation; either version 3 of the License, or 00009 (at your option) any later version. 00010 00011 ChibiOS/RT is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 GNU General Public License for more details. 00015 00016 You should have received a copy of the GNU General Public License 00017 along with this program. If not, see <http://www.gnu.org/licenses/>. 00018 00019 --- 00020 00021 A special exception to the GPL can be applied should you wish to distribute 00022 a combined work that includes ChibiOS/RT, without being obliged to provide 00023 the source code for any proprietary components. See the file exception.txt 00024 for full details of how and when the exception can be applied. 00025 */ 00026 00027 #include "ch.h" 00028 #include "test.h" 00029 00030 /** 00031 * @page test_threads Threads and Scheduler test 00032 * 00033 * File: @ref testthd.c 00034 * 00035 * <h2>Description</h2> 00036 * This module implements the test sequence for the @ref scheduler, 00037 * @ref threads and @ref time subsystems.<br> 00038 * Note that the tests on those subsystems are formally required but most of 00039 * their functionality is already demonstrated because the test suite itself 00040 * depends on them, anyway double check is good. 00041 * 00042 * <h2>Objective</h2> 00043 * Objective of the test module is to cover 100% of the subsystems code. 00044 * 00045 * <h2>Preconditions</h2> 00046 * None. 00047 * 00048 * <h2>Test Cases</h2> 00049 * - @subpage test_threads_001 00050 * - @subpage test_threads_002 00051 * - @subpage test_threads_003 00052 * - @subpage test_threads_004 00053 * . 00054 * @file testthd.c 00055 * @brief Threads and Scheduler test source file 00056 * @file testthd.h 00057 * @brief Threads and Scheduler test header file 00058 */ 00059 00060 /** 00061 * @page test_threads_001 Ready List functionality #1 00062 * 00063 * <h2>Description</h2> 00064 * Five threads, with increasing priority, are enqueued in the ready list 00065 * and atomically executed.<br> 00066 * The test expects the threads to perform their operations in increasing 00067 * priority order regardless of the initial order. 00068 */ 00069 00070 static msg_t thread(void *p) { 00071 00072 test_emit_token(*(char *)p); 00073 return 0; 00074 } 00075 00076 static char *thd1_gettest(void) { 00077 00078 return "Threads, enqueuing test #1"; 00079 } 00080 00081 static void thd1_execute(void) { 00082 00083 threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriority()-5, thread, "E"); 00084 threads[1] = chThdCreateStatic(wa[1], WA_SIZE, chThdGetPriority()-4, thread, "D"); 00085 threads[2] = chThdCreateStatic(wa[2], WA_SIZE, chThdGetPriority()-3, thread, "C"); 00086 threads[3] = chThdCreateStatic(wa[3], WA_SIZE, chThdGetPriority()-2, thread, "B"); 00087 threads[4] = chThdCreateStatic(wa[4], WA_SIZE, chThdGetPriority()-1, thread, "A"); 00088 test_wait_threads(); 00089 test_assert_sequence(1, "ABCDE"); 00090 } 00091 00092 const struct testcase testthd1 = { 00093 thd1_gettest, 00094 NULL, 00095 NULL, 00096 thd1_execute 00097 }; 00098 00099 /** 00100 * @page test_threads_002 Ready List functionality #2 00101 * 00102 * <h2>Description</h2> 00103 * Five threads, with pseudo-random priority, are enqueued in the ready list 00104 * and atomically executed.<br> 00105 * The test expects the threads to perform their operations in increasing 00106 * priority order regardless of the initial order. 00107 */ 00108 00109 static char *thd2_gettest(void) { 00110 00111 return "Threads, enqueuing test #2"; 00112 } 00113 00114 static void thd2_execute(void) { 00115 00116 threads[1] = chThdCreateStatic(wa[1], WA_SIZE, chThdGetPriority()-4, thread, "D"); 00117 threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriority()-5, thread, "E"); 00118 threads[4] = chThdCreateStatic(wa[4], WA_SIZE, chThdGetPriority()-1, thread, "A"); 00119 threads[3] = chThdCreateStatic(wa[3], WA_SIZE, chThdGetPriority()-2, thread, "B"); 00120 threads[2] = chThdCreateStatic(wa[2], WA_SIZE, chThdGetPriority()-3, thread, "C"); 00121 test_wait_threads(); 00122 test_assert_sequence(1, "ABCDE"); 00123 } 00124 00125 const struct testcase testthd2 = { 00126 thd2_gettest, 00127 NULL, 00128 NULL, 00129 thd2_execute 00130 }; 00131 00132 /** 00133 * @page test_threads_003 Threads priority change test 00134 * 00135 * <h2>Description</h2> 00136 * A series of priority changes are performed on the current thread in order 00137 * to verify that the priority change happens as expected.<br> 00138 * If the @p CH_USE_MUTEXES option is enabled then the priority changes are 00139 * also tested under priority inheritance boosted priority state. 00140 */ 00141 00142 static char *thd3_gettest(void) { 00143 00144 return "Threads, priority change"; 00145 } 00146 00147 static void thd3_execute(void) { 00148 tprio_t prio, p1; 00149 00150 prio = chThdGetPriority(); 00151 p1 = chThdSetPriority(prio + 1); 00152 test_assert(1, p1 == prio, 00153 "unexpected returned priority level"); 00154 test_assert(2, chThdGetPriority() == prio + 1, 00155 "unexpected priority level"); 00156 p1 = chThdSetPriority(p1); 00157 test_assert(3, p1 == prio + 1, 00158 "unexpected returned priority level"); 00159 test_assert(4, chThdGetPriority() == prio, 00160 "unexpected priority level"); 00161 00162 #if CH_USE_MUTEXES 00163 /* Simulates a priority boost situation (p_prio > p_realprio).*/ 00164 chSysLock(); 00165 chThdSelf()->p_prio += 2; 00166 chSysUnlock(); 00167 test_assert(5, chThdGetPriority() == prio + 2, 00168 "unexpected priority level"); 00169 00170 /* Tries to raise but below the boost level. */ 00171 p1 = chThdSetPriority(prio + 1); 00172 test_assert(6, p1 == prio, 00173 "unexpected returned priority level"); 00174 test_assert(7, chThdSelf()->p_prio == prio + 2, 00175 "unexpected priority level"); 00176 test_assert(8, chThdSelf()->p_realprio == prio + 1, 00177 "unexpected returned real priority level"); 00178 00179 /* Tries to raise above the boost level. */ 00180 p1 = chThdSetPriority(prio + 3); 00181 test_assert(9, p1 == prio + 1, 00182 "unexpected returned priority level"); 00183 test_assert(10, chThdSelf()->p_prio == prio + 3, 00184 "unexpected priority level"); 00185 test_assert(11, chThdSelf()->p_realprio == prio + 3, 00186 "unexpected real priority level"); 00187 00188 chSysLock(); 00189 chThdSelf()->p_prio = prio; 00190 chThdSelf()->p_realprio = prio; 00191 chSysUnlock(); 00192 #endif 00193 } 00194 00195 const struct testcase testthd3 = { 00196 thd3_gettest, 00197 NULL, 00198 NULL, 00199 thd3_execute 00200 }; 00201 00202 /** 00203 * @page test_threads_004 Threads delays test 00204 * 00205 * <h2>Description</h2> 00206 * Delay APIs and associated macros are tested, the invoking thread is verified 00207 * to wake up at the exact expected time. 00208 */ 00209 00210 static char *thd4_gettest(void) { 00211 00212 return "Threads, delays"; 00213 } 00214 00215 static void thd4_execute(void) { 00216 systime_t time; 00217 00218 test_wait_tick(); 00219 00220 /* Timeouts in microseconds.*/ 00221 time = chTimeNow(); 00222 chThdSleepMicroseconds(100000); 00223 test_assert_time_window(1, time + US2ST(100000), time + US2ST(100000) + 1); 00224 00225 /* Timeouts in milliseconds.*/ 00226 time = chTimeNow(); 00227 chThdSleepMilliseconds(100); 00228 test_assert_time_window(2, time + MS2ST(100), time + MS2ST(100) + 1); 00229 00230 /* Timeouts in seconds.*/ 00231 time = chTimeNow(); 00232 chThdSleepSeconds(1); 00233 test_assert_time_window(3, time + S2ST(1), time + S2ST(1) + 1); 00234 00235 /* Absolute timelines.*/ 00236 time = chTimeNow() + MS2ST(100); 00237 chThdSleepUntil(time); 00238 test_assert_time_window(4, time, time + 1); 00239 } 00240 00241 const struct testcase testthd4 = { 00242 thd4_gettest, 00243 NULL, 00244 NULL, 00245 thd4_execute 00246 }; 00247 00248 /** 00249 * @brief Test sequence for threads. 00250 */ 00251 const struct testcase * const patternthd[] = { 00252 &testthd1, 00253 &testthd2, 00254 &testthd3, 00255 &testthd4, 00256 NULL 00257 };