Official mbed Real Time Operating System based on the RTX implementation of the CMSIS-RTOS API open standard.
Dependents: denki-yohou_b TestY201 Network-RTOS NTPClient_HelloWorld ... more
Thread.cpp
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2006-2012 ARM Limited 00003 * 00004 * Permission is hereby granted, free of charge, to any person obtaining a copy 00005 * of this software and associated documentation files (the "Software"), to deal 00006 * in the Software without restriction, including without limitation the rights 00007 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00008 * copies of the Software, and to permit persons to whom the Software is 00009 * furnished to do so, subject to the following conditions: 00010 * 00011 * The above copyright notice and this permission notice shall be included in 00012 * all copies or substantial portions of the Software. 00013 * 00014 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00015 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00016 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00017 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00018 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00019 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 00020 * SOFTWARE. 00021 */ 00022 #include "rtos/Thread.h" 00023 00024 #include "mbed.h" 00025 #include "rtos/rtos_idle.h" 00026 00027 // rt_tid2ptcb is an internal function which we exposed to get TCB for thread id 00028 #undef NULL //Workaround for conflicting macros in rt_TypeDef.h and stdio.h 00029 #include "rt_TypeDef.h" 00030 00031 extern "C" P_TCB rt_tid2ptcb(osThreadId thread_id); 00032 00033 00034 static void (*terminate_hook)(osThreadId id) = 0; 00035 extern "C" void thread_terminate_hook(osThreadId id) 00036 { 00037 if (terminate_hook != (void (*)(osThreadId))NULL) { 00038 terminate_hook(id); 00039 } 00040 } 00041 00042 namespace rtos { 00043 00044 void Thread::constructor(osPriority priority, 00045 uint32_t stack_size, unsigned char *stack_pointer) { 00046 _tid = 0; 00047 _dynamic_stack = (stack_pointer == NULL); 00048 00049 #if defined(__MBED_CMSIS_RTOS_CA9) || defined(__MBED_CMSIS_RTOS_CM) 00050 _thread_def.tpriority = priority; 00051 _thread_def.stacksize = stack_size; 00052 _thread_def.stack_pointer = (uint32_t*)stack_pointer; 00053 #endif 00054 } 00055 00056 void Thread::constructor(Callback<void()> task, 00057 osPriority priority, uint32_t stack_size, unsigned char *stack_pointer) { 00058 constructor(priority, stack_size, stack_pointer); 00059 00060 switch (start(task)) { 00061 case osErrorResource: 00062 error("OS ran out of threads!\n"); 00063 break; 00064 case osErrorParameter: 00065 error("Thread already running!\n"); 00066 break; 00067 case osErrorNoMemory: 00068 error("Error allocating the stack memory\n"); 00069 default: 00070 break; 00071 } 00072 } 00073 00074 osStatus Thread::start(Callback<void()> task) { 00075 _mutex.lock(); 00076 00077 if (_tid != 0) { 00078 _mutex.unlock(); 00079 return osErrorParameter; 00080 } 00081 00082 #if defined(__MBED_CMSIS_RTOS_CA9) || defined(__MBED_CMSIS_RTOS_CM) 00083 _thread_def.pthread = Thread::_thunk; 00084 if (_thread_def.stack_pointer == NULL) { 00085 _thread_def.stack_pointer = new uint32_t[_thread_def.stacksize/sizeof(uint32_t)]; 00086 MBED_ASSERT(_thread_def.stack_pointer != NULL); 00087 } 00088 00089 //Fill the stack with a magic word for maximum usage checking 00090 for (uint32_t i = 0; i < (_thread_def.stacksize / sizeof(uint32_t)); i++) { 00091 _thread_def.stack_pointer[i] = 0xE25A2EA5; 00092 } 00093 #endif 00094 _task = task; 00095 _tid = osThreadCreate(&_thread_def, this); 00096 if (_tid == NULL) { 00097 if (_dynamic_stack) { 00098 delete[] (_thread_def.stack_pointer); 00099 _thread_def.stack_pointer = (uint32_t*)NULL; 00100 } 00101 _mutex.unlock(); 00102 _join_sem.release(); 00103 return osErrorResource; 00104 } 00105 00106 _mutex.unlock(); 00107 return osOK; 00108 } 00109 00110 osStatus Thread::terminate() { 00111 osStatus ret; 00112 _mutex.lock(); 00113 00114 // Set the Thread's tid to NULL and 00115 // release the semaphore before terminating 00116 // since this thread could be terminating itself 00117 osThreadId local_id = _tid; 00118 _join_sem.release(); 00119 _tid = (osThreadId)NULL; 00120 00121 ret = osThreadTerminate(local_id); 00122 00123 _mutex.unlock(); 00124 return ret; 00125 } 00126 00127 osStatus Thread::join() { 00128 int32_t ret = _join_sem.wait(); 00129 if (ret < 0) { 00130 return osErrorOS; 00131 } 00132 00133 // The semaphore has been released so this thread is being 00134 // terminated or has been terminated. Once the mutex has 00135 // been locked it is ensured that the thread is deleted. 00136 _mutex.lock(); 00137 MBED_ASSERT(NULL == _tid); 00138 _mutex.unlock(); 00139 00140 // Release sem so any other threads joining this thread wake up 00141 _join_sem.release(); 00142 return osOK; 00143 } 00144 00145 osStatus Thread::set_priority(osPriority priority) { 00146 osStatus ret; 00147 _mutex.lock(); 00148 00149 ret = osThreadSetPriority(_tid, priority); 00150 00151 _mutex.unlock(); 00152 return ret; 00153 } 00154 00155 osPriority Thread::get_priority() { 00156 osPriority ret; 00157 _mutex.lock(); 00158 00159 ret = osThreadGetPriority(_tid); 00160 00161 _mutex.unlock(); 00162 return ret; 00163 } 00164 00165 int32_t Thread::signal_set(int32_t signals) { 00166 // osSignalSet is thread safe as long as the underlying 00167 // thread does not get terminated or return from main 00168 return osSignalSet(_tid, signals); 00169 } 00170 00171 int32_t Thread::signal_clr(int32_t signals) { 00172 // osSignalClear is thread safe as long as the underlying 00173 // thread does not get terminated or return from main 00174 return osSignalClear(_tid, signals); 00175 } 00176 00177 Thread::State Thread::get_state() { 00178 #if !defined(__MBED_CMSIS_RTOS_CA9) && !defined(__MBED_CMSIS_RTOS_CM) 00179 #ifdef CMSIS_OS_RTX 00180 State status = Deleted; 00181 _mutex.lock(); 00182 00183 if (_tid != NULL) { 00184 status = (State)_thread_def.tcb.state; 00185 } 00186 00187 _mutex.unlock(); 00188 return status; 00189 #endif 00190 #else 00191 State status = Deleted; 00192 _mutex.lock(); 00193 00194 if (_tid != NULL) { 00195 status = (State)osThreadGetState(_tid); 00196 } 00197 00198 _mutex.unlock(); 00199 return status; 00200 #endif 00201 } 00202 00203 uint32_t Thread::stack_size() { 00204 #ifndef __MBED_CMSIS_RTOS_CA9 00205 #if defined(CMSIS_OS_RTX) && !defined(__MBED_CMSIS_RTOS_CM) 00206 uint32_t size = 0; 00207 _mutex.lock(); 00208 00209 if (_tid != NULL) { 00210 size = _thread_def.tcb.priv_stack; 00211 } 00212 00213 _mutex.unlock(); 00214 return size; 00215 #else 00216 uint32_t size = 0; 00217 _mutex.lock(); 00218 00219 if (_tid != NULL) { 00220 P_TCB tcb = rt_tid2ptcb(_tid); 00221 size = tcb->priv_stack; 00222 } 00223 00224 _mutex.unlock(); 00225 return size; 00226 #endif 00227 #else 00228 return 0; 00229 #endif 00230 } 00231 00232 uint32_t Thread::free_stack() { 00233 #ifndef __MBED_CMSIS_RTOS_CA9 00234 #if defined(CMSIS_OS_RTX) && !defined(__MBED_CMSIS_RTOS_CM) 00235 uint32_t size = 0; 00236 _mutex.lock(); 00237 00238 if (_tid != NULL) { 00239 uint32_t bottom = (uint32_t)_thread_def.tcb.stack; 00240 size = _thread_def.tcb.tsk_stack - bottom; 00241 } 00242 00243 _mutex.unlock(); 00244 return size; 00245 #else 00246 uint32_t size = 0; 00247 _mutex.lock(); 00248 00249 if (_tid != NULL) { 00250 P_TCB tcb = rt_tid2ptcb(_tid); 00251 uint32_t bottom = (uint32_t)tcb->stack; 00252 size = tcb->tsk_stack - bottom; 00253 } 00254 00255 _mutex.unlock(); 00256 return size; 00257 #endif 00258 #else 00259 return 0; 00260 #endif 00261 } 00262 00263 uint32_t Thread::used_stack() { 00264 #ifndef __MBED_CMSIS_RTOS_CA9 00265 #if defined(CMSIS_OS_RTX) && !defined(__MBED_CMSIS_RTOS_CM) 00266 uint32_t size = 0; 00267 _mutex.lock(); 00268 00269 if (_tid != NULL) { 00270 uint32_t top = (uint32_t)_thread_def.tcb.stack + _thread_def.tcb.priv_stack; 00271 size = top - _thread_def.tcb.tsk_stack; 00272 } 00273 00274 _mutex.unlock(); 00275 return size; 00276 #else 00277 uint32_t size = 0; 00278 _mutex.lock(); 00279 00280 if (_tid != NULL) { 00281 P_TCB tcb = rt_tid2ptcb(_tid); 00282 uint32_t top = (uint32_t)tcb->stack + tcb->priv_stack; 00283 size = top - tcb->tsk_stack; 00284 } 00285 00286 _mutex.unlock(); 00287 return size; 00288 #endif 00289 #else 00290 return 0; 00291 #endif 00292 } 00293 00294 uint32_t Thread::max_stack() { 00295 #ifndef __MBED_CMSIS_RTOS_CA9 00296 #if defined(CMSIS_OS_RTX) && !defined(__MBED_CMSIS_RTOS_CM) 00297 uint32_t size = 0; 00298 _mutex.lock(); 00299 00300 if (_tid != NULL) { 00301 uint32_t high_mark = 0; 00302 while (_thread_def.tcb.stack[high_mark] == 0xE25A2EA5) 00303 high_mark++; 00304 size = _thread_def.tcb.priv_stack - (high_mark * 4); 00305 } 00306 00307 _mutex.unlock(); 00308 return size; 00309 #else 00310 uint32_t size = 0; 00311 _mutex.lock(); 00312 00313 if (_tid != NULL) { 00314 P_TCB tcb = rt_tid2ptcb(_tid); 00315 uint32_t high_mark = 0; 00316 while (tcb->stack[high_mark] == 0xE25A2EA5) 00317 high_mark++; 00318 size = tcb->priv_stack - (high_mark * 4); 00319 } 00320 00321 _mutex.unlock(); 00322 return size; 00323 #endif 00324 #else 00325 return 0; 00326 #endif 00327 } 00328 00329 osEvent Thread::signal_wait(int32_t signals, uint32_t millisec) { 00330 return osSignalWait(signals, millisec); 00331 } 00332 00333 osStatus Thread::wait(uint32_t millisec) { 00334 return osDelay(millisec); 00335 } 00336 00337 osStatus Thread::yield() { 00338 return osThreadYield(); 00339 } 00340 00341 osThreadId Thread::gettid() { 00342 return osThreadGetId(); 00343 } 00344 00345 void Thread::attach_idle_hook(void (*fptr)(void)) { 00346 rtos_attach_idle_hook(fptr); 00347 } 00348 00349 void Thread::attach_terminate_hook(void (*fptr)(osThreadId id)) { 00350 terminate_hook = fptr; 00351 } 00352 00353 Thread::~Thread() { 00354 // terminate is thread safe 00355 terminate(); 00356 #ifdef __MBED_CMSIS_RTOS_CM 00357 if (_dynamic_stack) { 00358 delete[] (_thread_def.stack_pointer); 00359 _thread_def.stack_pointer = (uint32_t*)NULL; 00360 } 00361 #endif 00362 } 00363 00364 void Thread::_thunk(const void * thread_ptr) 00365 { 00366 Thread *t = (Thread*)thread_ptr; 00367 t->_task(); 00368 t->_mutex.lock(); 00369 t->_tid = (osThreadId)NULL; 00370 t->_join_sem.release(); 00371 // rtos will release the mutex automatically 00372 } 00373 00374 }
Generated on Tue Jul 12 2022 11:27:30 by 1.7.2