Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: mbed-os-example-blinky-gr-lychee GR-Boads_Camera_sample GR-Boards_Audio_Recoder GR-Boads_Camera_DisplayApp ... 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 _finished = false; 00048 _dynamic_stack = (stack_pointer == NULL); 00049 00050 #if defined(__MBED_CMSIS_RTOS_CA9) || defined(__MBED_CMSIS_RTOS_CM) 00051 _thread_def.tpriority = priority; 00052 _thread_def.stacksize = stack_size; 00053 _thread_def.stack_pointer = (uint32_t*)stack_pointer; 00054 #endif 00055 } 00056 00057 void Thread::constructor(Callback<void()> task, 00058 osPriority priority, uint32_t stack_size, unsigned char *stack_pointer) { 00059 constructor(priority, stack_size, stack_pointer); 00060 00061 switch (start(task)) { 00062 case osErrorResource: 00063 error("OS ran out of threads!\n"); 00064 break; 00065 case osErrorParameter: 00066 error("Thread already running!\n"); 00067 break; 00068 case osErrorNoMemory: 00069 error("Error allocating the stack memory\n"); 00070 default: 00071 break; 00072 } 00073 } 00074 00075 osStatus Thread::start(Callback<void()> task) { 00076 _mutex.lock(); 00077 00078 if ((_tid != 0) || _finished) { 00079 _mutex.unlock(); 00080 return osErrorParameter; 00081 } 00082 00083 #if defined(__MBED_CMSIS_RTOS_CA9) || defined(__MBED_CMSIS_RTOS_CM) 00084 _thread_def.pthread = Thread::_thunk; 00085 if (_thread_def.stack_pointer == NULL) { 00086 _thread_def.stack_pointer = new uint32_t[_thread_def.stacksize/sizeof(uint32_t)]; 00087 MBED_ASSERT(_thread_def.stack_pointer != NULL); 00088 } 00089 00090 //Fill the stack with a magic word for maximum usage checking 00091 for (uint32_t i = 0; i < (_thread_def.stacksize / sizeof(uint32_t)); i++) { 00092 _thread_def.stack_pointer[i] = 0xE25A2EA5; 00093 } 00094 #endif 00095 _task = task; 00096 _tid = osThreadCreate(&_thread_def, this); 00097 if (_tid == NULL) { 00098 if (_dynamic_stack) { 00099 delete[] (_thread_def.stack_pointer); 00100 _thread_def.stack_pointer = (uint32_t*)NULL; 00101 } 00102 _mutex.unlock(); 00103 _join_sem.release(); 00104 return osErrorResource; 00105 } 00106 00107 _mutex.unlock(); 00108 return osOK; 00109 } 00110 00111 osStatus Thread::terminate() { 00112 osStatus ret; 00113 _mutex.lock(); 00114 00115 // Set the Thread's tid to NULL and 00116 // release the semaphore before terminating 00117 // since this thread could be terminating itself 00118 osThreadId local_id = _tid; 00119 _join_sem.release(); 00120 _tid = (osThreadId)NULL; 00121 _finished = true; 00122 00123 ret = osThreadTerminate(local_id); 00124 00125 _mutex.unlock(); 00126 return ret; 00127 } 00128 00129 osStatus Thread::join() { 00130 int32_t ret = _join_sem.wait(); 00131 if (ret < 0) { 00132 return osErrorOS; 00133 } 00134 00135 // The semaphore has been released so this thread is being 00136 // terminated or has been terminated. Once the mutex has 00137 // been locked it is ensured that the thread is deleted. 00138 _mutex.lock(); 00139 MBED_ASSERT(NULL == _tid); 00140 _mutex.unlock(); 00141 00142 // Release sem so any other threads joining this thread wake up 00143 _join_sem.release(); 00144 return osOK; 00145 } 00146 00147 osStatus Thread::set_priority(osPriority priority) { 00148 osStatus ret; 00149 _mutex.lock(); 00150 00151 ret = osThreadSetPriority(_tid, priority); 00152 00153 _mutex.unlock(); 00154 return ret; 00155 } 00156 00157 osPriority Thread::get_priority() { 00158 osPriority ret; 00159 _mutex.lock(); 00160 00161 ret = osThreadGetPriority(_tid); 00162 00163 _mutex.unlock(); 00164 return ret; 00165 } 00166 00167 int32_t Thread::signal_set(int32_t signals) { 00168 // osSignalSet is thread safe as long as the underlying 00169 // thread does not get terminated or return from main 00170 return osSignalSet(_tid, signals); 00171 } 00172 00173 int32_t Thread::signal_clr(int32_t signals) { 00174 // osSignalClear is thread safe as long as the underlying 00175 // thread does not get terminated or return from main 00176 return osSignalClear(_tid, signals); 00177 } 00178 00179 Thread::State Thread::get_state() { 00180 #if !defined(__MBED_CMSIS_RTOS_CA9) && !defined(__MBED_CMSIS_RTOS_CM) 00181 #ifdef CMSIS_OS_RTX 00182 State status; 00183 _mutex.lock(); 00184 00185 if (_tid != NULL) { 00186 status = (State)_thread_def.tcb.state; 00187 } else if (_finished) { 00188 status = Deleted; 00189 } else { 00190 status = Inactive; 00191 } 00192 00193 _mutex.unlock(); 00194 return status; 00195 #endif 00196 #else 00197 State status = Deleted; 00198 _mutex.lock(); 00199 00200 if (_tid != NULL) { 00201 status = (State)osThreadGetState(_tid); 00202 } 00203 00204 _mutex.unlock(); 00205 return status; 00206 #endif 00207 } 00208 00209 uint32_t Thread::stack_size() { 00210 #ifndef __MBED_CMSIS_RTOS_CA9 00211 #if defined(CMSIS_OS_RTX) && !defined(__MBED_CMSIS_RTOS_CM) 00212 uint32_t size = 0; 00213 _mutex.lock(); 00214 00215 if (_tid != NULL) { 00216 size = _thread_def.tcb.priv_stack; 00217 } 00218 00219 _mutex.unlock(); 00220 return size; 00221 #else 00222 uint32_t size = 0; 00223 _mutex.lock(); 00224 00225 if (_tid != NULL) { 00226 P_TCB tcb = rt_tid2ptcb(_tid); 00227 size = tcb->priv_stack; 00228 } 00229 00230 _mutex.unlock(); 00231 return size; 00232 #endif 00233 #else 00234 return 0; 00235 #endif 00236 } 00237 00238 uint32_t Thread::free_stack() { 00239 #ifndef __MBED_CMSIS_RTOS_CA9 00240 #if defined(CMSIS_OS_RTX) && !defined(__MBED_CMSIS_RTOS_CM) 00241 uint32_t size = 0; 00242 _mutex.lock(); 00243 00244 if (_tid != NULL) { 00245 uint32_t bottom = (uint32_t)_thread_def.tcb.stack; 00246 size = _thread_def.tcb.tsk_stack - bottom; 00247 } 00248 00249 _mutex.unlock(); 00250 return size; 00251 #else 00252 uint32_t size = 0; 00253 _mutex.lock(); 00254 00255 if (_tid != NULL) { 00256 P_TCB tcb = rt_tid2ptcb(_tid); 00257 uint32_t bottom = (uint32_t)tcb->stack; 00258 size = tcb->tsk_stack - bottom; 00259 } 00260 00261 _mutex.unlock(); 00262 return size; 00263 #endif 00264 #else 00265 return 0; 00266 #endif 00267 } 00268 00269 uint32_t Thread::used_stack() { 00270 #ifndef __MBED_CMSIS_RTOS_CA9 00271 #if defined(CMSIS_OS_RTX) && !defined(__MBED_CMSIS_RTOS_CM) 00272 uint32_t size = 0; 00273 _mutex.lock(); 00274 00275 if (_tid != NULL) { 00276 uint32_t top = (uint32_t)_thread_def.tcb.stack + _thread_def.tcb.priv_stack; 00277 size = top - _thread_def.tcb.tsk_stack; 00278 } 00279 00280 _mutex.unlock(); 00281 return size; 00282 #else 00283 uint32_t size = 0; 00284 _mutex.lock(); 00285 00286 if (_tid != NULL) { 00287 P_TCB tcb = rt_tid2ptcb(_tid); 00288 uint32_t top = (uint32_t)tcb->stack + tcb->priv_stack; 00289 size = top - tcb->tsk_stack; 00290 } 00291 00292 _mutex.unlock(); 00293 return size; 00294 #endif 00295 #else 00296 return 0; 00297 #endif 00298 } 00299 00300 uint32_t Thread::max_stack() { 00301 #ifndef __MBED_CMSIS_RTOS_CA9 00302 #if defined(CMSIS_OS_RTX) && !defined(__MBED_CMSIS_RTOS_CM) 00303 uint32_t size = 0; 00304 _mutex.lock(); 00305 00306 if (_tid != NULL) { 00307 uint32_t high_mark = 0; 00308 while (_thread_def.tcb.stack[high_mark] == 0xE25A2EA5) 00309 high_mark++; 00310 size = _thread_def.tcb.priv_stack - (high_mark * 4); 00311 } 00312 00313 _mutex.unlock(); 00314 return size; 00315 #else 00316 uint32_t size = 0; 00317 _mutex.lock(); 00318 00319 if (_tid != NULL) { 00320 P_TCB tcb = rt_tid2ptcb(_tid); 00321 uint32_t high_mark = 0; 00322 while (tcb->stack[high_mark] == 0xE25A2EA5) 00323 high_mark++; 00324 size = tcb->priv_stack - (high_mark * 4); 00325 } 00326 00327 _mutex.unlock(); 00328 return size; 00329 #endif 00330 #else 00331 return 0; 00332 #endif 00333 } 00334 00335 osEvent Thread::signal_wait(int32_t signals, uint32_t millisec) { 00336 return osSignalWait(signals, millisec); 00337 } 00338 00339 osStatus Thread::wait(uint32_t millisec) { 00340 return osDelay(millisec); 00341 } 00342 00343 osStatus Thread::yield() { 00344 return osThreadYield(); 00345 } 00346 00347 osThreadId Thread::gettid() { 00348 return osThreadGetId(); 00349 } 00350 00351 void Thread::attach_idle_hook(void (*fptr)(void)) { 00352 rtos_attach_idle_hook(fptr); 00353 } 00354 00355 void Thread::attach_terminate_hook(void (*fptr)(osThreadId id)) { 00356 terminate_hook = fptr; 00357 } 00358 00359 Thread::~Thread() { 00360 // terminate is thread safe 00361 terminate(); 00362 #ifdef __MBED_CMSIS_RTOS_CM 00363 if (_dynamic_stack) { 00364 delete[] (_thread_def.stack_pointer); 00365 _thread_def.stack_pointer = (uint32_t*)NULL; 00366 } 00367 #endif 00368 } 00369 00370 void Thread::_thunk(const void * thread_ptr) 00371 { 00372 Thread *t = (Thread*)thread_ptr; 00373 t->_task(); 00374 t->_mutex.lock(); 00375 t->_tid = (osThreadId)NULL; 00376 t->_finished = true; 00377 t->_join_sem.release(); 00378 // rtos will release the mutex automatically 00379 } 00380 00381 }
Generated on Tue Jul 12 2022 11:02:33 by
1.7.2