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.
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 17:34:58 by
