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_sem Semaphores test 00032 * 00033 * File: @ref testsem.c 00034 * 00035 * <h2>Description</h2> 00036 * This module implements the test sequence for the @ref semaphores subsystem. 00037 * 00038 * <h2>Objective</h2> 00039 * Objective of the test module is to cover 100% of the @ref semaphores code. 00040 * 00041 * <h2>Preconditions</h2> 00042 * The module requires the following kernel options: 00043 * - @p CH_USE_SEMAPHORES 00044 * . 00045 * In case some of the required options are not enabled then some or all tests 00046 * may be skipped. 00047 * 00048 * <h2>Test Cases</h2> 00049 * - @subpage test_sem_001 00050 * - @subpage test_sem_002 00051 * - @subpage test_sem_003 00052 * . 00053 * @file testsem.c 00054 * @brief Semaphores test source file 00055 * @file testsem.h 00056 * @brief Semaphores test header file 00057 */ 00058 00059 #if CH_USE_SEMAPHORES 00060 00061 #define ALLOWED_DELAY MS2ST(5) 00062 00063 /* 00064 * Note, the static initializers are not really required because the 00065 * variables are explicitly initialized in each test case. It is done in order 00066 * to test the macros. 00067 */ 00068 static SEMAPHORE_DECL(sem1, 0); 00069 00070 /** 00071 * @page test_sem_001 Enqueuing test 00072 * 00073 * <h2>Description</h2> 00074 * Five threads with randomized priorities are enqueued to a semaphore then 00075 * awakened one at time.<br> 00076 * The test expects that the threads reach their goal in FIFO order or 00077 * priority order depending on the CH_USE_SEMAPHORES_PRIORITY configuration 00078 * setting. 00079 */ 00080 static char *sem1_gettest(void) { 00081 00082 return "Semaphores, enqueuing"; 00083 } 00084 00085 static void sem1_setup(void) { 00086 00087 chSemInit(&sem1, 0); 00088 } 00089 00090 static msg_t thread1(void *p) { 00091 00092 chSemWait(&sem1); 00093 test_emit_token(*(char *)p); 00094 return 0; 00095 } 00096 00097 static void sem1_execute(void) { 00098 00099 threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriority()+5, thread1, "A"); 00100 threads[1] = chThdCreateStatic(wa[1], WA_SIZE, chThdGetPriority()+1, thread1, "B"); 00101 threads[2] = chThdCreateStatic(wa[2], WA_SIZE, chThdGetPriority()+3, thread1, "C"); 00102 threads[3] = chThdCreateStatic(wa[3], WA_SIZE, chThdGetPriority()+4, thread1, "D"); 00103 threads[4] = chThdCreateStatic(wa[4], WA_SIZE, chThdGetPriority()+2, thread1, "E"); 00104 chSemSignal(&sem1); 00105 chSemSignal(&sem1); 00106 chSemSignal(&sem1); 00107 chSemSignal(&sem1); 00108 chSemSignal(&sem1); 00109 test_wait_threads(); 00110 #if CH_USE_SEMAPHORES_PRIORITY 00111 test_assert_sequence(1, "ADCEB"); 00112 #else 00113 test_assert_sequence(1, "ABCDE"); 00114 #endif 00115 } 00116 00117 /** 00118 * @page test_sem_002 Timeout test 00119 * 00120 * <h2>Description</h2> 00121 * The three possible semaphore waiting modes (do not wait, wait with timeout, 00122 * wait without timeout) are explored.<br> 00123 * The test expects that the semaphore wait function returns the correct value 00124 * in each of the above scenario and that the semaphore structure status is 00125 * correct after each operation. 00126 */ 00127 const struct testcase testsem1 = { 00128 sem1_gettest, 00129 sem1_setup, 00130 NULL, 00131 sem1_execute 00132 }; 00133 00134 static char *sem2_gettest(void) { 00135 00136 return "Semaphores, timeout"; 00137 } 00138 00139 static void sem2_setup(void) { 00140 00141 chSemInit(&sem1, 0); 00142 } 00143 00144 static msg_t thread2(void *p) { 00145 00146 (void)p; 00147 chThdSleepMilliseconds(50); 00148 chSysLock(); 00149 chSemSignalI(&sem1); /* For coverage reasons */ 00150 chSchRescheduleS(); 00151 chSysUnlock(); 00152 return 0; 00153 } 00154 00155 static void sem2_execute(void) { 00156 int i; 00157 systime_t target_time; 00158 msg_t msg; 00159 00160 /* 00161 * Testing special case TIME_IMMEDIATE. 00162 */ 00163 msg = chSemWaitTimeout(&sem1, TIME_IMMEDIATE); 00164 test_assert(1, msg == RDY_TIMEOUT, "wrong wake-up message"); 00165 test_assert(2, isempty(&sem1.s_queue), "queue not empty"); 00166 test_assert(3, sem1.s_cnt == 0, "counter not zero"); 00167 00168 /* 00169 * Testing not timeout condition. 00170 */ 00171 threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriority() - 1, 00172 thread2, 0); 00173 msg = chSemWaitTimeout(&sem1, MS2ST(500)); 00174 test_wait_threads(); 00175 test_assert(4, msg == RDY_OK, "wrong wake-up message"); 00176 test_assert(5, isempty(&sem1.s_queue), "queue not empty"); 00177 test_assert(6, sem1.s_cnt == 0, "counter not zero"); 00178 00179 /* 00180 * Testing timeout condition. 00181 */ 00182 test_wait_tick(); 00183 target_time = chTimeNow() + MS2ST(5 * 500); 00184 for (i = 0; i < 5; i++) { 00185 test_emit_token('A' + i); 00186 msg = chSemWaitTimeout(&sem1, MS2ST(500)); 00187 test_assert(7, msg == RDY_TIMEOUT, "wrong wake-up message"); 00188 test_assert(8, isempty(&sem1.s_queue), "queue not empty"); 00189 test_assert(9, sem1.s_cnt == 0, "counter not zero"); 00190 } 00191 test_assert_sequence(10, "ABCDE"); 00192 test_assert_time_window(11, target_time, target_time + ALLOWED_DELAY); 00193 } 00194 00195 const struct testcase testsem2 = { 00196 sem2_gettest, 00197 sem2_setup, 00198 NULL, 00199 sem2_execute 00200 }; 00201 00202 #if CH_USE_SEMSW 00203 /** 00204 * @page test_sem_003 Atomic signal-wait test 00205 * 00206 * <h2>Description</h2> 00207 * This test case explicitly address the @p chSemWaitSignal() function. A 00208 * thread is created that performs a wait and a signal operations. 00209 * The tester thread is awakened from an atomic wait/signal operation.<br> 00210 * The test expects that the semaphore wait function returns the correct value 00211 * in each of the above scenario and that the semaphore structure status is 00212 * correct after each operation. 00213 */ 00214 00215 static char *sem3_gettest(void) { 00216 00217 return "Semaphores, atomic signal-wait"; 00218 } 00219 00220 static void sem3_setup(void) { 00221 00222 chSemInit(&sem1, 0); 00223 } 00224 00225 static msg_t thread3(void *p) { 00226 00227 (void)p; 00228 chSemWait(&sem1); 00229 chSemSignal(&sem1); 00230 return 0; 00231 } 00232 00233 static void sem3_execute(void) { 00234 00235 threads[0] = chThdCreateStatic(wa[0], WA_SIZE, chThdGetPriority()+1, thread3, 0); 00236 chSemSignalWait(&sem1, &sem1); 00237 test_assert(1, isempty(&sem1.s_queue), "queue not empty"); 00238 test_assert(2, sem1.s_cnt == 0, "counter not zero"); 00239 00240 chSemSignalWait(&sem1, &sem1); 00241 test_assert(3, isempty(&sem1.s_queue), "queue not empty"); 00242 test_assert(4, sem1.s_cnt == 0, "counter not zero"); 00243 } 00244 00245 const struct testcase testsem3 = { 00246 sem3_gettest, 00247 sem3_setup, 00248 NULL, 00249 sem3_execute 00250 }; 00251 #endif /* CH_USE_SEMSW */ 00252 #endif /* CH_USE_SEMAPHORES */ 00253 00254 /** 00255 * @brief Test sequence for semaphores. 00256 */ 00257 const struct testcase * const patternsem[] = { 00258 #if CH_USE_SEMAPHORES 00259 &testsem1, 00260 &testsem2, 00261 #if CH_USE_SEMSW 00262 &testsem3, 00263 #endif 00264 #endif 00265 NULL 00266 };